PHP
Autoloading Primer
Sök…
Syntax
- fordra
- spl_autoload_require
Anmärkningar
Genom att automatiskt ladda in, som en del av en ramstrategi, underlättar du mängden pannplattkod du måste skriva.
Inline klassdefinition, ingen belastning krävs
// zoo.php
class Animal {
public function eats($food) {
echo "Yum, $food!";
}
}
$animal = new Animal();
$animal->eats('meat');
PHP vet vad Animal
är innan man kör ett new Animal
, för PHP läser källfiler från topp till botten. Men vad händer om vi ville skapa nya djur på många ställen, inte bara i källfilen där den är definierad? För att göra det måste vi ladda klassdefinitionen.
Manuell klassbelastning med kräver
// Animal.php
class Animal {
public function eats($food) {
echo "Yum, $food!";
}
}
// zoo.php
require 'Animal.php';
$animal = new Animal;
$animal->eats('slop');
// aquarium.php
require 'Animal.php';
$animal = new Animal;
$animal->eats('shrimp');
Här har vi tre filer. En fil ("Animal.php") definierar klassen. Denna fil har inga biverkningar förutom att definiera klassen och håller snyggt all kunskap om ett "djur" på ett ställe. Det är enkelt versionskontrollerat. Det kan lätt återanvändas.
Två filer konsumerar "Animal.php" -filen genom att manuellt require
-ing filen. Återigen, PHP läser källfiler topp till botten, så kräver går och finner "Animal.php" filen och gör Animal
klassdefinition tillgänglig innan du ringer new Animal
.
Föreställ dig nu att vi hade dussintals eller hundratals fall där vi ville utföra ett new Animal
. Det kräver (pun-avsedd) många, många require
uttalanden som är mycket tråkiga att koda.
Autoloading ersätter manuell klassdefinitionsbelastning
// autoload.php
spl_autoload_register(function ($class) {
require_once "$class.php";
});
// Animal.php
class Animal {
public function eats($food) {
echo "Yum, $food!";
}
}
// zoo.php
require 'autoload.php';
$animal = new Animal;
$animal->eats('slop');
// aquarium.php
require 'autoload.php';
$animal = new Animal;
$animal->eats('shrimp');
Jämför detta med de andra exemplen. Lägg märke till hur require "Animal.php"
har ersatts med require "autoload.php"
. Vi inkluderar fortfarande en extern fil vid körning, men snarare än att inkludera en specifik klassdefinition inkluderar vi logik som kan inkludera valfri klass. Det är en indirektnivå som underlättar vår utveckling. Istället för att skriva ett require
för varje klass vi behöver, skriver vi ett require
för alla klasser. Vi kan ersätta N require
med 1 require
.
Magin händer med spl_autoload_register . Denna PHP-funktion tar en stängning och lägger till stängningen i en kö med stängningar. När PHP möter en klass för vilken den inte har någon definition, överlämnar PHP klassnamnet till varje stängning i kön. Om klassen existerar efter att ha avslutat en stängning återgår PHP till sin tidigare verksamhet. Om klassen inte existerar efter att ha provat hela kön, kraschar PHP med "Klass" Vad som inte hittas. "
Autoloading som en del av en ramlösning
// autoload.php
spl_autoload_register(function ($class) {
require_once "$class.php";
});
// Animal.php
class Animal {
public function eats($food) {
echo "Yum, $food!";
}
}
// Ruminant.php
class Ruminant extends Animal {
public function eats($food) {
if ('grass' === $food) {
parent::eats($food);
} else {
echo "Yuck, $food!";
}
}
}
// Cow.php
class Cow extends Ruminant {
}
// pasture.php
require 'autoload.php';
$animal = new Cow;
$animal->eats('grass');
Tack vare vår generiska autoloader har vi tillgång till alla klasser som följer vår autoloader namnkonvention. I det här exemplet är vår konvention enkel: den önskade klassen måste ha en fil i samma katalog med namnet för klassen och slutar på ".php". Lägg märke till att klassnamnet exakt matchar filnamnet.
Utan autoloading skulle vi behöva manuellt require
basklasser. Om vi byggde en hel djurpark med djur skulle vi ha tusentals krav på uttalanden som lättare kunde ersättas med en enda autoloader.
I den slutliga analysen är PHP autoloading en mekanism som hjälper dig att skriva mindre mekanisk kod så att du kan fokusera på att lösa affärsproblem. Allt du behöver göra är att definiera en strategi som kartlägger klassnamn till filnamn . Du kan rulla din egen autoloadningsstrategi, som görs här. Eller så kan du använda någon av de standarder som PHP-gemenskapen har antagit: PSR-0 eller PSR-4 . Eller så kan du använda kompositör för att generellt definiera och hantera dessa beroenden.
Autoladning med kompositör
Kompositör genererar en vendor/autoload.php
fil.
Du kan helt enkelt inkludera den här filen så får du autoladning gratis.
require __DIR__ . '/vendor/autoload.php';
Detta gör det mycket enkelt att arbeta med tredjepartsberoende.
Du kan också lägga till din egen kod i Autoloader genom att lägga till en autoload-sektion till din composer.json
.
{
"autoload": {
"psr-4": {"YourApplicationNamespace\\": "src/"}
}
}
I det här avsnittet definierar du autoload-mappningarna. I det här exemplet är det en PSR-4- mappning av ett namnutrymme till en katalog: /src
katalogen finns i dina projektrotmapp, på samma nivå som /vendor
är. Ett exempel på filnamn är src/Foo.php
innehåller en YourApplicationNamespace\Foo
.
Viktigt: Efter att du har lagt till nya poster i autoload-sektionen måste du köra kommandot dump-autoload
igen för att generera och uppdatera vendor/autoload.php
filen med den nya informationen.
Förutom PSR-4
autoladning stöder Composer också PSR-0
, classmap
och classmap
files
. Se autoload-referensen för mer information.
När du inkluderar filen /vendor/autoload.php
returnerar den en instans av Composer Autoloader. Du kan lagra returvärdet för inkluderingssamtalet i en variabel och lägga till fler namnutrymmen. Detta kan till exempel vara användbart för autoladning av klasser i en testsvit.
$loader = require __DIR__ . '/vendor/autoload.php';
$loader->add('Application\\Test\\', __DIR__);