Path: csiph.com!eternal-september.org!feeder.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Matthew Carter Newsgroups: comp.lang.php Subject: Re: Class 'Model' not found Date: Sun, 28 Aug 2016 00:00:05 -0400 Organization: Ahungry (http://ahungry.com) Lines: 174 Message-ID: <87poottuey.fsf@ahungry.com> References: <1563ad73-c46d-487f-84e0-a80a1217f2db@googlegroups.com> <1647269.ji5Ds1KI6Y@PointedEars.de> <87shtwuki0.fsf@ahungry.com> <2827421.aeNJFYEL58@PointedEars.de> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Injection-Info: mx02.eternal-september.org; posting-host="7c986cd4736462de309a749b207746fe"; logging-data="25608"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/UZ1ElUO45E0XITt2gyRNT" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.5 (gnu/linux) Cancel-Lock: sha1:R6fed/MUqjI1T1rUmw1In5xchBY= sha1:Lxu80ADUSYlWjpKHnsG34OTszVI= Xref: csiph.com comp.lang.php:16984 Thomas 'PointedEars' Lahn writes: > Jerry Stuckle wrote: > >> On 8/23/2016 1:23 AM, Matthew Carter wrote: >>> Jerry Stuckle writes: >>>> You've obviously not had the autoloading function pick up the wrong >>>> version of a class. But that's not surprising from you. You have >>>> repeatedly shown you have no concept of good coding techniques, and have >>>> probably never had two classes of ANY name on your system. >>> >>> Why would you have 2 identically named classes in the same namespace (if >>> different namespaces, alias them)? > ^^^^^^^^^^ >>> If you're actually referring to 2 versions of the same class at >>> different points in time, why not a VCS? >> >> Because you loaded two different packages, both with the same class >> name. > > You can have the same class name in the same namespace in two different > *files*. > > But you _can not_ have that in the same PHP program, not even as includes. > It is not possible to redeclare classes, and you cannot undeclare/delete a > class. So it is irrelevant if you use an autoloader in that case. For > example, > > require_once 'Foo/Bar.php'; > require_once 'Baz/Bar.php'; > > where each Bar.php contains > > class Bar > { > // … > } > > results in “PHP Fatal error: Cannot redeclare class Bar in … on line …”. > No “use” statement can prevent that because the class has to be loaded > *before* it can be aliased. Which is why interoperable classes are declared > in their own namespace these days (formerly, prefixes were used to avoid > name collisions instead). > > As for the same class in different namespaces, I have marked the important > part in Matthew’s posting. For further reference: > > > > IOW: > > /* or: use Foo\Bar\Baz */; > use Foo\Bar\Baz as Bla; > > use Foo\Bar2\Baz as Blub; > > Then there could be a “Foo/Bar/Baz.php” that contains > > namespace Foo\Bar; > > class Baz > { > // … > } > > and a “Foo/Bar2/Baz.php” that contains > > namespace Foo\Bar2; > > class Baz > { > // … > } > > and (with a suitable autoloader) you could just write > > /* or “new Baz()”, see above */ > new Bla(); > > new Blub(); > >> Or you're running two different versions of software on the same machine. >> It's not at all uncommon when you're running multiple sites on one server. > > If only you knew what you are talking about. > > Different sites on the same machine, each using different versions of the > same class, perhaps in the same namespace, would either use *different* > autoloaders each (to avoid loading classes and their dependencies manually). > This can be as simple as adapting the include_path per site, or as > complicated as using different “require_once” statements (with different > paths) to load the correct autoloader. > > Or they would use one or more namespace-and-path-aware autoloaders. It is > possible to register *several* autoloaders, each only attempting to autoload > the classes that are in its namespace. Simple example: > > /* Library 1 code */ > > function autoload_lib1 ($class) > { > echo "autoload_lib1: autoloading $class ...\n"; > if (strpos($class, "Lib1\\") !== 0) > { > trigger_error("DEBUG: autoload_lib1: autoloading of $class rejected: " > . " Not in our namespace\n", E_USER_NOTICE); > return; > } > > /* Use include_once for the example only */ > include_once "lib1path" . DIRECTORY_SEPARATOR > . str_replace("\\", DIRECTORY_SEPARATOR, > str_replace("Lib1\\", "", $class)) > . ".php"; > } > > spl_autoload_register("\\autoload_lib1", true); > > > /* Library 2 code */ > > function autoload_lib2 ($class) > { > echo "autoload_lib2: autoloading $class ...\n"; > if (strpos($class, "Lib2\\") !== 0) > { > trigger_error("DEBUG: autoload_lib1: autoloading of $class rejected: " > . " Not in our namespace\n", E_USER_NOTICE); > return; > } > > /* Use include_once for the example only */ > include_once "lib2path" . DIRECTORY_SEPARATOR > . str_replace("\\", DIRECTORY_SEPARATOR, > str_replace("Lib2\\", "", $class)) > . ".php"; > } > > spl_autoload_register("\\autoload_lib2", true); > > > /* User code */ > > new Lib1\Foo1(); > > [Usually it does not make sense to use two versions of the same library > simultaneously because of different dependencies, and because the newer > version can do more than the older one. However, it is probably a good idea > to always write an autoloader so that it does not attempt to autoload > classes that are "out of its jurisdiction".] > > It is also possible to have *one* autoloader that handles *several* > namespaces and maps namespaces to paths correctly. Simplest (as is, > *unsafe*) case: > > function autoload_all ($class) > { > require_once str_replace("\\", DIRECTORY_SEPARATOR, $class) . ".php"; > } > > spl_autoload_register("\\autoload_all", true); > > [Note that the autoloader can be in a namespace itself, which reduces the > risk of namespace collisions for *its* declaration. That also makes it > easier to autoload only the classes "in the autoloader’s jurisdiction".] > > IOW, the problems that you are presuming simply *do* *not* *exist*. Great explanation, a wonderful reference for anyone needing to understand these topics better. -- Matthew Carter (m@ahungry.com) http://ahungry.com