by Dominik Jungowski
29. April 2009
No Comment
There's a strange bug in PHP we recently came across: When using func_get_args() is used as second (or third or fourth etc) parameter, PHP crashes with a Fatal Error.
Try this code:
function returnSomething()
{
return func_get_args();
}
function callSomeFunction($message)
{
someFunction(func_get_args(), 'Hello World');
someFunction(1, returnSomething());
someFunction(1, func_get_args());
}
function someFunction($code, $message)
{
print($message . PHP_EOL);
}
callSomeFunction('Hello World');
The result should be
Hello World
Array
Array
yet you get
Hello World
Array
Fatal error: func_get_args(): Can't be used as a function parameter
in /home/dominik/test.php on line 12
The code works with any other function (see example code), only func_get_args() causes a crash.
So I thought: Let's commit a bug! I then found out that this very bug has already been committed in 2005: http://bugs.php.net/bug.php?id=27887. The bug was closed (unfixed) with this really unsatisfactory explanation:
[16 Jun 2005 1:34am UTC] tony2001@php.net
Damien, the docs say: "This function cannot be used directly as a function
parameter. Instead, its result may be assigned to a variable, which can
then be passed to the function.", so don't use it as a parameter.
[16 Jun 2005 9:04am UTC] derick@php.net
So there is no bug, and the docs already describe it -> bogus.
Of course: Why should I fix a bug, when I can just put a note in the documentation that says "don't use it as parameter".
Edit: I filed a bug and it was closed with the comment "This is a known issue and have been fixed in 5.3.". Good to know!
by Dominik Jungowski
1. April 2009
No Comment
Today we had a database crisis due to a powercut. Apart from corrupted tables (because of the immediate "shutdown") we also had another problem: CLI scripts/cronjobs suddenly threw a MySQL server has gone away Exception after a really short amount of time (maybe 30 seconds)
I found this useful list, the only problem was: all the points didn't match for my case. So we came up with an own list that we worked through:
- Flush privileges
- Restore the User grants/privileges
- Restart the MySQL server
- dpkg-reconfigure mysql-server-5.0 (or similar)
In our case restarting the MySQL server fixed the problem.
by Dominik Jungowski
31. Januar 2009
Comments (2)
There's one problem with array_unique(): It doesn't work with multidimensional arrays. Here's an example:
$array = array(
array(
'id' => 123,
'name' => 'Some Product',
'ean' => '1234567890123'
),
array(
'id' => 123,
'name' => 'Some Product',
'ean' => '4852950174938'
),
array(
'id' => 123,
'name' => 'Some Product',
'ean' => '1234567890123'
),
);
$uniqueArray = array_unique($array);
var_dump($uniqueArray);
Two elements are exactly the same, but one element has a different EAN, yet the var_dump() returns the following:
array(1) {
[0]=>
array(3) {
["id"]=>
int(123)
["name"]=>
string(12) "Some Product"
["ean"]=>
string(13) "1234567890123"
}
}
Obviously this is unexpected behaviour. array_unique() threw out the second element, which is clearly not the same as Element 1 and 3. The easiest way I came across is using md5 hashes for comparison of the elements. All you need is to iterate over the first dimension, serialize it and create a MD5 hash of it for comparison:
/**
* Create Unique Arrays using an md5 hash
*
* @param array $array
* @return array
*/
function arrayUnique($array, $preserveKeys = false)
{
// Unique Array for return
$arrayRewrite = array();
// Array with the md5 hashes
$arrayHashes = array();
foreach($array as $key => $item) {
// Serialize the current element and create a md5 hash
$hash = md5(serialize($item));
// If the md5 didn't come up yet, add the element to
// to arrayRewrite, otherwise drop it
if (!isset($arrayHashes[$hash])) {
// Save the current element hash
$arrayHashes[$hash] = $hash;
// Add element to the unique Array
if ($preserveKeys) {
$arrayRewrite[$key] = $item;
} else {
$arrayRewrite[] = $item;
}
}
}
return $arrayRewrite;
}
$uniqueArray = arrayUnique($array);
var_dump($uniqueArray);
Now the result is the one array_unique() should have already given:
array(2) {
[0]=>
array(3) {
["id"]=>
int(123)
["name"]=>
string(12) "Some Product"
["ean"]=>
string(13) "1234567890123"
}
[1]=>
array(3) {
["id"]=>
int(123)
["name"]=>
string(12) "Some Product"
["ean"]=>
string(13) "4852950174938"
}
}
This works with as many dimensions as you like.