require gedrag
Ik heb diverse child classes in diverse files
Ook heb ik diverse parrent classes ook in diverse files
Als ik nu dus bv een file require, met een class die gebruik maat van een parrent class, maar die file met die parrent class is nog nog niet toegevoegd middels een require, dan krijg ik gelijk toch al een error.
Ik vind dit vreemd omdat ik van die child class nog helemaal geen instantie van heb aangemaakt.
Wie kan mij dit gedrag een beetje uitleggen opdat ik dit kan begrijpen waarom ik dus toch die error krijg ondanks dat er geen instantie van de child class is aangemaakt nog.
Alvast bedankt.
Daarom krijg je een warning of een fatal error.
Bedankt voor je bericht.
Ok, dus er word een soort van voorcontrole gedaan?
Vind ik wel jammer, want ik krijg zo dus een fout terwijl als ik op een later moment de parrent class nog wel require, voordat ik dus wel een instantie aanmaak van de child class het dus goed zou kunnen werken.
Eigenlik zou ik dus een fout verwachten als ik de child class ga instantieren, en als de parrent clas dan niet gevonden zou worden.
Nu moet ik dus zorgen dat alle parrent classes dus echt eerst geladen worden voordat ik een class require die een parrent class extend.
Iets om dus rekening mee te houden :-)
spl_register_autoloader te kijken, of naar de magic __autoload() functie in PHP. Hiermee kun je een functie opzetten die, mocht de klasse nog niet gerequired zijn, de klasse alsnog required.
Ik raad je aan eens naar een Ik werk volledig ook met namespaces, en hiermee is het mij niet gelukt een goed werkende autoload functie te kunnen opzetten.
Ik heb dus uiteindelijk maar besloten om alles wat ik nodig heb gewoon echt via require in te laden.
Ik gebruik ook geen require_once omdat ik exact weet waar ik wat nodig heb, en dan ook de juiste classes require die nodig zijn.
PSR-0 standaards en je kunt het mooi gebruiken, je krijgt er zelfs een functie die perfect werkt.
Nu is dat alleen een losse functie, maar Symfony Project heeft er een ClassLoader component voor die je zo kan gebruiken: http://symfony.com/doc/current/components/class_loader.html
En ook ik heb ooit eens een ClassLoader gemaakt, gebaseerd op die van symfony: https://github.com/WouterJ/snakeMvc/tree/master/lib/snakeMvc/Loader
Ik werk ook volledig met namespaces, en dan lukt het perfect. Zorg dat je namespaces en de locatie van de klasse zich houden aan de Nu is dat alleen een losse functie, maar Symfony Project heeft er een ClassLoader component voor die je zo kan gebruiken: http://symfony.com/doc/current/components/class_loader.html
En ook ik heb ooit eens een ClassLoader gemaakt, gebaseerd op die van symfony: https://github.com/WouterJ/snakeMvc/tree/master/lib/snakeMvc/Loader
Want een autoloader is nog steeds wel gewenst. omdat ik dan niet zelf via reqiures alle files moet inserten.
Toevoeging op 25/03/2012 23:51:19:
Ik ben alleen bang dat het gebruik van usings dan wel teniet word gedaan, en dat ik dus altijd de volledige namespace moet gebruiken als ik een class wil instansieren.
Dus als ik bv dit gebruik in een totaal andere namespace:
use WebFrameWork\DomainLayer\UiTemplates\BaseTemplates\BasePage;
$basePage = new BasePage();
Hoe gebruik ik dit dan middels een autoloader?
Volgens mij was dit ook waar ik destijds tegen aanliep, en het maar had opgegeven toen :-)
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
class ClassLoader
{
public static function register()
{
spl_autoload_register(array(__CLASS__, 'loadClass'));
}
// 1 van onze autoloaders
public static function loadClass( $className )
{
echo $className; // even voor debuggen
}
}
ClassLoader::register();
use WebFrameWork\DomainLayer\UiTemplates\BaseTemplates\BasePage;
$basePage = new BasePage();
// ClassLoader::loadClass() echo:
// "WebFrameWork\DomainLayer\UiTemplates\BaseTemplates\BasePage"
?>
class ClassLoader
{
public static function register()
{
spl_autoload_register(array(__CLASS__, 'loadClass'));
}
// 1 van onze autoloaders
public static function loadClass( $className )
{
echo $className; // even voor debuggen
}
}
ClassLoader::register();
use WebFrameWork\DomainLayer\UiTemplates\BaseTemplates\BasePage;
$basePage = new BasePage();
// ClassLoader::loadClass() echo:
// "WebFrameWork\DomainLayer\UiTemplates\BaseTemplates\BasePage"
?>
De namespaces worden dus gewoon meegegeven. Als je hier vervolgens de PSR-0 functie aankoppelt heb je eigenlijk al je eigen simpele classloader:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
class ClassLoader
{
// register method
public static function loadClass( $className )
{
$path = self::getFilePath($className);
if( file_exists($path) )
require_once $path;
else
throw new LogicException(sprintf('Class %s does not exists in %s', $classame, $path));
}
public static function getFilePath( $className )
{
$className = ltrim($className, '\\');
$fileName = '';
$namespace = '';
if ($lastNsPos = strripos($className, '\\')) {
$namespace = substr($className, 0, $lastNsPos);
$className = substr($className, $lastNsPos + 1);
$fileName = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
}
$fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
return $fileName;
}
}
use WebFrameWork\DomainLayer\UiTemplates\BaseTemplates\BasePage;
$basePage = new BasePage();
// ClassLoader::loadClass() require_once:
// %path%/WebFrameWork/DomainLayer/UiTemplates/BaseTemplates/BasePage.php
?>
class ClassLoader
{
// register method
public static function loadClass( $className )
{
$path = self::getFilePath($className);
if( file_exists($path) )
require_once $path;
else
throw new LogicException(sprintf('Class %s does not exists in %s', $classame, $path));
}
public static function getFilePath( $className )
{
$className = ltrim($className, '\\');
$fileName = '';
$namespace = '';
if ($lastNsPos = strripos($className, '\\')) {
$namespace = substr($className, 0, $lastNsPos);
$className = substr($className, $lastNsPos + 1);
$fileName = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
}
$fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
return $fileName;
}
}
use WebFrameWork\DomainLayer\UiTemplates\BaseTemplates\BasePage;
$basePage = new BasePage();
// ClassLoader::loadClass() require_once:
// %path%/WebFrameWork/DomainLayer/UiTemplates/BaseTemplates/BasePage.php
?>
De classloaders van Symfony en die van mij zijn dan nog uitgebouwd met registered namespaces, prefixes en basepaths.
Ik zal dit dan vanavond gelijk even verder proberen, want ik kanteer wel ook die PSR-0 opbouw.
bedankt.
Toevoeging op 26/03/2012 21:46:58:
Tsjonge wat heb ik en spijt deze vraag niet eerder gesteld te hebben.
Ik heb het nu inderdaad werkend.
Je hoeft zelfs niet eens require_once te gebruiken, maar je kan gewoon require gebruiken
spl_autoload_register lijkt zelf al te herkennen of een class al is gedistantieerd en doet dan niet alsnog de file inserten.
Ik gebruik nu deze class voor mijn autoload functionaliteit, met grote dank aan Wouter.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?php
namespace WebFrameWork
{
defined("SCRIPT_EXEC_PERM") or die ("HTTP/1.0 401 Unauthorized");
class AutoLoader
{
/**
* @var string
*/
private $_basePath;
/**
* @param $basePath
*/
public function __construct($basePath)
{
$this->_basePath = $basePath;
spl_autoload_register(array(__CLASS__, 'AutoLoadClasses'));
}
public function __destruct()
{
unset($this);
}
/**
* @param $className
*/
private function AutoLoadClasses($className)
{
$path = $this->GetFullFilePath($this->_basePath ."/". $className);
if( file_exists($path) )
{
require($path);
}
else
{
die (sprintf('Class %s does not exists in %s', $className, $path));
}
}
/**
* @param $className
* @return string
*/
private function GetFullFilePath($className)
{
$className = ltrim($className, '\\');
$fileName = '';
$namespace = '';
if ($lastNsPos = strripos($className, '\\'))
{
$namespace = substr($className, 0, $lastNsPos);
$className = substr($className, $lastNsPos + 1);
$fileName = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
}
$fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
return $fileName;
}
}
}
?>
namespace WebFrameWork
{
defined("SCRIPT_EXEC_PERM") or die ("HTTP/1.0 401 Unauthorized");
class AutoLoader
{
/**
* @var string
*/
private $_basePath;
/**
* @param $basePath
*/
public function __construct($basePath)
{
$this->_basePath = $basePath;
spl_autoload_register(array(__CLASS__, 'AutoLoadClasses'));
}
public function __destruct()
{
unset($this);
}
/**
* @param $className
*/
private function AutoLoadClasses($className)
{
$path = $this->GetFullFilePath($this->_basePath ."/". $className);
if( file_exists($path) )
{
require($path);
}
else
{
die (sprintf('Class %s does not exists in %s', $className, $path));
}
}
/**
* @param $className
* @return string
*/
private function GetFullFilePath($className)
{
$className = ltrim($className, '\\');
$fileName = '';
$namespace = '';
if ($lastNsPos = strripos($className, '\\'))
{
$namespace = substr($className, 0, $lastNsPos);
$className = substr($className, $lastNsPos + 1);
$fileName = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
}
$fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
return $fileName;
}
}
}
?>
Toevoeging op 26/03/2012 21:55:48:
Ik weet nu ook wel weer dat ik het vroeger met de gewone autoload heb geprobeerd en niet met deze spl_autoload_register.
Ben erg blij dit nu ook voor elkaar te hebben, dit schoont de code mooi op ook van alle handmatige require's
Gewijzigd op 26/03/2012 21:49:10 door Eelco Alosery