PHP Benchmark: The array plus operator VS array_merge

Posted: August 13th, 2011 | Author: | Filed under: PHP | Tags: , , , | No Comments »

Just a quick post about a benchmark that quite surprised me. The array plus operator ($arr1 + $arr2) is over 6 times faster compared to array_merge. I did expect that to be faster, but not that much. This is the benchmark I used:

nadav@shesek:~$ time php -r '$x=array("x"=>1, "y"=>2); $y = array("y"=>3, "z"=>4);
> for ($i=1; $i<=500000; $i++) { $y + $x; }'

real	0m1.437s
user	0m1.392s
sys	0m0.024s

nadav@shesek:~$ time php -r '$x=array("x"=>1, "y"=>2); $y = array("y"=>3, "z"=>4);
> for ($i=1; $i<=500000; $i++) { array_merge($x, $y); }'

real	0m9.994s
user	0m7.472s
sys	0m2.400s

The results were about the same for several executions.

A couple of things should be be noted about the array plus operator:

  1. As opposed to array_merge, it overwrites numeric keys too. If you need to merge the values of two arrays with numeric keys, use array_merge instead
  2. If you need recursive merge, use array_merge_recursive instead.
  3. The values from the first array overwrites the values from the second, as opposed to array_merge. So the equivalent of array_merge($a, $b) is $b + $a, not $a + $b.
  4. Example:

    $arr = array('a' => 1, 'b' => 2, 'c' => 3);
    $arr = array('b' => 4) + $arr;
    // $arr is now array('a' => 1, 'b' => 4, 'c' => 3)
    

Generic PHP object wrapper for resources

Posted: March 7th, 2011 | Author: | Filed under: PHP | Tags: , , | No Comments »

I hate working with PHP’s resources. I hate the long function names, I hate repeating the function names prefix, I hate having to pass around the resource variable. It looks like hack that was used instead of real object and classes and it feels dirty compared to OOP code. I personally think it should’ve been replaced with real classes and objects a long time ago. </whining>

So, I thought on a simple way to wrap it with a class that lets you work with those resources as-if they were real objects. Basically, its a simple class that wraps the resource, configured with the functions prefix and has some __call() magic.

For example, when working with GD, that code:

$image = imagecreate(150, 50);
$bg = imagecolorallocate($image, 255, 255, 255);
$red = imagecolorallocate($image, 255, 0, 0);
imagestring($image, 2, 2, 2, 'Hello, world!', $red);
imagejpeg($image);

Can be written as:

$image = new ResourceWrapper('image', 'create', 150, 50);
$bg = $image->colorAllocate(255, 255, 255);
$red = $image->colorAllocate(255, 0, 0);
$image->string(2, 2, 2, 'Hello, world!', $red);
$image->jpeg();

The ResourceWrapper class constructor takes the function names prefix as its first argument (e.g. ‘image’ for GD, ‘mysql_’ for mysql, ‘bz’ for bzip, etc) and the function used to create the resource as the second argument (without the prefix). The rest of the argument are passed untouched to that method. In that example, it’ll call imagecreate(150, 150) and store the resource as a property on the object.

Than, every call on that object is handled using __call() magic. The function prefix is added to method that was called, the stored resource is passed along all the other arguments and the return value from that function is returned.

The resource is passed, by default, as the first argument to the function calls. In some cases, like mysql, it should be passed last. The can be changed using $object->_setPosition(ResourceWrapper::POS_LAST).

This is the code for the ResourceWrapper class:

/**
 * A wrapper class for PHP resourcse.
 *
 * Used for wrapping PHP resources in an object, and working with them in an
 * Object-Oriented manner.
 *
 * Some methods are prefixed with `_` even though they're public to avoid
 * clashes with resource-related functions.
 *
 * @author Shesek <th[e]@RemoveMe.shesek.inf[o]>
 * @license http://creativecommons.org/licenses/by/3.0/ CC-BY 3.0
 * @see http://www.shesek.info/php/generic-php-object-wrapper-for-resources
 */

class ResourceWrapper {
	/**
	 * POS_FIRST and POS_LAST are used to set the correct position of the
	 * resource argument on function calls.
	 */
	const POS_FIRST = 1;
	const POS_LAST = 2;

	/**
	 * Holds the PHP resource being wrapped
	 *
	 * @var resource
	 */
	protected $resource;

	/**
	 * The prefix for functions related to this resource
	 *
	 * e.g. 'image' for GD, 'mysql_' for mysql, 'bz' for bzip, etc
	 *
	 * @var string
	 */
	protected $prefix;

	/**
	 * The position of the resource argument on function calls
	 *
	 * Either ResourceWrapper::POS_FIRST or ResourceWrapper::POS_LAST
	 *
	 * @var integer
	 */
	protected $resource_position = 1;

	/**
	 * The constructor creates the PHP resource and stores it locally on the object.
	 *
	 * The $prefix and $method arguments are used to determine the function name,
	 * and the rest of the arguments are passed untouced to it.
	 *
	 * For example, passing 'mysql_' as the $prefix and 'connect' as the $method
	 * would cause it to call mysql_connect(), with the other parameters.
	 *
	 * new ResourceWrapper('mysql_', 'connect', 'localhost', 'nadav')
	 * is translated to mysql_connect('localhost', 'nadav')
	 *
	 * @param string $prefix
	 * @param string $method
	 */
	public function __construct($prefix, $method) {
		$this->prefix = $prefix;
		$args = func_get_args();
		$this->resource = $this->__call($method, array_slice($args, 2));
	}

	/**
	 * Delegates calls to the original PHP functions while passing the resource.
	 *
	 * Adds the function prefix (as defined in the constructor) to the method name
	 * being called, passes the resource along with the other arguments, invokes
	 * the original function and return the return value from it.
	 *
	 * @param string $method
	 * @param array $args
	 * @return mixed
	 */
	public function __call($method, $args) {
		if (!is_null($this->resource)) {
			if ($this->resource_position === self::POS_FIRST) {
				array_unshift($args, $this->resource);
			}
			else {
				array_push($args, $this->resource);
			}
		}
		return call_user_func_array($this->prefix . $method, $args);
	}

	/**
	 * Set wheter the resource should be passed last or first in the arguments.
	 *
	 * @param	integer	$position	ResourceWrapper::POS_FIRST or ResourceWrapper::POS_LAST
	 */
	public function _setPosition($position) {
		$this->resource_position = $position;
		return $this;
	}

	/**
	 * Returns the wrapped PHP resource.
	 *
	 * @return resource
	 */
	public function _getResource() {
		return $this->resource;
	}

	/**
	 * Magic toString conversion
	 */
	public function __toString() {
		return 'ResourceWrapper for '.get_resource_type($this->resource);
	}
}

That’s about it. Its very simple – but makes the code more organized and look nicer. In my opinion, it feels much more natural that way.

You can also download it here. Released under CC-BY 3.0.


Transform a transparent PNG to white-background JPG using PHP GD

Posted: October 14th, 2010 | Author: | Filed under: PHP | Tags: , , , , , | No Comments »

It seems like Facebook doesn’t handle transparent PNG files very well (they’re transformed into JPG without handling the transparent background, which ends up as a weird black background), so we needed to transform it ourselves to a white-background JPG to make it display well:

function imagetranstowhite($trans) {
	// Create a new true color image with the same size
	$w = imagesx($trans);
	$h = imagesy($trans);
	$white = imagecreatetruecolor($w, $h);

	// Fill the new image with white background
	$bg = imagecolorallocate($white, 255, 255, 255);
	imagefill($white, 0, 0, $bg);

	// Copy original transparent image onto the new image
	imagecopy($white, $trans, 0, 0, 0, 0, $w, $h);
	return $white;
}

Can be used like that:

// Open original PNG image
$png = imagecreatefrompng($path);
// Transform to white-background JPEG
$jpg = imagetranstowhite($png);
// Save new image
imagejpeg($jpg, $new_path);

Toodledo API implemented in PHP

Posted: March 29th, 2010 | Author: | Filed under: PHP | Tags: , , , | 12 Comments »

Toodledo API 2.0 is out, which is not supported by this class. The 1.0 version is depreciated, but still supported for now. I’ll publish a new version when I have some free time.

I couldn’t find one, so I decided to write a PHP class that talks with Toodledo API. its not very well documented/commented, but quite simple and works well.

Works on PHP5+ only. Uses the built-in stream wrapper for making HTTP requests, and returns the response as an SimpleXML object. It uses file-system caching for storing the tokens the API gives you (there’s a CACHEDIR const to define where it should be saved).

The usage is as follows:

$t = new Toodledo('user id', 'password', 'app id'); // last parameter is optional

// Add task
$response = $t->addTask(array(
	'title' => 'Finish writing toodledo class in PHP',
	...
));
$id = (string)$response->added;

// Get tasks
$tasks = $t->getTasks(array(
	'title' => 'foo',
	'tag' => 'bar',
));
foreach ($tasks->task as $task) {
	echo (string)$task->title;
}

You can also get the response as raw XML string and as array, by using Toodledo::RAW and Toodledo::ARR as the second argument.

print_r($t->getTasks(array('title' => 'foo'), Toodledo::ARR));

OK, so, I must admit – I cheated. I didn’t really implement the entire API, I just wrote one method named request() and used some __call() magic to make everything work. basically, you just call $object->APIMethodName(array(‘extra’=>’parameters’)) with whatever method name and parameters and it just build the request accordingly.

When an error occurs (either while making the request or the Toodledo API returns an error), an Exception is thrown. Make sure to catch those.

That’s about it. You can download it here. Released under the WTFPL license.


HTTP error 417 with PHP’s curl

Posted: March 11th, 2010 | Author: | Filed under: PHP | Tags: , , , , , , | 4 Comments »

I’ve been getting 417 response codes (Expectation failed) while making requests with PHP/curl to tinyurl.com (I’ll probably publish that project here in a week or two). Well, its very annoying. took me some time to figure that one out.

If someone else wonders about it, that’s the deal:

If the content length (of the request post data) is bigger than 1KB (>=1025 bytes), the client (curl in our case) sends the request with a “Expect: 100-continue” header and without the actual post data, than awaits for a response with status 100, and than finally sends the actual post data.

The problem is that many servers (lighttpd 1.4 among them, fixed at 1.5) doesn’t support that, which is exactly why I got the 417 error when my client attempted to use that header.

To make curl suppress that header, and just send the request/post data normally while ignoring the fact that the post data is more than 1KB, add the following piece of code:

curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));

Adding a header with no value makes it overwrite the original value and suppress the header, which should make everything work fine.

It should be noted that every time you set CURLOPT_HTTPHEADER it overwrites the original HTTPHEADER value and not appends to it, so if you already set it, you should simply add ‘Expect:’ to your existing HTTPHEADER array instead of adding the entire line.


My implementation of PHP Chainable

Posted: March 2nd, 2010 | Author: | Filed under: PHP | Tags: , , | No Comments »

I needed a way to use method chainability on objects without having to modify the actual class (e.g. extending some Chainable class or implementing one) and without having to “return $this” on every method.

I came up with, what I believe to be, an elegant simple solution – a generic approach that can be used on any class/object, which makes chaining possible on 3rd-party classes and enables you to get the return values from those methods.

For the lazy ones among us, it also allows to have the benefits of method chaining without having to think about it while coding, but I won’t recommended that because of the performance hit. Its more useful for 3rd-party classes, if you’re the one writing the class just make sure to support chaining.

So, first of all, this is the Chainable class:

class Chainable {
	private $obj;
	private $result;
	public function __construct($obj){
		$this->obj = $obj;
	}
	public function __call($method, $args) {
		if (substr($method, 0, 1) == '_') {
			array_unshift($args, $this->result);
			$method = substr($method, 1);
		}
		$this->result = call_user_func_array(array($this->obj, $method), $args);
		return $this;
	}
	// __set & __get were added later on and mentiond at the very end of the post
	public function __set($key, $value){$this->obj->$key = $value; return $this;}
	public function __get($key){return $this->obj->$key;}

	public function result(){
		return $this->result;
	}

	// new Chainable($obj)->foo() isn't possible, Chainable::get($obj)->foo() is
	public static function get($obj){
		$chainable = new Chainable($obj);
		return $chainable;
	}
}

(You can download a raw version from here)

Basically, you use instances of Chainable instead of working directly with the actual class. You get a new instance by using new Chainable($object), or the more convient way which allows to call methods of it right away – Chainable::get($object).

After getting a Chainable object that’s connected to your object, you simply use $chainableObj->method1()->method2().

If you want to pass the result of the last method call to the next method, you prefix the method that should receive the result with a “_”, and than the first argument passed to it would be the last return value.

Also, you have a result() method for getting the last result from “outside”. this does create problems when you actually have a result() method on the object you’re passing to Chainable, and I will probably change it to something less likely to be used.

Lets take an example class, Foo:

class Foo {
	public function bar($str){
		return 'bar::' . $str;
	}

	public function taz($passed, $str) {
		return 'taz::' . $str . ' -- passed::' . $passed;
	}
}

Than, to use the Chainable interface you:

$foo = new Foo;
echo Chainable::get($foo)->bar('shesek')->_taz('test')->result();
</pre>

Which prints "taz::test -- passed::bar::shesek". note the "<strong style="color: #ff0000;">_</strong>taz" which allows taz() to get the return value of bar() as the first argument, $passed.

Another approach could be adding a "chain" method inside the Foo class (probably much easier to make a base class that has this and extend):
1
public function chain(){
	return Chainable::get($this);
}

Which enables you to use $foo->chain()->bar('shesek')->_taz('test')->result();. It makes the code prettier, with the price of having to modify the class itself – but a very minor modification.

If you have any remarks or thoughts, I’ll be happy to hear about it!

Update: Added __set & __GET

__set allows you to set variables in the object while chaining (example with PHPMailer):

$mail=new PHPMailer();
Chainable::get($mail)->__set('Subject','Hello there')->AddReplyTo('my@email.info')->SetFrom('my@email.info')->AddAddress('your@email.info')->msgHTML('<h1>Hey!</h1>')->send()->result()

This is equal to $mail->Subject=’…’;. This can be used as a magic setter too, but doesn’t make much sense.

__get allows you to read public properties of the object:

$http = new HTTP;
echo Chainable::get($http)->__set('url', 'http://www.google.com/')->request()->html;

The last ->html> is equal to $http->html.