Voici comment je charge automatiquement toutes les classes de mon dossier controllers
,
# auto load controller classes
function __autoload($class_name)
{
$filename = 'class_'.strtolower($class_name).'.php';
$file = AP_SITE.'controllers/'.$filename;
if (file_exists($file) == false)
{
return false;
}
include ($file);
}
Mais j'ai aussi des classes dans le dossier models
et je veux aussi les charger automatiquement - que dois-je faire? Dois-je dupliquer le chargement automatique ci-dessus et simplement changer le chemin d'accès en models/
(mais n'est-ce pas répétitif ??)?
Merci.
MODIFIER:
ce sont mes noms de fichiers de classes dans le dossier du contrôleur:
class_controller_base.php
class_factory.php
etc
ce sont mes noms de fichiers de classes dans le dossier modèle:
class_model_page.php
class_model_parent.php
etc
c'est ainsi que je nomme ma classe de classes de contrôleur habituellement (j'utilise des traits de soulignement et des lowcaps),
class controller_base
{
...
}
class controller_factory
{
...
}
c'est ainsi que je nomme généralement ma classe de classes de modèles (j'utilise des traits de soulignement et des lowcaps),
class model_page
{
...
}
class model_parent
{
...
}
Vous devez nommer vos classes pour que le trait de soulignement (_
) Se traduise par le séparateur de répertoire (/
). Quelques frameworks PHP font cela, comme Zend et Kohana.
Donc, vous nommez votre classe Model_Article
Et placez le fichier dans classes/model/article.php
, Puis votre chargement automatique fait ...
function __autoload($class_name)
{
$filename = str_replace('_', DIRECTORY_SEPARATOR, strtolower($class_name)).'.php';
$file = AP_SITE.$filename;
if ( ! file_exists($file))
{
return FALSE;
}
include $file;
}
Notez également que vous pouvez utiliser spl_autoload_register()
pour faire de n'importe quelle fonction une fonction de chargement automatique. Il est également plus flexible, vous permettant de définir plusieurs fonctions de type de chargement automatique.
S'il doit y avoir plusieurs fonctions de chargement automatique, spl_autoload_register () le permet. Il crée efficacement une file d'attente de fonctions de chargement automatique et parcourt chacune d'elles dans l'ordre où elles sont définies. En revanche, __autoload () ne peut être défini qu'une seule fois.
Modifier
Remarque: __ autoload a été DÉCONSEILLÉ à partir de PHP 7.2.0. cette fonctionnalité est fortement déconseillée. Veuillez vous référer à la documentation PHP pour plus de détails. http://php.net/manual/en/function.autoload.php
Je vois que vous utilisez controller_*****
Et model_*****
Comme convention de dénomination de classe.
J'ai lu un fantastique article , qui suggère une convention de nommage alternative en utilisant namespace
de php.
J'adore cette solution car peu importe où je mets mes cours. Le __autoload
Le trouvera peu importe où il se trouve dans ma structure de fichiers. Cela me permet également d'appeler mes cours comme je veux. Je n'ai pas besoin d'une convention de dénomination de classe pour que mon code fonctionne.
Vous pouvez, par exemple, configurer votre structure de dossiers comme:
Vos cours peuvent être organisés comme ceci:
<?php
namespace application\controllers;
class Base {...}
et:
<?php
namespace application\models;
class Page {...}
L'autochargeur pourrait ressembler à ceci (ou voir "une note sur le chargement automatique" à la fin):
function __autoload($className) {
$file = $className . '.php';
if(file_exists($file)) {
require_once $file;
}
}
Ensuite ... vous pouvez appeler des classes de trois manières:
$controller = new application\controllers\Base();
$model = new application\models\Page();
ou,
<?php
use application\controllers as Controller;
use application\models as Model;
...
$controller = new Controller\Base();
$model = new Model\Page();
ou,
<?php
use application\controllers\Base;
use application\models\Page;
...
$controller = new Base();
$model = new Page();
EDIT - une note sur le chargement automatique:
Mon chargeur automatique principal ressemble à ceci:
// autoload classes based on a 1:1 mapping from namespace to directory structure.
spl_autoload_register(function ($className) {
# Usually I would just concatenate directly to $file variable below
# this is just for easy viewing on Stack Overflow)
$ds = DIRECTORY_SEPARATOR;
$dir = __DIR__;
// replace namespace separator with directory separator (prolly not required)
$className = str_replace('\\', $ds, $className);
// get full name of file containing the required class
$file = "{$dir}{$ds}{$className}.php";
// get file if it is readable
if (is_readable($file)) require_once $file;
});
Cet autochargeur est un mappage direct 1: 1 du nom de la classe à la structure du répertoire; l'espace de noms est le chemin du répertoire et le nom de classe est le nom de fichier. Ainsi, la classe application\controllers\Base()
définie ci-dessus chargerait le fichier www/application/controllers/Base.php
.
J'ai mis l'autochargeur dans un fichier, bootstrap.php, qui se trouve dans mon répertoire racine. Cela peut être soit inclus directement, soit php.ini peut être modifié en auto_prepend_file afin qu'il soit inclus automatiquement à chaque demande.
En utilisant spl_autoload_register vous pouvez enregistrer plusieurs fonctions de chargement automatique pour charger les fichiers de classe comme vous le souhaitez. C'est-à-dire, vous pouvez mettre tout ou partie de vos classes dans un répertoire, ou vous pouvez mettre tout ou partie de vos classes à espace de noms dans le même fichier . Très souple :)
Je dois mentionner quelque chose sur les "bons" scripts de chargement automatique et la structure du code, alors lisez ATTENTIVEMENT ce qui suit
Garder en tete:
par exemple: Example.php contient
class Example {}
par exemple: /Path1/Path2/Example.php correspond
namespace Path1\Path2;
class Example {}
par exemple: /Path1/Path2/Example.php avec root:
namespace APP\Path1\Path2;
class Example {}
Dans cet esprit, j'ai produit le script suivant:
function Loader( $Class ) {
// Cut Root-Namespace
$Class = str_replace( __NAMESPACE__.'\\', '', $Class );
// Correct DIRECTORY_SEPARATOR
$Class = str_replace( array( '\\', '/' ), DIRECTORY_SEPARATOR, __DIR__.DIRECTORY_SEPARATOR.$Class.'.php' );
// Get file real path
if( false === ( $Class = realpath( $Class ) ) ) {
// File not found
return false;
} else {
require_once( $Class );
return true;
}
}
Où le placer ..
Rappelez-vous:
Bon codage ;-)
Un petit examen des autres réponses: CECI IS JUSTE MON AVIS PERSONNEL - AUCUNE INFRACTION VISÉE!
https://stackoverflow.com/a/5280353/626731 @alex bonne solution, mais ne vous faites pas payer les noms de classe pour les mauvaises structures de fichiers ;-) c'est du travail pour les espaces de noms
https://stackoverflow.com/a/5280510/626731 @ Mark-Eirich ça marche, mais son style assez méchant/laid/lent/raide [..] pour le faire de cette façon ..
https://stackoverflow.com/a/5284095/626731 @tealou pour que son problème soit résolu, c'est l'approche la plus claire à ce jour :-) ..
https://stackoverflow.com/a/9628060/626731 @ br3nt cela reflète mon point de vue, mais s'il vous plaît (!) .. n'utilisez pas strtr !! .. ce qui m'amène à:
https://stackoverflow.com/a/11866307/626731 @Iscariot .. à vous, un petit "benchmark de vous-savez-bullshit:"
Time sprintf preg_replace strtr str_replace v1 str_replace v2
08:00:00 AM 1.1334 2.0955 48.1423 1.2109 1.4819
08:40:00 AM 1.0436 2.0326 64.3492 1.7948 2.2337
11:30:00 AM 1.1841 2.5524 62.0114 1.5931 1.9200
02:00:00 PM 0.9783 2.4832 52.6339 1.3966 1.4845
03:00:00 PM 1.0463 2.6164 52.7829 1.1828 1.4981
Average 1.0771 2.3560 55.9839 1.4357 1.7237
Method Times Slower (than sprintf)
preg_replace 2.19
strtr 51.97
str_replace v1 1.33
str_replace v2 1.6
Source: http://www.simplemachines.org/community/index.php?topic=175031.
Questions? .. (Mais il a en fait raison sur le chemin complet, y compris)
https://stackoverflow.com/a/12548558/626731 @ Sunil-Kartikey https://stackoverflow.com/a/17286804/626731 @jurrien
NE JAMAIS boucler dans un environnement à temps critique! Ne recherchez pas de fichiers sur os! - LENT
https://stackoverflow.com/a/21221590/626731 @sagits .. bien mieux que Marks ;-)
function autoload($className)
{
//list comma separated directory name
$directory = array('', 'classes/', 'model/', 'controller/');
//list of comma separated file format
$fileFormat = array('%s.php', '%s.class.php');
foreach ($directory as $current_dir)
{
foreach ($fileFormat as $current_format)
{
$path = $current_dir.sprintf($current_format, $className);
if (file_exists($path))
{
include $path;
return ;
}
}
}
}
spl_autoload_register('autoload');
Voici ma solution,
/**
* autoload classes
*
*@var $directory_name
*
*@param string $directory_name
*
*@func __construct
*@func autoload
*
*@return string
*/
class autoloader
{
private $directory_name;
public function __construct($directory_name)
{
$this->directory_name = $directory_name;
}
public function autoload($class_name)
{
$file_name = 'class_'.strtolower($class_name).'.php';
$file = AP_SITE.$this->directory_name.'/'.$file_name;
if (file_exists($file) == false)
{
return false;
}
include ($file);
}
}
# nullify any existing autoloads
spl_autoload_register(null, false);
# instantiate the autoloader object
$classes_1 = new autoloader('controllers');
$classes_2 = new autoloader('models');
# register the loader functions
spl_autoload_register(array($classes_1, 'autoload'));
spl_autoload_register(array($classes_2, 'autoload'));
Je ne sais pas si c'est la meilleure solution ou non mais cela semble fonctionner parfaitement ...
Qu'est-ce que tu penses??
Ma version de @Mark Eirich répond:
function myload($class) {
$controllerDir = '/controller/';
$modelDir = '/model/';
if (strpos($class, 'controller') !== false) {
$myclass = $controllerDir . $class . '.php';
} else {
$myclass = $modelDir . $class . '.inc.php';
}
if (!is_file($myclass)) return false;
require_once ($myclass);
}
spl_autoload_register("myload");
Dans mon cas, seule la classe de contrôleur a le mot-clé dans son nom, adaptez-le à vos besoins.
Réponse la plus simple que je puisse vous donner sans écrire ces codes complexes et même sans utiliser l'espace de noms (si cela vous embrouille)
Exemple de code. Fonctionne à 100%.
function __autoload($class_name){
$file = ABSPATH . 'app/models/' . $class_name . '.php';
if(file_exists($file)){
include $file;
}else{
$file = ABSPATH . 'app/views/' . $class_name . '.php';
if(file_exists($file)){
include $file;
}else{
$file = ABSPATH . 'app/controllers/' . $class_name . '.php';
include $file;
}
}
Je suppose que la logique est explicable en elle-même. Vive mec! J'espère que cela t'aides :)
Voici ce que je ferais:
function __autoload($class_name) {
$class_name = strtolower($class_name);
$filename = 'class_'.$class_name.'.php';
if (substr($class_name, 0, 5) === 'model') {
$file = AP_SITE.'models/'.$filename;
} else $file = AP_SITE.'controllers/'.$filename;
if (!is_file($file)) return false;
include $file;
}
Tant que vous nommez vos fichiers de manière cohérente, comme class_controller_*.php
et class_model_*.php
, cela devrait fonctionner correctement.
La fonction __autoload () ne doit pas être utilisée car elle n'est pas encouragée. Utilisez plutôt spl_autoload (), spl_autoload_register (). __autoload () ne peut charger qu'une classe mais spl_autoload () peut obtenir plus de 1 classes. Et une chose de plus, à l'avenir, __autoload () pourrait devenir obsolète. Plus de choses peuvent être trouvées sur http://www.php.net/manual/en/function.spl-autoload.php
Même si ce script n'a pas la convention de nom et ce fil est déjà un peu vieux, au cas où quelqu'un chercherait une réponse possible, voici ce que j'ai fait:
function __autoload($name) {
$dirs = array_filter(glob("*"), 'is_dir');
foreach($dirs as $cur_dir) {
dir_searcher($cur_dir, $name);
}
}
function dir_searcher($cur_dir, $name) {
if(is_file("$cur_dir/$name.php")) {
require_once "$cur_dir/$name.php";
}
$dirs = array_filter(glob($cur_dir."/*"), 'is_dir');
foreach($dirs as $cdir) {
dir_searcher("$cdir", $name);
}
}
je ne sais pas si c'est vraiment optimal, mais il recherche dans les dossiers en lisant dir récursivement. Avec une fonction créative str_replace, vous pouvez obtenir votre convention de nom.
J'utilise ça. Définissez fondamentalement votre structure de dossiers (MVC, etc.) comme une constante dans un tableau sérialisé. Appelez ensuite le tableau dans votre classe de chargement automatique. Fonctionne efficacement pour moi.
Vous pouvez évidemment créer le tableau de dossiers à l'aide d'une autre fonction, mais pour MVC, vous pouvez également le saisir manuellement.
Pour que cela fonctionne, vous devez appeler vos classes ...... class.classname.php
//in your config file
//define class path and class child folders
define("classPath","classes");
define("class_folder_array", serialize (array ("controller", "model", "view")));
//wherever you have your autoload class
//autoload classes
function __autoload($class_name) {
$class_folder_array = unserialize (class_folder_array);
foreach ($class_folder_array AS $folder){
if(file_exists(classPath."/".$folder.'/class.'.$class_name.'.php')){require_once classPath."/".$folder.'/class.'.$class_name.'.php';break;}
}
}
Tout le monde copie et colle des choses à partir du code qu'ils ont obtenu sur Internet (à l'exception de la réponse sélectionnée). Ils utilisent tous String Replace.
Le remplacement de chaîne est 4 fois plus lent que strtr. Vous devriez l'utiliser à la place.
Vous devez également utiliser des chemins d'accès complets lorsque vous incluez des classes avec le chargement automatique car le système d'exploitation met moins de temps à résoudre le chemin d'accès.