Is PHP's OOP implementation complete?

This was in a loop correct? Out of curiosity how often in that loop did each DateTime need a different TimeZone defined? (Just wondering if an optimization could have been reusing the same object instead of defining it new on each iteration – as I see that in .NET from time to time and it is one of the first changes I’ll make)

Yes, I wrote above that I ended up caching the time zone object in a static variable to optimize this. This was a simple function that converted datetime from one time zone to another so I needed two time zone objects. Of course, in each iteration the needed objects were the same so I could cache them for reuse. I was surprised to see that instantiation of such simple objects of a built-in class could have a noticeable overhead. It was evident that object instantiation was what took most of the resources in the whole process - the very act of converting the date alone was the fastest operation.

Yes, this was a loop used when displaying comments in a tree view, when there were more than 100 comments I began to notice the overhead of the DateTimeZone object instantiations.

.NET has the same problem (even with String concatenation, which is why objects like StringBuilder exist) and it is a compiled language. One of the things I learned early on, is to watch your instantiation closely around loops, threaded activities, etc. as performance will begin to show if you don’t pay careful attention.

Just to give an example (a really bad example of the string scenario)
[highlight=C#]
string endResult = string.Empty;
for (int i = 0; i < 100000; i++)
endResult += string.Format(“Item {0}”, i.ToString());



StringBuilder on the other hand optimizes a lot of components when needing to work with a large string or a lot of concatenations
[highlight=C#]
StringBuilder endResult = new StringBuilder(500000); // set aside the length you think you may need
for (int i =0; i < 100000; i++)
    endResult.AppendFormat("Item {0}", i.ToString());

Likewise, I’ve seen very similar issues with the DateTime object in .NET that you described with PHP. The issue you encounter is the memory allocation. Each use of new X is going to place a X into a new memory location. Throw that into a loop and you’ll quickly see why that degrades performance. Any time X is reusable, it should be reused, or another way to clean it up, destroy X once you are done with it (might not see all the performance you could gain until garbage collection occurs).

Thanks, it’s interesting to know the problem exists in other languages as well. However, I’m not fully convinced that memory allocation is the cause of the overhead. When I construct a new string or array in PHP they also need memory allocation but this process is very fast. Sure, if an object is large then a lot of memory must be allocated but to me it looks like there must something more intensive going on when a new object is instantiated. If this problem is in other languages then perhaps it’s the nature of the beast and it’s hard to do any optimizations here.

It’s silly to say the implementation of OO in any particular language is ‘complete’ or not - as long as it satisfies the base principles outlined above (which PHP does). It may have more or less features than another language, but the languages are constantly evolving so just because (say) Java adds some OO feature/trick, doesn’t suddenly make all other languages which don’t implement this ‘incomplete’ in some way. So yes, PHP’s OOP implementation is ‘complete’, even though it doesn’t have everything that other languages do.

Yes, constants are not supposed to do that but PHP doesn’t allow final properties either, so either this or final properties should be implemented.

Yeah, I’m sure there is more to it, but I know the last time I ran a performance monitor on similar code, the memory usage shot up like crazy (in .NET), I think it was due to the way objects are stored on the heap and persisted across garbage collection (and whether it falls into tier 1, 2, 3 or 4 of garbage collection). Maybe there is something else that happens underneath too, but it definitely happens in .NET and you’ve found it in PHP, so they both likely do some implementation very similar to see that happen in both languages.

That would be my fault of choosing a poor title, since I split the thread from another discussion, as this one blossomed into all sorts of directions around PHP’s OOP implementation.

Gotcha. I do miss not being able to use readonly, final, and other attributes/properties too. Surprisingly, I must not do as much heavy programming in PHP as I don’t seem to run into “Man, I wish I had this or that” a lot while in PHP. It does happen occasionally, just not as often as I would have thought.

Sometimes I feel it when I recall the time long ago I used to work in Java but I guess not missing these things often is more related to being used to PHP not having them and working around them.

Agreed. Predecessor/precursor are much better terms than grandfather.

Just found out that PHP 5.4’s Closure class can achieve Metaprogramming in an alternative way:
http://www.php.net/manual/en/closure.bind.php

Although it’s not as elegant as runkit when it comes down to Metaprogramming, it seems to be working at least and does not require installation from PECL. Still, the fact that it’s not compatible with PHP 5.3 means that it cannot be used in plugin developments for internet applications as most webhosts still do not offer PHP 5.4. Doubt this will happen soon though, will likely have to wait another 2-3 years.

From everything I’ve read about metaprogramming, it sounds like a horrible way to code. Sounds like a bad idea to me.

I wont say so, it helps a lot with a plugin system. In fact, there are certain jobs that can only be accomplished with Metaprogramming.

Like what?

Oh yeah, just found out that PHP’s OOP has another flaw in it, this time it involves callable objects/methods. The problem is that __invoke() does not apply to class/object attributes, it only works for standard string variables. Consider a plugin system shown like below:

Class UserController:


class UserController{

    public function add(){
        echo "Creating User...<br>";
    }

    public function edit(){
        echo "Updating User...<br>";
    }

    public function delete(){
        echo "Removing User...<br>";
    }

}

UserSearchPlugin:


class UserSearchPlugin{

    public function __invoke(){
        echo "Searching User....<br>";
    }
}

The code below will throw a fatal error:


$controller = new UserController;
$controller->search = new UserSearchPlugin();
$controller->search();

While it will work if you modify it a bit, but the code will look a lot more ugly:


$controller = new UserController;
$controller->search = new UserSearchPlugin();
$search = $controller->search;
$search();

Of course some may argue that invoking class/object property could override their methods, that happens when you have a property and a method sharing the same name. This can be a fatal collision issue, but my question is, do you even think its a good OO design if for some reason your class/object has properties with the same name as its methods? At least I dont think so, while apparently the way PHP prevents metaprogramming and this method invocation mechanism is making it almost impossible for me to design a proper plugin system for my application. sigh

So is $controller->search->invoke() really that ugly?

And do keep in mind that very few OOP systems will allow $controller->search = new UserSearchPlugin(); without declaring the instance variable.

Well the fact is that my controller is invoking each action in this way: $controller->$action(), which is why the fact that __invoke() does not work with class/object properties is a huge blow. Maybe few OOP systems allows you to set property on the fly, but many enable metaprogramming so adding methods on the fly is easier. I was just trying to emulate metaprogramming with PHP, its just not that easy.

I do find a workaround for the plugin problem though, it requires using magic method __call() and therefore can be heavy on performance.


class UserController{

    public function __call($method, $params){
        if(property_exists($this->$method)){
            $method = $this->method;
            $method();
        }
    }

    public function add(){
        echo "Creating User...<br>";
    }

    public function edit(){
        echo "Updating User...<br>";
    }

    public function delete(){
        echo "Removing User...<br>";
    }

}  

Then $controller->$action() will work, its not a pretty solution but it does the work for now.

From my observation python seems to use zope.interface. (maybe there are others.)

Sent from my XT316 using Tapatalk 2

You may get better and more consistent results with call_user_func_array. That way, you can execute anything that’s callable, including an invokable object.

Maybe I’m missing something but what’s the downside to overriding the __call method? Is there a huge performance penalty? Or are any database methods used still going to dominate any performance issues here unless you’re database is completely in memory?

From an OOP vantage point it certainly seems to give you the polymorphism that you are after.

I am not sure I am understanding here but is it being claimed, in this thread, that metaprogramming would be a high performance way of implementing a plugin handling framework in PHP or is it code elegance that is the driving factor here?

Sent from my XT316 using Tapatalk 2

Well there is indeed a significant performance penalty of using __call() and call_user_func_array(), using two of them together makes this even worse. The result is evident from Mark O’Sullivan’s article:

Id say the worst practice is to implement call_user_func_array() inside __call() magic method, it cant get slower than using these two together although implementing them separately.