Page 4 of 5

Posted: Sun May 13, 2007 2:58 pm
by Ambush Commander
I like d11twq's analogy the best: implementing __autoload() means you are adopting Java's style of class management.

Posted: Sun May 13, 2007 7:11 pm
by Jenk
Ambush Commander wrote:While I won't pass judgment on the new behavior, I have certainly been bitten by the autoloading behavior of class_exists.
If it was named "class_available" it might be more clear. It is supposed to depict if the class asked for is available - be it loaded or autoloaded.

Posted: Mon May 14, 2007 2:22 pm
by RobertGonzalez
arborint wrote: Foo.php

Code: Select all

<?php
class Foo {
	function Foo() {
		echo 'Foo';
	}
}
test.php

Code: Select all

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

if (class_exists('Foo')) {
	echo '1st check Foo exists.<br/>';
}
if (class_exists('Foo')) {
	echo '2nd check Foo exists.<br/>';
}
It will output:

Code: Select all

1st check Foo exists.
2nd check Foo exists.
That means if an autoload function is present that class_exists() returns true if a class is not loaded -- and load the class, and of course true if the class has been previously loaded.
Loading the class as in including the file in which the class is contained? Or is there more to it than that?

Posted: Mon May 14, 2007 2:58 pm
by Christopher
Everah wrote:Loading the class as in including the file in which the class is contained? Or is there more to it than that?
Not more -- different. What they have done is added the autoload callback check/call to other functions related to whether a class has been loaded. Since all those functions now run the same internal check as new, they all have the ability to "benefit" (dreamscape ;)) from an autoload function being registered. If you think of it, it makes sense that new would, before proceeding, call the same internal "class exists" code that class_exists() uses.

So in the code I posted, the first class_exists() will -- if the class is not loaded -- internally run the check to see if there is an autoload callback registered. So in the example the first class_exists() returns true because even though the class was not loaded -- it loaded it (well it called the autoload function). The second class_exists() returns true because the first call loaded it.

My point in my comments in this thread is not that this system is not workable, nor that it might not be the best for PHP. My point was that we may never know if the alternatives were better because this system evolved from a focus on what was easy to implement in the engine, rather than what might be the best design or promoting practice in PHP OOP. It was my opinion that the reason this happened is that they developers know a lot about the engine's internals, but are pretty provincial in their knowledge of OOP.

Posted: Mon May 14, 2007 3:24 pm
by kyberfabrikken
arborint wrote:My point in my comments in this thread is not that this system is not workable, nor that it might not be the best for PHP. My point was that we may never know if the alternatives were better because this system evolved from a focus on what was easy to implement in the engine, rather than what might be the best design or promoting practice in PHP OOP. It was my opinion that the reason this happened is that they developers know a lot about the engine's internals, but are pretty provincial in their knowledge of OOP.
While I recognise your point, I have a hard time seeing any alternatives. What other mechanisms, could have been implemented to provide a similar feature?
I my book, autoload is an all out improvement. It provides lazy loading of classes, and it decouples the filename from the code, using the class.

Posted: Mon May 14, 2007 3:41 pm
by RobertGonzalez
So my next question is does PHP have a default autoloader of sorts? I mean, if you do not define __autoload and call class_exists without turning off autoloading, how does PHP interpret that?

Posted: Mon May 14, 2007 3:43 pm
by Ambush Commander
The definition of the __autoload() is, itself, "turning on" autoload. Otherwise, one acts as if it doesn't exist.

I think that's part of the problem: if you have a library that uses class semantics as if there was no autoload, and it gets used in an application that has __autoload, you'll have problems. I did.

Posted: Mon May 14, 2007 3:52 pm
by stereofrog
Everah wrote:So my next question is does PHP have a default autoloader of sorts? I mean, if you do not define __autoload and call class_exists without turning off autoloading, how does PHP interpret that?
If there's no autoload, class_exists(Foo) returns false and new Foo raises a fatal error. An adequate design solution would be to throw the normal catchable ClassNotFound exception instead. Hopefully this is going to happen in php6, and autoload will be deprecated just like other "cool" php features: register_globals, magic_quotes etc.

Posted: Mon May 14, 2007 4:12 pm
by Christopher
kyberfabrikken wrote:While I recognise your point, I have a hard time seeing any alternatives. What other mechanisms, could have been implemented to provide a similar feature?
I my book, autoload is an all out improvement. It provides lazy loading of classes, and it decouples the filename from the code, using the class.
I mention some alternatives here but I don't really have a well thought out answer. And as I have said repeatedly, autoload is a workable solution. I think Everah's questions show that it is not perhaps the clearest solution. For example, they could have followed the session system's design and had a autoload_start() function with a default autoload function that just used the current path and perhaps replaced underscores with path separators. You could then register replacement or additional autoloaders. That would have been both consistent with what people know and would have set a standard that was a baseline.

I can see lots of alternatives, but from what I have read there was not much "best practices" discussion -- not how it could work -- but on how programmers should best deal with loading classes. I have the same problem with __get()/__set()/__call() -- they are solutions, but there are many other ways to solve the same problems that might promote better practices in the long run/big picture. Or maybe not and I am just full of it. ;)

Posted: Mon May 14, 2007 5:09 pm
by RobertGonzalez
Ambush Commander wrote:The definition of the __autoload() is, itself, "turning on" autoload. Otherwise, one acts as if it doesn't exist.

I think that's part of the problem: if you have a library that uses class semantics as if there was no autoload, and it gets used in an application that has __autoload, you'll have problems. I did.
Can you give an example?

I am sorry for sounding so thick, but for some reason this concept of loading a class is just not sinking in. To me it sounds like autoloading includes the file the class lives in if it can find that file. If it can't find the file and actually call new <whateverclassneedstobeloaded> then it will crap out with a fatal error. Otherwise, if it can find it, it includes it and calls new <whateverclassneedstobeloaded>. If there is no autoload function defined, then basically we are in the mode of using include/require and trusting that the class we are instantiating has already been included and can be instantiated.

Posted: Mon May 14, 2007 5:13 pm
by Ambush Commander
According to the manual, here's what PHP does when it encounters a "new" declaration:

1. PHP will attempt to instantiate the class. If it succeeds, yay, if not...
2. PHP will check for the existence of an __autoload function (if not, die)
3. PHP will run __autoload
4. PHP will attempt to instantiate the class again. This time, if it fails, die.

Posted: Mon May 14, 2007 5:31 pm
by RobertGonzalez
Ok, I think I am getting autoloading. Example:

Code: Select all

<?php
$object = new Class_Objectifier();
?>
If the code that contains the class Class_Objectifier has not been included, or that class is not yet defined within the current scope, PHP will invoke autoload and attempt to find the class file based on what is in __autoload(). If it can find it using __autoload() it will include it and instantiate it. If it cannot find it using __autoload(), then it craps out completely and squawks.

Not how does this work in conjunction with spl_autoload_register()?

Posted: Mon May 14, 2007 6:44 pm
by Christopher
Everah wrote:Ok, I think I am getting autoloading. Example:

Code: Select all

<?php
$object = new Class_Objectifier();
?>
If the code that contains the class Class_Objectifier has not been included, or that class is not yet defined within the current scope, PHP will invoke autoload and attempt to find the class file based on what is in __autoload(). If it can find it using __autoload() it will include it and instantiate it. If it cannot find it using __autoload(), then it craps out completely and squawks.
I think the thing that you are not getting is that there is now autoload function -- you supply the function to load classes. So if you used the simple autoload function I posted:

Code: Select all

<?php
function __autoload($class) {
        include $class . '.php';
}
Then there would need to be a file named Class_Objectifier.php in the include_path for the autoload to succeed.
Everah wrote:Not how does this work in conjunction with spl_autoload_register()?
All the SPL autoload functions do is allow multiple autoload functions. This is because there is only one possible function named "__autoload" so if I write a library that uses "__autoload" and the application is already defining "__autoload" then there is a name clash. The SPL functions get around the name clash.

Posted: Tue May 15, 2007 2:46 am
by Chris Corbyn
arborint wrote:I have the same problem with __get()/__set()/__call() -- they are solutions, but there are many other ways to solve the same problems that might promote better practices in the long run/big picture. Or maybe not and I am just full of it.
These methods come in really useful at times. I use __get() and __set() in my abstract View component (just like many others do), but I also provide setVar() and getVar() in the View too. They're just convenience methods really.

Posted: Tue May 15, 2007 4:02 am
by kyberfabrikken
d11wtq wrote: These methods come in really useful at times. I use __get() and __set() in my abstract View component (just like many others do), but I also provide setVar() and getVar() in the View too. They're just convenience methods really.
I think arborint's point was that the implementation is sketchy. C#'s "properties" are a much nicer implementation of basically the same functionality.