问题
I was reading this page - http://deaduseful.com/blog/posts/50-php-optimisation-tips-revisited
And one of the recommendations was to avoid using Magic Methods, cited from a Zend Performance PDF which gives no reason for its recommendation to avoid them.
After some Google searching (and winding up here to an unrelated question) I wondered if anyone had any reccomendations on that front?
I use __get() alot in my code, usually to save variables that I don't always use e.g.
I may have a table with name, desc, category_id, time_added
My get would look something like this:
public function __get($name) { switch($name) { case 'name': case 'desc': case 'category': case 'time_added': $result = do_mysql_query(); $this->name = $result['name']; $this->desc = $result['desc']; $this->category = $result['category']; $this->time_added = $result['time_added']; return $this->{$name}; break; default: throw Exception("Attempted to access non existant or private property - ".$name); } }
This seems like a great way to do things as I only ever get something from the database if it's needed and I can refence things like $article->time_added rather than fiddling around with arrays.
Would this be considered bad practice and an extra load on the server?
Often I will extend classes with magic methods and do something like this if the child class doesn't match something in a get.
public function __get($name) { switch($name) { case 'name': case 'desc': case 'category': case 'time_added': $result = do_mysql_query(); $this->name = $result['name']; $this->desc = $result['desc']; $this->category = $result['category']; $this->time_added = $result['time_added']; return $this->{$name}; break; default: return parent::__get($name); } }
Would this be bad practice and bad for performance? The maximum number of levels I have when extending magic methods is three.
回答1:
It's true, they are slower... but the difference is so tiny that speed vs code is a factor. Is it worth worrying about the difference for quicker development and maintenance?
See magic benchmarks for stats
回答2:
Consider using array accessors.
class Record implements ArrayAccess {
/**
* @see ArrayAccess::offsetExists()
*
* @param offset $offset
*/
public function offsetExists($offset) {
}
/**
* @see ArrayAccess::offsetGet()
*
* @param offset $offset
*/
public function offsetGet($offset) {
//fetch and cache $result
return $result[$offset];
}
/**
* @see ArrayAccess::offsetSet()
*
* @param offset $offset
* @param value $value
*/
public function offsetSet($offset, $value) {
}
/**
* @see ArrayAccess::offsetUnset()
*
* @param offset $offset
*/
public function offsetUnset($offset) {
}
回答3:
I did some tests with PHP magic methods and native get/set operations (on a public property)
The results:
Magic methods are much slower than native access. BUT access time is still so small, that it will not make a difference in 99.9% of all cases.
Even if you do 1 Million magic method accesses within one request, it still only takes about 0.1 second...
"Read only" means access via magic methods. The image shows PHP 5.5.9 and PHP 7.0 results.
Here is the benchmark script: https://github.com/stracker-phil/php-benchmark/blob/master/benchmark.php
来源:https://stackoverflow.com/questions/3634748/php-zend-say-avoid-magic-methods