View Full Version : Resolved PHP Classes & Performance

11-05-2012, 12:18 PM
Hi ya, I have a general question about using PHP classes. Imagine I make a large file with many classes, but I may not necessarily need all those classes every time that file is called. Will I suffer a performance loss for classes that I don't initialize? I would expect PHP to look inside abstract or static classes as it loads them, but I'm not sure about the others. Can classes effectively hide code until used? ... Can anything?

11-05-2012, 02:46 PM
Yep, you'll see a performance loss doing this. PHP will parse all of these files and build the symbols table as necessary to include the definition of any function or class. So it will cost you time and memory to do this.
I don't understand by what you mean saying to hide code. You can write nested functions in which they will not index their signatures until the outer function is called. It still parses the entire file though, so you need to write it proper, but the function will not be available until the outer is called. PHP doesn't support class or method nesting though.

Use an autoload to specify paths and common class extension instead. Throw that onto the php load path and it will automatically find the class when called. Mucho easier with namespacing as it resolves the namespace as a path, so you can simply autoload the extension and then issue a register to the root path. When you issue a use command it will chain the namespace as if it were a filepath.

11-05-2012, 05:35 PM
Thanks a lot Fou-Lu, this is surely something I will keep in mind when structuring my files. When I said "hiding code", I meant having code in a file without it effecting the memory use or page load. I also have a curiosity on what you said here: ".. It still parses the entire file though, so you need to write it proper.." I can write a fatal error in a conditional statement, like so..

if(1 == 2) { undefinedFunction(); }

.. and this won't be a problem. How does this happen, if everything in the file gets parsed? Would this actually be "hiding code" as I mentioned it? Thanks again, all this is very helpful for me.

11-05-2012, 05:42 PM
runtime error <> syntactical error. If you run that code, it will parse as its valid PHP code, but it will throw a runtime error if it ever enters the condition since undefinedFunction isn't defined (assuming that its not defined of course). It needs to be proper PHP code that doesn't throw a syntactical error so it has to pass the compile and link checks. PHP doesn't have a mechanism to verify that a function exists during link, its only during run that will trigger an error.

11-05-2012, 06:11 PM
Ah, I understand that now, <?php if(1 == 2) { ) } ?> kicks the bucket.

Unfortunately I can't use namespaces, since the server I'm on uses PHP 5.2.17. I suppose autoloading is still a good idea, I'll be getting my head around that shortly! Gracias Fou-Lu.

11-06-2012, 08:12 AM
tip: use spl_autoload_register() (http://php.net/spl-autoload-register), it’s way better than __autoload().

11-06-2012, 10:30 AM
tip: use spl_autoload_register() (http://php.net/spl-autoload-register), itís way better than __autoload().

I don't understand how on first glance. I appreciate you making that a link though.

11-06-2012, 10:51 AM
__autoload() usually looks in one place (unless you write a lot of code), spl_autoload_register() allows for several functions, that can look up one individual place (and the look-up stops naturally, if a match is found). and of course you can unregister look-up functions again.

11-06-2012, 02:57 PM
Thats right, you effectively chain together functionality of multiple autoloads. So it checks in method a first, then in method b, and all the way through the chain until it either finds a valid condition (such as a class to load), or fails to find it.
This is why the namespaces are so convenient, its a matter of putting it to the root directory and autoloading it:

set_include_path(get_include_path() . PATH_SEPARATOR . realpath(__DIR__ . "/../"));

The use is automatically invoked to use the filepath as the namespace path, so you never need to issue an include/require again for a class to load. Too bad your PHP version is < 5.3.

11-07-2012, 02:55 PM
.. you never need to issue an include/require again for a class to load..

Ooh, I like that. Now you've got me imagining all new levels of clean and efficient code. Shouldn't I be able to do that rather easily, even without namespaces?

What if I do this in auto_prepend_file:

// Assuming I'm keeping all my class files at my include path.

function __autoload($class) { include $class.'.class.php'; }

Pardon my use of __autoload() over spl_autoload_register(). I'm still reading about that one, and I didn't want to use it wrong in such a simple example!

Is there a reason to have it more complicated than that?

11-07-2012, 03:26 PM
That would work fine yeah. The problem is that you need to put all the class files in the same place for that to work, but if you were to keep adding to the path, then it would be capable of searching on the path to find the classes it needs.
I wouldn't include it though. I would require_once it.

11-07-2012, 05:50 PM
I expect spl_autoload_register() will be of help for searching more than one directory. :thumbsup: I will use require_once as well.

I'm wondering, do you know if auto_prepend_file uses _once functionality? I might be better to include_once this code in my pages, rather than have it reload every-time it creates a new class.

11-07-2012, 06:02 PM
The documentation isn't specific. It indicates it uses include for the file that you want to include, but since its implicitly done before the main, I'd expect that subsequent inclusions do not apply an auto_prepend or auto_append functionality for each one. So it should only do it once.
I myself still use require_once functionality instead of prepending. That's a personal choice though as I like testing each and every class with as minimal dependency as possible, so I point all of them to a common global include, which takes care of my registrations.

11-07-2012, 07:31 PM
In the section for core php.ini directives it says it uses require, however, it's actually require_once!

I prepended this file:

<?php if(isset($Var)) { ++$Var; } else { $Var = 0; } ?>

I could require or include any number of files, but the only way I could make $Var = "1" was to include or require itself, but not include_once or require_once.
This goes to prove that it is registering that file on the "been included/required" list. As for being require, it fatal errors when the file doesn't exist.

I'll feel a lot better about using it now that I understand that. Anyway, thanks very much Fou-Lu. Your guidance has taught me things I will consider essential in future endeavors.