Vendor composer autoload classmap php

Автозагрузка классов для WordPress

Если вы используете у себя в проектах сотни require или include , то вам точно стоит прочесть эту статью.

Зачем нужна автозагрузка?

Автозагрузка (autoload) нужна для того, чтобы навсегда избавится от require, include и постоянного изменения порядка их подключения.

Рассмотрим два вариант autoload:

Autoload своих классов через composer

В файл composer.json нужно добавить директиву autoload и в нее classmap с перечнем папок, в которых нужно искать классы, интерфейсы и прочее.

После этого нужно обязательно обновить autoload composer’а с помощью следующей команды:

После этого в /vendor/composer/autoload_classmap.php появляется массив ключ=значение, где ключ — это полное название класса, а значение — это путь к данному классу. Сам файл выглядит примерно так:

// autoload_classmap.php @generated by Composer $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( 'My_Namespace\\Example1' => $baseDir . '/folder1/class-example1.php', 'My_Namespace\\Example2' => $baseDir . '/folder2/class-example2.php', );

Свой автозагрузчик с помощью spl_autoload

Иногда проект может быть достаточно большой включать в себя плагины, mu-плагины и темы. При работе с мультисайтом/ами вполне возможна такая ситуация.

Столкнувшись с такой проблемой, решил сделать небольшой mu-плагин, который будет подгружать все нужные мне файлы сам. Решил отойти от composer’а, чтобы не тянуть его везде, где он мне нужен.

Меняем namespace на путь к файлу

Следующий пример написан с соблюдением WPCS:

class Autoload < private $prefix = 'My_Namespace'; public function __construct() < spl_autoload_register( [ $this, 'autoload' ] ); >private function autoload( string $class ): void < if ( 0 === strpos( $class, $this->prefix ) ) < $plugin_parts = explode( '\\', $class ); $name = array_pop( $plugin_parts ); $name = preg_match( '/^(Interface|Trait)/', $name ) ? $name . '.php' : 'class-' . $name . '.php'; $path = implode( '/', $plugin_parts ) . '/' . $name; $path = strtolower( str_replace( [ '\\', '_' ], [ '/', '-' ], $path ) ); $path = WP_CONTENT_DIR . '/plugins/' . $path; require_once $path; >> > new Autoload();

С помощью ф-ции spl_autoload_register мы добавляем autoload, который будет срабатывать каждый раз, когда вызывается неизвестная ф-ция, класс или интерфейс.

Обязательно проверяем на то, чтобы все классы начинались с $this->prefix, который в примере My_Namespace. Затем формируем нужный путь к файлу и подключаем его. Все вроде бы хорошо, но есть одна проблема с тем, что при большом кол-ве классов слишком много действий вместо просто подключения файлов. Для этого нужно сделать механизм кеширования. Попробуем сделать что-то, вроде classmap от composer’а.

Classmap для spl_autoload

class Autoload < private $map_file; private $map; private $prefix = 'My_Namespace'; private $has_been_update = false; public function __construct() < $this->map_file = __DIR__ . '/classmap.php'; $this->map = @include $this->map_file; $this->map = is_array( $this->map ) ? $this->map : []; spl_autoload_register( [ $this, 'autoload' ] ); add_action( 'shutdown', [ $this, 'update_cache' ] ); > private function autoload( string $class ): void < if ( 0 === strpos( $class, $this->prefix ) ) < if ( $this->map[ $class ] && file_exists( $this->map[ $class ] ) ) < require_once $this->map[ $class ]; > else < $this->has_been_update = true; $plugin_parts = explode( '\\', $class ); $name = array_pop( $plugin_parts ); $name = preg_match( '/^(Interface|Trait)/', $name ) ? $name . '.php' : 'class-' . $name . '.php'; $path = implode( '/', $plugin_parts ) . '/' . $name; $path = strtolower( str_replace( [ '\\', '_' ], [ '/', '-' ], $path ) ); $path = WP_CONTENT_DIR . '/plugins/' . $path; $this->map[ $class ] = $path; require_once $path; > > > public function update_cache(): void < if ( ! $this->has_been_update ) < return; >$map = implode( "\n", array_map( function ( $k, $v ) < return "'$k' =>'$v',"; >, array_keys( $this->map ), array_values( $this->map ) ) ); file_put_contents( $this->map_file, ' >
  • $map_file — путь к файлу classmap
  • $map — classmap
  • $has_been_update — свойство, которое проверяет обновился ли classmap с последней загрузки страницы.

Метод autoload немного поменялся. Вот основные отличия:

if ( $this->map[ $class ] && file_exists( $this->map[ $class ] ) ) < // Подключаем файл, который мы нашли в classmap. Проверка file_exists нужна на случай, если мы захотим удалить, переместить или переименовать файл. >else < $this->has_been_update = true; // classmap нужно обновить . $this->map[ $class ] = $path; // Обновляем classmap . >

В метод update_cache, который срабатывает на событие shutdown обновляем сам файл classmap’а, если он был изменен с последней загрузки.

Источник

PHP Composer Autoload

Summary: in this tutorial, you’ll learn how to use Composer to autoload PHP classes from files using PSR-4 standard.

Loading classes using the require_once construct

First, create the following directory structure with files:

. ├── app │ ├── bootstrap.php │ └── models │ └── User.php └── index.phpCode language: PHP (php)

The User.php file in the models folder holds the User class:

 class User < private $username; private $password; public function __construct($username, $password) < $this->username = $username; $this->password = password_hash($password); > public function getUsername(): string < return $this->username; > >Code language: PHP (php)

The User is a simple class. It has two properties $username and $password . The constructor initializes the properties from its arguments. Also, it uses the password_hash() function to hash the $password .

The bootstrap.php file uses the require_once construct to load the User class from the User.php file in the models folder:

 require_once 'models/User.php';Code language: PHP (php)

When you have more classes in the models folder, you can add more require_once statement to the bootstrap.php file to load those classes.

The index.php file loads the bootstrap.php file and uses the User class:

 require './app/bootstrap.php'; $user = new User('admin', '$ecurePa$$w0rd1');Code language: PHP (php)

This application structure works well if you have a small number of classes. However, when the application has a large number of classes, the require_once doesn’t scale well. In this case, you can use the spl_autoload_register() function to automatically loads the classes from their files.

The problem with the spl_autoload_register() function is that you have to implement the autoloader functions by yourself. And your autoloaders may not like autoloaders developed by other developers.

Therefore, when you work with a different codebase, you need to study the autoloaders in that particular codebase to understand how they work.

This is why Composer comes into play.

Introduction to the Composer

Composer is a dependency manager for PHP. Composer allows you to manage dependencies in your PHP project. In this tutorial, we’ll focus on how to use the Composer for autoloading classes.

Before using Composer, you need to download and install it. The official documentation provides you with the detailed steps of how to download and install Composer on your computer.

To check whether the Composer installed successfully, you run the following command from the Command Prompt on Windows or Terminal on macOS and Linux:

composer -vCode language: PHP (php)

It’ll return the current version and a lot of options that you can use with the composer command.

Autoloading classes with Composer

Back the the previous example, to use the Composer, you first create a new file called composer.json under the project’s root folder. The project directory will look like this:

. ├── app │ ├── bootstrap.php │ └── models │ └── User.php ├── composer.json └── index.phpCode language: PHP (php)

In the composer.json , you add the following code:

< "autoload": < "classmap": ["app/models"] > >Code language: PHP (php)

This code means that Composer will autoload all class files defined the app/models folder.

If you have classes from other folders that you want to load, you can specify them in classmap array:

 < "autoload": < "classmap": ["app/models", "app/services"] > >Code language: PHP (php)

In this example, Composer will load classes from both models and services folders under the app folder.

Next, launch the Command Prompt on Windows or Terminal on macOS and Linux, and navigate to the project directory.

Then, type the following command from the project directory:

composer dump-autoloadCode language: PHP (php)

Composer will generate a directory called vendor that contains a number of files like this:

. ├── app │ ├── bootstrap.php │ └── models │ └── User.php ├── composer.json ├── index.php └── vendor ├── autoload.php └── composer ├── autoload_classmap.php ├── autoload_namespaces.php ├── autoload_psr4.php ├── autoload_real.php ├── autoload_static.php ├── ClassLoader.php └── LICENSECode language: PHP (php)

The most important file to you for now is autoload.php file.

After that, load the autoload.php file in the bootstrap.php file using the require_once construct:

 require_once __DIR__ . '/../vendor/autoload.php';Code language: PHP (php)

Finally, you can use the User class in the index.php :

 require './app/bootstrap.php'; $user = new User('admin', '$ecurePa$$w0rd1');Code language: PHP (php)

From now, whenever you have a new class in the models directory, you need to run the command composer dump-autoload again to regenerate the autoload.php file.

For example, the following defines a new class called Comment in the Comment.php file under the models folder:

 class Comment < private $comment; public function __construct(string $comment) < $this->comment = $comment; > public function getComment(): string < return strip_tags($this->comment); > >Code language: PHP (php)

If you don’t run the composer dump-autoload command and use the Comment class in the index.php file, you’ll get an error:

 require './app/bootstrap.php'; $user = new User('admin', '$ecurePa$$w0rd1'); $comment = new Comment('

Hello

'
); echo $comment->getComment();
Code language: PHP (php)
Fatal error: Uncaught Error: Class 'Comment' not found in. Code language: PHP (php)

However, if you run the composer dump-autoload command again, the index.php file will work properly.

Composer autoload with PSR-4

PSR stands for PHP Standard Recommendation. PSR is a PHP specification published by the PHP Framework Interop Group or PHP-FIG.

The goals of PSR are to enable interoperability of PHP components and to provide a common technical basis for the implementation of best practices in PHP programming.

PHP-FIG has published a lot of PSR starting from PSR-0. For a complete list of PSR, check it out the PSR page.

PSR-4 is auto-loading standard that describes the specification for autoloading classes from file paths. https://www.php-fig.org/psr/psr-4/

According to the PSR-4, a fully qualified class name has the following structure:

The structure starts with a namespace, followed by one or more sub namespaces, and the class name.

To comply with PSR-4, you need to structure the previous application like this:

. ├── app │ ├── Acme │ │ ├── Auth │ │ │ └── User.php │ │ └── Blog │ │ └── Comment.php │ └── bootstrap.php ├── composer.json └── index.phpCode language: PHP (php)

The new structure has the following changes:

First, the models directory is deleted.

Second, the User.php is under the Acme/Auth folder. And the User class is namespaced with Acme/Auth . Notice how namespaces map to the directory structure. This also helps you find a class file more quickly by looking at its namespace.

 namespace Acme\Auth; class User < // implementation // . >Code language: PHP (php)

Third, the Comment.php is under the Acme/Blog folder. The Comment class has the namespace Acme\Blog :

 namespace Acme\Blog; class Comment < // implementation // . >Code language: PHP (php)

Fourth, the composer.json file looks like the following:

< "autoload": < "psr-4": < "Acme\\":"app/Acme" > > >Code language: PHP (php)

Instead using the classmap , the composer.json file now uses psr-4 . The psr-4 maps the namespace «Acme\\» to the «app/Acme» folder.

Note that the second backslash ( \ ) in the Acme\ namespace is used to escape the first backslash ( \ ).

Fifth, to use the User and Comment classes in the index.php file, you need to run the composer dump-autoload command to generate the autoload.php file:

composer dump-autoloadCode language: PHP (php)

Since the User and Comment classes have namespaces, you need to have the use statements in index.php as follows:

 require './app/bootstrap.php'; use Acme\Auth\User as User; use Acme\Blog\Comment as Comment; $user = new User('admin', '$ecurePa$$w0rd1'); $comment = new Comment('

Hello

'
); echo $comment->getComment();
Code language: PHP (php)

Summary

  • Composer is a dependency management tool in PHP.
  • Use PSR-4 for organizing directory and class files.
  • Use the composer dump-autoload command to generate the autoload.php file.

Источник

Читайте также:  Тип данных файл java
Оцените статью