web-dev-qa-db-fra.com

Meilleure façon de charger automatiquement les classes dans PHP

Je travaille sur un projet par lequel j'ai la structure de fichiers suivante:

index.php
|---lib
|--|lib|type|class_name.php
|--|lib|size|example_class.php

Je voudrais charger automatiquement les classes, nom_classe et classe_exemple (nommées de la même manière que les classes PHP), afin que dans index.php les classes soient déjà instanciées afin que je puisse faire:

$class_name->getPrivateParam('name');

J'ai jeté un œil sur le net mais je ne trouve pas vraiment la bonne réponse - quelqu'un peut-il m'aider?

MODIFIER

Merci pour les réponses. Permettez-moi de développer mon scénario. J'essaie d'écrire un plugin WordPress qui peut être déposé dans un projet et des fonctionnalités supplémentaires ajoutées en déposant une classe dans un dossier "fonctionnalité" par exemple, à l'intérieur du plugin. Il n'y aura jamais 1000 classes, à un Push peut-être 10?

Je pouvais écrire une méthode pour parcourir la structure de dossiers du dossier "lib", y compris chaque classe, puis l'attribuer à une variable (du nom de la classe), mais je ne pensais pas que c'était un moyen très efficace de le faire, mais il semble peut-être que c'est la meilleure façon d'atteindre ce dont j'ai besoin?

21
Sjwdavies

S'il vous plaît, si vous avez besoin de charger automatiquement des classes - utilisez les espaces de noms et les conventions de noms de classe avec le chargement automatique SPL, cela vous fera gagner du temps pour la refactorisation. Et bien sûr, vous devrez instancier chaque classe en tant qu'objet. Merci.

Comme dans ce fil: chargement automatique PHP dans les espaces de noms

Mais si vous souhaitez une solution de contournement complexe, veuillez jeter un œil à la classe de chargement automatique de Symfony: https://github.com/symfony/ClassLoader/blob/master/ClassLoader.php

Ou comme ça (je l'ai fait dans l'un de mes projets):

<?
spl_autoload_register(function($className)
{
    $namespace=str_replace("\\","/",__NAMESPACE__);
    $className=str_replace("\\","/",$className);
    $class=CORE_PATH."/classes/".(empty($namespace)?"":$namespace."/")."{$className}.class.php";
    include_once($class);
});
?>

puis vous pouvez instancier votre classe comme ceci:

<?
$example=new NS1\NS2\ExampleClass($exampleConstructParam);
?>

et voici votre classe (trouvée dans /NS1/NS2/ExampleClass.class.php):

<?
namespace NS1\NS2
{
    class Symbols extends \DB\Table
    {
        public function __construct($param)
        {
            echo "hello!";
        }
    }
}
?>
31
Serge Velikanov

Si vous avez accès à la ligne de commande, vous pouvez l'essayer avec composer dans la section classMap avec quelque chose comme ceci:

{
    "autoload": {
        "classmap": ["yourpath/", "anotherpath/"]
    }
}

alors vous avez un plugin wordpress pour activer composer dans le wordpress cli: http: // wordpress .org/plugins/composer /

10
lilobase

http://php.net/manual/de/function.spl-autoload-register.php

spl_autoload_register(function ($class) {
    @require_once('lib/type/' . $class . '.php');   
    @require_once('lib/size/' . $class . '.php');
});
3
Daniel W.
function __autoload($class_name) {
   $class_name = strtolower($class_name);
   $path       = "{$class_name}.php";
   if (file_exists($path)) {
       require_once($path);
   } else {
       die("The file {$class_name}.php could not be found!");
   }
}

MISE À JOUR:__autoload() est obsolète à partir de PHP 7.2

3
Hassan Azimi

J'ai ici un exemple que j'utilise pour le chargement automatique et l'initialisation.
Fondamentalement, une meilleure version de spl_autoload_register car elle essaie uniquement d'exiger le fichier de classe chaque fois que vous initialisez la classe.
Ici, il récupère automatiquement chaque fichier dans votre dossier de classe, requiert les fichiers et l'initialise. Il vous suffit de nommer la classe de la même manière que le fichier.
index.php

<?php
require_once __DIR__ . '/app/autoload.php';

$loader = new Loader(false);

User::dump(['hello' => 'test']);

autoload.php

<?php
class Loader 
{

    public static $library;

    protected static $classPath = __DIR__ . "/classes/";

    protected static $interfacePath = __DIR__ . "/classes/interfaces/";

    public function __construct($requireInterface = true) 
    {
        if(!isset(static::$library)) {
            // Get all files inside the class folder
            foreach(array_map('basename', glob(static::$classPath . "*.php", GLOB_BRACE)) as $classExt) {
                // Make sure the class is not already declared
                if(!in_array($classExt, get_declared_classes())) {
                    // Get rid of php extension easily without pathinfo
                    $classNoExt = substr($classExt, 0, -4); 
                    $file = static::$path . $classExt;

                    if($requireInterface) {
                        // Get interface file
                        $interface = static::$interfacePath . $classExt;
                        // Check if interface file exists
                        if(!file_exists($interface)) {
                            // Throw exception
                            die("Unable to load interface file: " . $interface);
                        }

                        // Require interface
                        require_once $interface;
                        //Check if interface is set
                        if(!interface_exists("Interface" . $classNoExt)) {
                            // Throw exception
                            die("Unable to find interface: " . $interface);
                        }
                    }

                    // Require class
                    require_once $file;
                    // Check if class file exists
                    if(class_exists($classNoExt)) {
                        // Set class        // class.container.php
                        static::$library[$classNoExt] = new $classNoExt();
                    } else {
                        // Throw error
                        die("Unable to load class: " . $classNoExt);
                    }

                }
            }
        }
    }

    /*public function get($class) 
    {
        return (in_array($class, get_declared_classes()) ? static::$library[$class] : die("Class <b>{$class}</b> doesn't exist."));
    }*/
}

Vous pouvez facilement gérer avec un peu de codage, pour exiger également des classes dans différents dossiers.
J'espère que cela peut vous être utile.

2
anttwuan

Vous pouvez spécifier un chargement automatique adapté aux espaces de noms à l'aide de ce chargeur automatique.

<?php
spl_autoload_register(function($className) {
    $file = __DIR__ . '\\' . $className . '.php';
    $file = str_replace('\\', DIRECTORY_SEPARATOR, $file);
    if (file_exists($file)) {
        include $file;
    }
});

Assurez-vous que vous spécifiez correctement l'emplacement du fichier de classe.

Source

0
Supun Kavinda