Posted: June 7th, 2008 | Author: tolleiv | Tags: compression, extracting, php, zip | Comments Off
The __halt_compiler(); function in php enables to store some additional data in a php-file without blowing up the memory. A very nice possibility is to use this for a self-extracting php file as installation-packages of your php application.
A wile ago I created a script which automatically creates such a archive and I think you might like it….for the impatient ones: Download / Download as Zip.
Before I start to show how the entire script works I’d like to show you a small example so that you can see how the __halt_compiler(); function can be used to store some data at the end of a file:
$fp = fopen(__FILE__, ‘r’);
fseek($fp, __COMPILER_HALT_OFFSET__);
$i=0;
while($buffer = fgets($fp)) {
echo ($i++). “:”. $buffer.“
”;
};
__HALT_COMPILER();Line 1
Line 2
Line 3
Last line
The first thing you might mention is, that the closing “?>” is missing, but since the function-name is nearly self-explaining you should realize very fast what the output of the script might be
If that’s working the question is what’s needed for a script which is meant to create and extract a archive? The first thing is a way to create the archive itself. I used the PHP-builtin ZipArchive for that. The second thing is a script which is able to extract this archiv (using the method show above). That’s handled by the following snippet:
try {
$zipfilename = md5(time()).‘archive.zip’; //remove with tempname()
$fp_tmp = fopen($zipfilename,‘w’);
$fp_cur = fopen(__FILE__, ‘r’);
fseek($fp_cur, __COMPILER_HALT_OFFSET__);
$i=0;
while($buffer = fread($fp_cur,10240)) {
fwrite($fp_tmp,$buffer);
}
fclose($fp_cur);
fclose($fp_tmp);
$zipfile = new ZipArchive();
if($zipfile->open($zipfilename)===true) {
if(!$zipfile->extractTo(‘.’)) throw new Exception(‘extraction failed…’);
} else throw new Exception(‘reading archive failed’);
$zipfile->close();
unlink($zipfilename);
} catch (Exception $e) {
printf(“Error:
%s%s>”,$e->getMessage(),$e->getTraceAsString());
};
__HALT_COMPILER();[zipdata is appended here later]
As you see that’s no rocket-science just read the data, pass it to the ZipArchive object via a temporary file and extract the archive.
If that’s working then you need a script which brings the PHP extraction script and the zip-data together. And since we want to have a single script for the creation of our self extracting php archive, it would be very odd if we’d place the “template” for the extraction in a separate file. That’s the reason why I just use the same method as above for this script and this time the data is php code instead of zip-data:
try {
$sourcefolder = ‘compressthis/’; // maybe you want to get this via CLI argument …
$targetname = ‘phparchive.php’;
$zipfilename = md5(time()).‘archive.zip’; // replace with tempname()
// create a archive from the submitted folder
$zipfile = new ZipArchive();
$zipfile->open($zipfilename,ZipArchive::CREATE);
addFiles2Zip($zipfile,$sourcefolder,true);
$zipfile->close();
// compile the selfextracting php-archive
$fp_dest =fopen($targetname,‘w’);
$fp_cur = fopen(__FILE__, ‘r’);
fseek($fp_cur, __COMPILER_HALT_OFFSET__);
$i=0;
while($buffer = fgets($fp_cur)) {
fwrite($fp_dest,$buffer);
}
fclose($fp_cur);
$fp_zip = fopen($zipfilename,‘r’);
while($buffer = fread($fp_zip,10240)) {
fwrite($fp_dest,$buffer);
}
fclose($fp_zip);
fclose($fp_dest);
unlink($zipfilename);
} catch (Exception $e) {
echo $e->getTraceAsString();
}
function
addFiles2Zip(ZipArchive $zip,$path,$removeFirstFolder=false) {
$d = opendir($path);
while($file = readdir($d)) {
if ($file == “.” || $file == “..”) continue;
$curfile=($removeFirstFolder)?substr($path.$file,strpos($path,‘/’)+1):$path.$file;
if(is_dir($path.$file)) {
$zip->addEmptyDir($curfile);
addFiles2Zip($zip,$path.$file.‘/’,$removeFirstFolder);
} else {
$zip->addFile($path.$file,$curfile);
}
}
closedir($d);
}
__HALT_COMPILER();[the script shown above]
If you all wrap up into a single script the you’ll have something like the script I already mentioned.
I think that it could be useful to have a version with a better error-handling and maybe also some CLI functions so that there’s no need to edit the script itself everytime… I’ll keep you updated as soon as I have something like that
The __halt_compiler(); function in php enables to store some additional data in a php-file without blowing up the memory. A very nice possibility is to use this for a self-extracting php file as installation-packages of your php application.
A wile ago I created a script which automatically creates such a archive and I think you might like it....for the impatient ones: Download / Download as Zip.
Before I start to show how the entire script works I'd like to show you a small example so that you can see how the __halt_compiler(); function can be used to store some data at the end of a file:
$fp = fopen(__FILE__, ‘r’);
fseek($fp, __COMPILER_HALT_OFFSET__);
$i=0;
while($buffer = fgets($fp)) {
echo ($i++). “:”. $buffer.“”;
};
__HALT_COMPILER();Line 1
Line 2
Line 3
Last line
The first thing you might mention is, that the closing "?>" is missing, but since the function-name is nearly self-explaining you should realize very fast what the output of the script might be ;)
I
Posted: June 2nd, 2008 | Author: tolleiv | Tags: php | Comments Off
If you’re still wondering whether the single- or double quotes are processed faster in PHP you might want to look at phpbench.com. They don’t provide any ground breaking new insights, but they show in a very nice way what’s best pratice when it comes to arrays, strings and loops…
If you're still wondering whether the single- or double quotes are processed faster in PHP you might want to look at phpbench.com. They don't provide any ground breaking new insights, but they show in a very nice way what's best pratice when it comes to arrays, strings and loops...
Posted: May 30th, 2008 | Author: tolleiv | Tags: behavioral, pattern, php, value object | Comments Off
This metaphor does not fit completely, and the “Money-Example” is omnipresent, but I really like the pattern and so that’s the story:
Let’s say you have your grannies recipe for a chocolate cookie and you want to keep this in mind, but also you like to somehow experiment with some new or different ingredients. Normally you just keep in mind what you changed and later you write down the new recipe. But from time to time you might want to compare the two recipes or maybe you want to make cookies with the new and the changed recipes. In this situation it’s really good to have both written down on paper.
In the world of OOP you could think of a solution using the Memento-Pattern but this doesn’t really fit the situation and it’s also some kind of overhead. That’s the reason why the Value Object is the pattern of my choice.
So let’s look at the recipes again – we want to add and remove ingredients without modifying the original recipe and we want to compare the resulting recipes. We don’t need to track a special identity of our recipes since we’re only “collecting” ingredients.
The idea of the Value Object is that every every method which somehow transforms the state of a object always returns a new object and the old object stays untouched. Whenever needed you should also implement a method to compare objects, I must concede that the common “Money Example” shows much better when that’s needed …
Another edge of this pattern in PHP is that you can use method-chaining to perform multiple actions within a single line of code. So just have a look at the example you will like it’s taste
class Recipe {
protected $ingredients;
public function __construct($ingred=”) {
$this->ingredients = implode(‘,’,array_unique(explode(‘,’,$ingred)));
}
public function addIncredient($ingred=”) {
return new Recipe($this->ingredients.‘,’.$ingred);
}
public function removeIncredien($ingred=”) {
return new Recipe(preg_replace(‘/,{0,1}’.$ingred.‘,{0,1}/’,”,$this->ingredients.‘,’));
}
public function printIncredients() {
echo str_replace(‘,’,‘
’,$this->ingredients);
}
public function equals(Recipe $recipe) {
return (strcmp($this->ingredients,$recipe->ingredients)===0)?true:false;
}
}
$granniesRecipe = new Recipe(‘flour,baking soda,sugar,salt,butter,vanilla,chocolate’);
$aNewRecipe = $granniesRecipe->addIncredient(‘lemon’);
$coconutRecipe = $granniesRecipe->removeIncredien(‘chocolate’)->addIncredient(‘coconut’);
// check if that worked:
echo ‘
Grannies Cookie Recipe – Incredients are:
’;
$granniesRecipe->printIncredients();
echo ‘
A new Cookie Recipe could look like:
’;
$aNewRecipe->printIncredients();
echo ‘
A coconut cookie would look like:
’;
$coconutRecipe->printIncredients();
The implementation is a bit odd, since it only collects the names of the ingredients but not the amount, but including the amounts of incredients would not change the concept and that’s why I left it out. I hope you got a idea how the pattern works – the main thing is that there’s no identity and that new objects are instantiated as soon as the state of the old one would change.
This metaphor does not fit completely, and the "Money-Example" is omnipresent, but I really like the pattern and so that's the story:
Let's say you have your grannies recipe for a chocolate cookie and you want to keep this in mind, but also you like to somehow experiment with some new or different ingredients. Normally you just keep in mind what you changed and later you write down the new recipe. But from time to time you might want to compare the two recipes or maybe you want to make cookies with the new and the changed recipes. In this situation it's really good to have both written down on paper. ;)
In the world of OOP you could think of a solution using the Memento-Pattern but this doesn't really fit the situation and it's also some kind of overhead. That's the reason why the Value Object is the pattern of my choice.
So let's look at the recipes again - we want to add and remove ingredients without modifying the original recipe and we want to compare the resulting recipes. We don't need to track
Posted: May 22nd, 2008 | Author: tolleiv | Tags: php | Comments Off
There are so many people from outside of the PHP World and lots of them are complaining about PHP and their reasons are mostly so ridiculous. In most cases they just say that PHP code sucks.
The PHP 10.0 Blog brought up some good arguments about that and I fully agree – it’s not the language that produces sucking code, it’s the guy who wrote it down. Click
There are so many people from outside of the PHP World and lots of them are complaining about PHP and their reasons are mostly so ridiculous. In most cases they just say that PHP code sucks.The PHP 10.0 Blog brought up some good arguments about that and I fully agree - it's not the language that produces sucking code, it's the guy who wrote it down. Click