RobotLoader::addClass – nespravna vynimka pri kolizii nazvov tried

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
viktorc
Člen | 21
+
0
-

V RobotLoader (Nette 1.0-dev 64b5b90 z 2010–09–17 pre PHP 5.2 bez prefixov) je jeden preklep a dve vaznejsie chyby.

  1. preklep RobotLoader::addClass: $class → $lClass na konci vyvolania InvalidStateException:
<?php
...
$lClass = strtolower($class);
if (!empty($this->list[$lClass]) && $this->list[$lClass][0] !== $file && is_file($this->list[$lClass][0])) {
	spl_autoload_call($class); // hack: enables exceptions
	//throw new InvalidStateException("Ambiguous class '$class' resolution; defined in $file and in " . $this->list[$class][0] . ".");
	throw new InvalidStateException("Ambiguous class '$class' resolution; defined in $file and in " . $this->list[$lClass][0] . ".");
}
...
?>
  1. Vacsi problem je vsak ak sa vyskytne kolizia nazvov tried.

Konkretny priklad: subor nSMTPMailer/exceptions.php z nSMTPMailera definuje InvalidStateException a IOException, ktore su definuje aj Nette v Utils/exceptions.php.

Spravne by mal addClass vyhodit InvalidStateException s informaciou o duplicite tychto tried v oboch suboroch. Bohuzial (nezmyselnu) vynimku vyhodi uz spl_autoload_call:

Fatal error: Cannot redeclare class ArgumentOutOfRangeException in …\Nette\Utils\exceptions.php on line 39

Trieda ArgumentOutOfRangeException vsak nema koliziu (zobrazuje sa pravdepodobne preto, lebo je prva v Nette\Utils\exceptions.php). Potom da dost roboty najst pricinu problemu.

Je nutne volat v addClass pri zisteni kolizii nazvov tried pred vyhodenim vynimky spl_autoload_call?

Poznamky:
Ked som zakomentoval deklaraciu InvalidStateException v nSMTPMailer/exceptions.php (zostala duplicitna IOException), vyhodila sa (podla ocakavania) rovnaka nezmyselna vynimka.

Ked som vsak zakomentoval aj IOException a doplnil do oboch suborov definiciu TestException, vyhodila sa (nechapem preco) spravna vynimka InvalidStateException.

  1. Nefunguju vynimky pre RobotLoader v subore netterobots.txt. Problem je niekde v RobotLoader::scanDirectory, pravdepodobne pri definovani filtra pre Finder.
<?php
...
$iterator->append(Finder::find(String::split($this->acceptFiles, '#[,\s]+#'))
    ->from($dir)
    ->exclude(String::split($this->ignoreDirs, '#[,\s]+#'))
    ->filter(create_function('$file', 'list($disallow) = NClosureFix::$vars['.NClosureFix::uses(array(&$disallow)).'];
        return !isset($disallow[$file->getPathname()]);
    '))->getIterator()
);
...
?>

Pole $disallow sa naplni spravne, ale Finder porovnava aktualnu polozku (subor, ci adresar) s obsahom pola $disallow len pre adresare.

Chyby c. 1 a 3 su nove v Nette 1.0 (v 0.9.5 neboli). Chyba c. 2 je stara, ale tam sa vdaka fungujucemu netterobots.txt pri nSMTPMailer-i neprejavi.
Sorry, ze som sa tak rozkecal ;-)

Filip Procházka
Moderator | 4668
+
0
-

Já tam teda chybu nevidím a co se týče té vyjímky tak je naprosto logická, pokud máš nějaké rozšíření a to má u sebe třídy Nette, protože je postavené, aby šlo používat bez něj, tak se nemůžeš divit že budou nastávat kolize.

Třídy které jsou navíc smaž nebo jim dej namespace té knihovničky a uprav závislosti

David Grudl
Nette Core | 8228
+
0
-

„Fatal error“ není výjimka, ale fatal error. Nepoužíváš víc autoloadingů a nedělá problémy ten druhý? Já v RobotLoaderu žádnou chybu nevidím.

ale Finder porovnava aktualnu polozku (subor, ci adresar) s obsahom pola $disallow len pre adresare.

Ok, upravím aby porovnával i pro soubory.

viktorc
Člen | 21
+
0
-

Viac autoloadingov nepouzivam. Problem je len ked sa prekryju nazvy vynimiek z Utils/exceptions.php.

Vtedy Ladenka vypise:
„Compile Error
Cannot redeclare class ArgumentOutOfRangeException“ (nezavisle od toho, ktora trieda je problem).

namiesto predpokladaneho:
„InvalidStateException
Ambiguous class…“

Ak je v addClass zakomentovane spl_autoload_call, vypise sa korektna vynimka so spravnym popisom duplicity. Ak to tam vsak musi z nejakeho dovodu zostat, tak to tam samozrejme nechaj. Toto sa asi prilis casto neprejavi.

Pri inych triedach, alebo vynimkach Nette to funguje spravne vzdy (aspon co som skusal).

David Grudl
Nette Core | 8228
+
0
-

Tu chybu nepíše robotloader, ale vzniká při načítání skriptu přes require. Vyvolá jej zřejmě druhý autoloader, což může být i NetteLoader. Řešením je neindexovat duplicitní třídy a třeba zmíněný soubor zakázat přes netterobots.txt

David Grudl
Nette Core | 8228
+
0
-

Omlouvám, ta chyba v překlepu $class → $lClass tam skutečně byla, opraveno.

Upravil jsem RobotLoader tak, aby nemusel spl_autoload_call volat (to byl hack pro PHP 5.2, kde nelze při autoloadingu vyhodit výjimku). Tak to snad už bude fungovat OK.

viktorc
Člen | 21
+
0
-

Potom by to uz mohlo byt ok, diky ;-)