Přejít k navigační liště

Zdroják » PHP » Symfony po krůčkách – ClassLoader

Symfony po krůčkách – ClassLoader

Články PHP

Pokud chceme psát v naší PHP aplikaci hezky objektově, je třeba ty objekty (třídy) nějak načítat. Bezpochyby každý z vás někdy přemýšlel, jak to udělat nejlépe. Symfony k tomu nabízí komponentu ClassLoader.

Nálepky:

Snad každý někdy řešil, jak nejlépe načítat třídy v PHP. Pamatuji si začátky a psaní require_once pro všechny classy do bootstrap souborů.

// boostrap.php
require_once __DIR__ . '/src/App.php';
...

Později spl_autoload_register  a další „vylepšení“ první ukázky. Toto vše bylo samozřejmě ještě předtím, než přišel Composer a stačilo napsat pouze

require_once __DIR__ . '/vendor/autoload.php';

O víc se už nemusíte starat. Tedy, pokud dodržujete alespoň nějaký standard (PSR-0 nebo PSR-4). Stačí pouze dobře nastavit composer.json.

// composer.json
...
"autoload": {
    "psr-4": {
        "MF\\": "src/"
    }
},
...

Composer autoload vs Symfony ClassLoader

Určitě se tedy ptáte, proč zmiňuji Symfony ClassLoader, když už jsem vlastně řekl, že celý problém vyřešil autoload od Composeru. Máte pravdu – Composer autoloader řeší celou situaci ohledně načítání tříd sám. A řekl bych, že skvěle.

Proč tedy používat Symfony ClassLoader komponentu?

Upřímně – nevím. Nenašel jsem žádný rozumný důvod pro běžné aplikace.

Napadlo mě ale několik důvodů, proč by to přece jen mohl být dobrý nápad:

  1. nemůžete nebo nechcete z nějakého důvodu používat Composer
  2. potřebujete řešit výkon autoloadování natolik, že ani Composer autoload (s optimize apod.) nestačí

Z mého pohledu tedy v 99% případů stačí composer autoload. Obvzláště pak, když autoloaderu pomůžete těmito příkazy:

$ composer dump-autoload --optimize
$ composer install --optimize-autoloader 

Ukázková aplikace

Pro ukázku jsem si připravil jednoduchou aplikaci na výpis „Hello world!„. Úmyslně jsem tuto banalitu rozdělil na více tříd, aby bylo co načítat. Na kód se můžete podívat na githubu.

├── README.md
├── composer.json
├── composer.lock
├── index.php
├── index_apc.php
├── index_apc_unregister.php
├── index_composer.php
├── index_map.php
├── index_psr4.php
├── index_wincache.php
├── index_xcache.php
├── src
│   ├── App.php
│   └── Render
│       ├── MessageRender.php
│       ├── Render.php
│       └── RenderInterface.php
└── src_psr0
    └── MF
        ├── App.php
        └── Render
            ├── MessageRender.php
            ├── Render.php
            └── RenderInterface.php
<?php
// index.php
require_once __DIR__ . '/vendor/symfony/class-loader/ClassLoader.php';

use MF\App;
use MF\Render\Render;
use Symfony\Component\ClassLoader\ClassLoader;

$loader = new ClassLoader();
$loader->addPrefix('MF', __DIR__ . '/src_psr0');
$loader->register();

$app = new App(new Render());

$app->renderResponse();

Třída App pouze zabaluje základní zpracování requestu.

Třída RenderInterface(resp. jeho implementace) se stará o samotné vypsání obsahu stránky – „Hello world!“.

Abychom mohli třídy používat, PHP script musí třídy znát. V index.php je vidět použití Symfony komponenty ClassLoader, o které tento článek pojednává. Různých implementací class loaderů od Symfony je víc a budu se jim jednotlivě věnovat dále.

Symfony class loadery

Nyní bych rád popsal jednotlivé implementace ClassLoaderů od Symfony – jejich použití, výhody a nevýhody.

Psr0 ClassLoader

Jak již z názvu vyplývá, Psr0 ClassLoader autoloaduje Psr0 strukturu – tzn: \{Vendor Name}\({Namespace}\)*{Class Name} . Použití Psr0 ClassLoaderu jste mohli vidět již na začátku článku.

// index.php
...
$loader = new ClassLoader();
$loader->addPrefix('MF', __DIR__ . '/src_psr0');
$loader->register();
...

Psr4 ClassLoader

Psr4 ClassLoader autoloaduje podle struktury Psr4 – tzn: \{NamespaceName}(\{SubNamespaceNames})*\{ClassName}. Použití je velmi podobné Psr0 ClassLoaderu.

// index_psr4.php
...
$loader = new Psr4ClassLoader();
$loader->addPrefix('MF', __DIR__ . '/src');
$loader->register();
...

MapClassLoader

Dovoluje vytvořit mapu tříd, podle které se bude autoloading řídit. Mapa je v podstatě klasické pole, ve kterém se definují cesty k souborům podle názvu tříd.

Hodí se hlavně na třídy třetích stran, které nepodporují Psr0/4.

Ve výchozím nastavení se MapClassLoader přidává až za ostatní autoloading. Pokud chcete použít MapClassLoader jako výchozí, předejte true do registrační metody. Pak bude MapClassLoader předán před ostatní autoloading.

// index_map.php
...
$loader = new MapClassLoader([
    'MF\\App' => __DIR__ . '/src/App.php',
    'MF\\Render\\RenderInterface' => __DIR__ . '/src/Render/RenderInterface.php',
    'MF\\Render\\Render' => __DIR__ . '/src/Render/Render.php',
]);
$loader->register();
...

Možná zrychlení

Použití autoloadingu v každém requestu může být zbytečně náročné. Proto je dobré skriptu ulehčit práci a výslednou mapu tříd si uložit do cache. K tomuto slouží cachovací třídy (ApcClassLoader, …). Je možné definovat i prefix pro cache, pro jednoduché dohledání / smazání.

Tyto třídy fungují jako adapter nad ClassLoadery, resp. nad čímkoliv, co implementuje metodu findFile($class). Pro ukázku jsem se rozhodl použít Psr4ClassLoader jako základní autoloading nástroj.

ApcClassLoader

ApcClassLoader potřebuje ke svému fungování PHP extensionu apc (Alternative PHP Cache).

// index_apc.php
...
$loader = new Psr4ClassLoader();
$loader->addPrefix('MF', __DIR__ . '/src');

$loader = new ApcClassLoader('apc.prefix', $loader);
$loader->register();
...

XCacheClassLoader

XCacheClassLoader využívá k ukládání xcache.

// index_xcache.php
...
$loader = new Psr4ClassLoader();
$loader->addPrefix('MF', __DIR__ . '/src');

$loader = new XcacheClassLoader('cache.prefix', $loader);
$loader->register();
...

WinCacheClassLoader

WinCacheClassLoader, stejně jako dvě předchozí instance, potřebuje PHP extensionu wincache. Tato implementace slouží k použití PHP na Windows.

// index_wincache.php
...
$loader = new Psr4ClassLoader();
$loader->addPrefix('MF', __DIR__ . '/src');

$loader = new WinCacheClassLoader('cache.prefix', $loader);
$loader->register();
...

Co jsme si dnes ukázali

  • rozdíl mezi Composer autoloadem a Symfony ClassLoaderem
  • jednoduché použití ClassLoaderů od Symfony
  • případné možnosti zrychlení (cachování)

Pokud byste se chtěli podívat na ClassLoader podrobněji, můžete využít dokumentaci, kde najdete více informací.

Komentáře

Odebírat
Upozornit na
guest
1 Komentář
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
Zobrazit všechny komentáře
Jáchym Toušek

Composer autoloding lze ještě trochu vylepšit pomocí --classmap-authoritative.

Přístupnost není jen o splnění norem: nový pohled na inkluzivní design

Přístupnost a inkluze možná nepatří mezi nejžhavější témata digitálního světa – dokud o nich nezačne mluvit Vitaly Friedman. Na WebExpo 2024 předvedl, že inkluzivní design není jen o splněných checkboxech, ale hlavně o lidech. S energií sobě vlastní obrátil zažité přístupy naruby a ukázal, že skutečně přístupný web je nejen možný, ale i nezbytný.

Efektivnější vývoj UI nebo API: Co si odnést z WebExpo 2025?

Různé
Komentáře: 0
Jak snadno implementovat moderní uživatelské rozhraní? Které funkce brzdí rychlost vašeho webu? A kdy raději sami přibrzdit, abychom využitím AI nepřekročili etické principy? Debatu aktuálních dev témat rozdmýchá sedmnáctý ročník technologické konference WebExpo, která proběhne v Praze od 28. do 30. května. Který talk či workshop si rozhodně nenechat ujít? Toto je náš redakční výběr z vývojářských hroznů.

Zapřáhněte AI jako nikdy předtím. Květnová konference WebExpo přivítá hvězdy technologického světa

Od 28. do 30. května 2025 promění pražský Palác Lucerna na tři dny technologická konference WebExpo. Na programu je více než 80 přednášek a workshopů od expertů z celého světa. WebExpo tradičně propojuje vývojáře, designéry, marketéry i byznysové lídry a nabízí praktické dovednosti, strategické myšlení a přináší nejnovější trendy nejen v oblasti AI.