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ší Nejvíce hlasů
Jáchym Toušek

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

Rok po Shai-Hulud: co se změnilo na npm a co musíte udělat do ledna

Před rokem začal registrem npm procházet samošířící červ Shai-Hulud. Od té doby se útoky na dodavatelský řetězec JavaScriptu staly pravidelnou záležitostí a npm postupně přepisuje pravidla publikování. Projdeme, co se za ten rok stalo, jak dnes bezpečně publikovat balíček, co musíte stihnout do ledna 2027 a jak se bránit jako uživatel balíčků.

Vercel zrychlil směrování v CDN. Překvapivě pomohly menší bloky

Vercel zrychlil směrování v CDN tím, že začal načítat víc dat najednou. U velkých webů mu po každém nasazení scházely v cache údaje o mnoha jednotlivých cestách, takže je musel opakovaně dohledávat. U nových bloků metadat Vercel naměřil o 91 % kratší dobu tohoto hledání v 99. percentilu. Cesta k výsledku ale vedla přes nečekané zjištění: příliš velký blok se při vyřizování požadavků nevyplatil.

GraphQL: Alternativa k REST API zblízka

Když se dnes navrhuje nové API, většina vývojářů automaticky sáhne po RESTu. Je to pochopitelné: REST je jednoduchý, dobře zdokumentovaný, podporují ho všechny jazyky a frameworky a většina z nás s ním pracuje léta. Přesto se v posledních letech stále častěji objevuje otázka, zda je REST vždy tou nejlepší volbou. Nejčastěji zmiňovanou alternativou je GraphQL, dotazovací jazyk pro API, který vznikl ve Facebooku a který dnes používají firmy jako GitHub, Shopify nebo Netflix.