Slim är ett lättviktigt ramverk som packar mycket slag för sitt lilla fotavtryck. Den har ett otroligt routingsystem, och erbjuder en solid bas för att arbeta utan att komma iväg. Låt mig visa dig!
Men det är inte att säga att Slim inte har några problem; det är en-fil setup blir rörig när din ansökan växer. I den här artikeln granskar vi hur du strukturerar en Slim applikation för att inte bara upprätthålla, men förbättra dess funktionalitet och hålla sakerna snygga och systematiska.
Låt oss börja med att titta på en vanlig Slim-kod för att identifiera problemet. När du har installerat Slim through Composer måste du skapa en instans av Smal
objekt och definiera dina rutter:
få ('/', funktion () echo "Hemsida";); $ app-> get ('/ testPage', funktion () använd ($ app) $ app-> render ('testpage.php');); $ App> run ();
Låt oss slänga Slim-objektet i "controller".
Det första metodsamtalet sätter en ny rutt för root-URI-en (/
) och kopplar den angivna funktionen till den rutten. Detta är ganska ordentligt, men ändå lätt att installera. Det andra metodsamtalet definierar en rutt för URI testPage
. Inuti den tillförda metoden använder vi Slim göra()
metod för att göra en syn.
Här ligger det första problemet: den här funktionen (en stängning) kallas inte i det nuvarande sammanhanget och har ingen möjlighet att komma åt Slims funktioner. Det är därför vi behöver använda använda sig av
sökord för att skicka referensen till Slim-appen.
Den andra frågan härrör från Slims arkitektur; Det är tänkt att definieras i en enda fil. Naturligtvis kan du lägga ut variabeln till en annan fil, men det blir bara rörigt. Helst vill vi ha möjlighet att lägga till controllers för att modulera ramverket i enskilda komponenter. Som en bonus skulle det vara trevligt om dessa controllers erbjöd inbyggd tillgång till Slim-funktionerna, vilket eliminerar behovet av att skicka referenser till stängningarna.
Det är diskutabelt om läsning av källkod från ett open source-projekt betraktas som omvänd teknik, men det är termen jag ska hålla fast vid. Vi förstår hur man använder Slim, men vad händer under huven? Låt oss titta på en mer komplicerad rutt för att komma till roten till denna fråga:
$ app-> get ('/ users /: name', funktion ($ namn) echo "Hello". $ name;);
Denna ruttdefinition använder ett kolon med ordet, namn
. Detta är en platshållare, och värdet som används i sin plats skickas till funktionen. Till exempel, / Användare / gabriel
matchar denna rutt och "gabriel" skickas till funktionen. Rutten, / användare
, å andra sidan är inte en match eftersom det saknas parametern.
Om du tänker på det logiskt, finns det ett antal steg som måste slutföras för att kunna bearbeta en rutt.
För att bättre optimera processen, smal - använd regex callbacks och grupper - lagrar platshållarna när det kontrollerar matchningar. Detta kombinerar två steg i ett, vilket bara innebär att du behöver utföra den anslutna funktionen när Slim är klar. Det blir klart att färdvägsobjektet är självständigt, och uppriktigt sagt, allt som behövs.
I det föregående exemplet hade vi tillgång till Slim-särdrag när vi analyserade rutorna, men vi behövde skicka en Slim-objektreferens eftersom det annars inte skulle vara tillgängligt inom funktionens exekveringskontext. Det är allt du behöver för de flesta applikationer, eftersom programmets logik ska ske i kontrollenheten.
Med det i åtanke, låt oss ta bort "routing" -delen i en klass och vrid Slim-objektet till "controller".
Till att börja med, låt oss ladda ner och installera "Vanilla Slim" om du inte redan har gjort det. Jag antar att du har installerat Composer, men om inte, följ stegen .
Inne i en ny katalog skapar du en fil med namnet composer.json
, och lägg till följande:
"namn": "nät / slim-mvc", "kräver": "slim / slim": "*", "slim / extras": "*", "twig / twig": "*"
I ett terminalfönster, navigera till nämnda katalog och typ kompositör installera
. Jag går igenom dessa paket, om det här är första gången du använder Slim.
Du behöver tekniskt inte de smarta extrakten eller Twig för denna handledning, men jag gillar att använda Twig istället för standard PHP-mallar. Om du använder Twig behöver du Slim-extras eftersom det ger ett gränssnitt mellan Twig och Slim.
Nu kan vi lägga till våra anpassade filer, och vi börjar med att lägga till en katalog till säljare
mapp. Jag heter min Nettuts
, men var god att namnge din, vad du än vill. Om du fortfarande befinner dig i terminalen, se till att terminalfönstret finns i projektets katalog och skriv följande:
mkdir-leverantör / Nettnät
Redigera nu composer.json
genom att lägga till hänvisningen till den här nya mappen:
"slim / slim": "*", "slim / extras": "*", "kvist / kvist": "*", " autoload ": " psr-0 ": " Webuts ":" leverantör / "
Vi vill att vår app automatiskt laddar klasser från Nettuts
namespace, så det här berättar kompositören att kartlägga alla förfrågningar om Nettuts
till PSR-0-standarden från och med Säljare
mapp.
Utför nu:
kompositör dump-autoload
Detta kompilerar autoladdaren för att inkludera den nya referensen. Skapa sedan en fil med namnet Router.php
, inom Nettuts
katalog och ange följande:
Vi såg att varje rutobjekt har en fristående funktion som bestämmer om den matchar den angivna URI. Så vi vill ha en rad rutter och en funktion att analysera genom dem. Vi behöver också en annan funktion för att lägga till nya rutter och ett sätt att hämta URI från den aktuella HTTP-begäran.
Låt oss börja med att lägga till några medlemsvariabler och konstruktören:
Klassruter skyddade $-rutter; skyddad $ request offentlig funktion __construct () $ env = \ Slim \ Miljö :: getInstance (); $ this-> request = new \ Slim \ Http \ Request ($ env); $ this-> routes = array ();Vi ställer in
rutter
variabel för att innehålla rutterna ochbegäran
variabel för att lagra SlimBegäran
objekt. Därefter behöver vi möjlighet att lägga till rutter. För att hålla fast vid bästa praxis kommer jag att bryta detta i två steg:public function addRoutes ($ rutter) foreach ($ rutter som $ route => $ path) $ method = "any"; om (strpos ($ path, "@")! == false) lista ($ path, $ method) = explodera ("@", $ path); $ func = $ this-> processCallback ($ path); $ r = new \ Slim \ Route ($ rutt, $ func); $ R-> setHttpMethods (strtoupper ($ metod)); array_push ($ this-> rutter, $ r);Denna offentliga funktion accepterar en associativ grupp av rutter i formatet av
route => väg
, varrutt
är en vanlig Slim-rutt ochväg
är en sträng med följande konvention:Eventuellt kan du lämna vissa parametrar för att använda ett standardvärde. Klassnamnet kommer till exempel att ersättas med
Huvudsaklig
om du lämnar ut det,index
är standard för utelämnade funktionsnamn, och standard för HTTP-metoden ärnågra
. Självklart,några
är inte en riktig HTTP-metod, men det är ett värde som Slim använder för att matcha alla HTTP-metortyper.De
addRoutes
funktionen börjar med aför varje
slinga som cyklar genom rutterna. Därefter ställer vi in standard HTTP-metoden, eventuellt överstyrar den med den angivna metoden om@
symbolen är närvarande. Sedan skickar vi återstoden av sökvägen till en funktion för att hämta en återuppringning och bifoga den till en rutt. Slutligen lägger vi till rutten till matrisen.Nu ska vi titta på
processCallback ()
fungera:skyddad funktion processCallback ($ path) $ class = "Main"; om (strpos ($ path, ":")! == false) list ($ class, $ path) = explodera (":", $ path); $ function = ($ path! = "")? $ bana: "index"; $ func = function () använd ($ class, $ function) $ class = '\ Controllers \\'. $ Klass; $ class = new $ class (); $ args = func_get_args (); returnera call_user_func_array (array ($ class, $ function), $ args); ; returnera $ func;Den andra frågan härrör från Slims arkitektur; Det är tänkt att definieras i en enda fil.
Vi ställer in standardkursen till
Huvudsaklig
, och åsidosätta den klassen om kolonsymbolen finns. Därefter bestämmer vi om en funktion är definierad och använder standardmetodenindex
om nödvändigt. Vi skickar sedan klassen och funktionsnamnen till en stängning och returnerar den till rutten.Inuti stängningen förbereder vi klassnamnet med namespace. Vi skapar sedan en ny instans av den angivna klassen och hämtar listan över argument som skickats till den här funktionen. Om du kommer ihåg, medan Slim kontrollerar om en rutt matchar, bygger den långsamt en lista med parametrar baserat på jokertecken från rutten. Denna funktion (
func_get_args ()
) kan användas för att få de överförda parametrarna i en array. Sedan använder ducall_user_func_array ()
Metoden gör att vi kan ange klassen och funktionen medan parametrarna överförs till regulatorn.Det är inte en väldigt komplicerad funktion när du förstår det, men det är ett mycket bra exempel på när stängningar är till nytta.
För att återskapa, lade vi till en funktion till vår
router
som låter dig passera en associativ array som innehåller rutter och banor som kartlägger klasser och funktioner. Det sista steget är att bearbeta rutterna och utföra alla som matchar. Att hålla sig till Slim-namngivningskonventionen, låt oss kalla detspringa
:public function run () $ display404 = true; $ uri = $ this-> request-> getResourceUri (); $ method = $ this-> request-> getMethod (); ($ this-> rutter som $ i => $ rutt) om ($ route-> matchar ($ uri)) om ($ route-> supportsHttpMethod ($ method) || $ route-> supportsHttpMethod ")) call_user_func_array ($ route-> getCallable (), array_values ($ route-> getParams ())); $ display404 = false; om ($ display404) echo "404 - rutt ej hittad";Vi börjar med att ställa in
display404
variabel, representerar inga rutter som hittats, tillSann
. Om vi hittar en matchande rutt ställer vi in det härfalsk
och förbikoppla felmeddelandet. Därefter använder vi Slims begäranobjekt för att hämta den aktuella URI- och HTTP-metoden.Vi använder den här informationen för att bläddra igenom och hitta matchningar från vår array.
När ruttobjektet är klart
tändstickor()
funktionen körs, du kan ringagetParams ()
för att hämta de analyserade parametrarna. Använda den funktionen ochgetCallable ()
metod, vi kan genomföra stängningen och överföra nödvändiga parametrar. Slutligen visar vi ett 404 meddelande om ingen rutt matchade den aktuella URI.Låt oss skapa kontrollerklassen som innehåller callbacks för dessa rutter. Om du har följt med, kanske du har insett att vi aldrig tvingat ett protokoll eller en klasstyp. Om du inte vill skapa en kontrollerklass, fungerar någon klass bra.
Så varför skapar du en kontrollerklass? Det korta svaret är att vi fortfarande inte har använt Slim! Vi använde delar av Slim för HTTP-förfrågan och -rutter, men hela punkten var att ha enkel tillgång till alla Slim-egenskaper. Vår controller klass kommer att förlänga den verkliga Slim-klassen, få tillgång till alla Slim-metoder.
Du kan lika enkelt hoppa över detta och underklassen Slim direkt från dina controllers.
Bygga kontrollenheten
Denna kontroller gör det möjligt att modifiera Slim medan du fortfarande håller den vanilj. Namnge filen
Controller.php
, och skriv följande kod:data = $ inställningar ['modell']; förälder :: __ konstruera ($ inställningar);När du initierar Slim kan du passera i olika inställningar, allt från programmets debug-läge till templerande motor. Istället för att hårdkodning av några värden i konstruktorn laddar jag dem från en fil som heter
settings.php
och överför den uppsättningen till förälderens konstruktör.Eftersom vi utökar Slim, tyckte jag att det skulle vara coolt att lägga till en "modell" -inställning, så att människor kunde haka sitt dataobjekt direkt i kontrollenheten.
Det är det avsnitt du kan se mitt i ovanstående kod. Vi kontrollerar om
modell
inställningen har ställts in och tilldelats den till regulatornsdata
egendom vid behov.Skapa nu en fil med namnet
settings.php
i roten till ditt projekt (mappen medcomposer.json
fil) och ange följande:new \ Slim \ Extras \ Visningar \ Twig (), 'templates.path' => '... / Visningar', 'model' => (Objekt) array ("message" => "Hello World")); returnera $ inställningar;Dessa är vanliga Slim-inställningar med undantag av modellen. Vilket värde som helst tilldelas
modell
egendom överförs tilldata
variabel; Det här kan vara en matris, en annan klass, en sträng, etc ... Jag satte den på ett objekt eftersom jag gillar att använda->
notation i stället för konsolen (array) notation.Vi kan nu testa systemet. Om du kommer ihåg i
router
klass, förklara vi klassnamnet med "Kontrollant
"namespace. Öppna uppcomposer.json
lägg till följande direkt efter fso-0-definitionen förNettuts
namespace:"name": "netts / slim_advanced", "require": "slim / slim": "2.2.0", "slim / extras": "*", "kvist / kvist": "*", " autoload ": " psr-0 ": " Webuts ":" leverantör / "," Controller ":" ./ "Därefter som tidigare, bara dumpa autoloader:
kompositör dump-autoloadOm vi bara ställa in basvägen till rotkatalogen, så namnrymden
Kontrollant
kommer att kartlägga till en mapp med namnet "Kontrollant
"i roten till vår app. Skapa så den mappen:mkdir ControllerInne i den här mappen skapar du en ny fil med namnet
main.php
. Inuti filen måste vi deklarera namnrymden och skapa en klass som utökar vårKontrollant
basklass:data-> meddelande; offentliga funktionstest () echo "testsida";Detta är inte komplicerat, men låt oss ta det med måtta. I denna klass definierar vi två funktioner; deras namn spelar ingen roll eftersom vi kommer att kartlägga dem till rutter senare. Det är viktigt att märka att jag direkt åtkomst till egenskaper från styrenheten (dvs modellen) i den första funktionen och i själva verket får du full tillgång till alla Slim-kommandon.
Låt oss nu skapa den faktiska offentliga filen. Skapa en ny katalog i roten till ditt projekt och namnge den
offentlig
. Som namnet antyder, det här är var alla offentliga saker kommer att bo. Inne i den här mappen skapar du en fil som heterindex.php
och ange följande:'Huvud: index @ get', '/ test' => 'Huvud: test @ get'); $ Router-> addRoutes ($ linjer); $ Router-> run ();Vi inkluderar Composer's autoloading-bibliotek och skapar en ny instans av vår router. Då definierar vi två rutter, lägger dem till routerns objekt och kör det.
Du måste också aktivera mod_rewrite i Apache (eller motsvarande med en annan webbserver). För att ställa in detta, skapa en fil med namnet
.htaccess
inutioffentlig
katalog och fyll i det med följande:RewriteEngine On RewriteCond% REQUEST_FILENAME! -F RewriteRule ^ index.php [QSA, L]Nu kommer alla förfrågningar till den här mappen (som inte matchar en faktisk fil) att överföras till
index.php
.I din webbläsare, navigera till din
offentlig
katalog och du bör se en sida som säger "Hello World". Navigera till "/testa
", och du borde se meddelandet" Testsida ". Det är inte hemskt spännande, men vi har framgångsrikt flyttat all logikkod till enskilda kontroller.
Rond två
Slim är inte CodeIgniter, det är inte Symfony och det är inte Laravel.
Så vi har grundläggande funktionalitet, men det finns några grova kanter. Låt oss börja med routern.
Från och med nu visar vi ett enkelt felmeddelande om en rutt inte existerar. I en riktig applikation vill vi ha samma funktion som att ladda en vanlig sida. Vi vill dra nytta av Slims förmåga att ladda visningar, samt ställa in svarets felkod.
Låt oss lägga till en ny klassvariabel som innehåller en valfri sökväg (precis som de andra rutterna). Överst i filen lägger du till följande rad direkt efter definitionen för begäran objekt:
skyddad $ errorHandler;Låt oss sedan skapa en funktion som accepterar en sökväg och tilldelar den en återuppringningsfunktion. Det här är relativt enkelt eftersom vi redan abstraherade denna funktion:
allmän funktion set404Handler ($ path) $ this-> errorHandler = $ this-> processCallback ($ path);Låt oss nu justera
springa
kommandot att valfritt utföra återuppringningen istället för att bara visa felmeddelandet:om ($ display404) om (is_callable ($ this-> errorHandler)) call_user_func ($ this-> errorHandler); annars echo "404 - rutt ej hittad";Öppna kontrollerklassen. Här kan du anpassa Slim: s funktionalitet till dina egna personliga preferenser. Till exempel vill jag ha möjlighet att släppa filutvidgningen när du läser in visningar. Så istället för att skriva
$ This-> render ( "home.php");
, Jag vill bara skriva:$ This-> render ( "hem");
. För att göra detta, åsidosätter vi renderingsmetoden:public function render ($ namn, $ data = array (), $ status = null) om (strpos ($ namn, ".php") === false) $ name = $ name. ".Php"; förälder :: render ($ namn, $ data, $ status);Vi accepterar samma parametrar som föräldrafunktionen, men vi kontrollerar om filtillägget tillhandahålls och lägg till det om det behövs. Efter den här ändringen överför vi filen till överordnad metod för bearbetning.
Detta är bara ett enda exempel, men vi borde lägga några andra ändringar här i
göra()
metod. Om du till exempel lägger samma sidhuvud och sidfot på alla dina dokument kan du lägga till en funktionrenderPage ()
. Den här funktionen skulle ladda den överförda bilden mellan samtalen för att ladda den vanliga rubriken och sidfoten.Låt oss nu titta på att ladda vissa visningar. I roten till ditt projekt skapar du en mapp med namnet "
Visningar
"(plats och namn kan justeras isettings.php
fil). Låt oss bara skapa två visade visningartest.php
ocherror.php
.Inuti
test.php
, lägg till följande:titel
Detta är sidan name!
Och inuti
error.php
fil, ange det här:404
Rutten du letade efter kunde inte hittas
Ändra också
Huvudsaklig
controller genom att ändraindex()
funktion till följande:public function index () $ this-> render ("test", array ("title" => $ this-> data-> meddelande, "namn" => "Hem"));Här gör vi testvyn som vi just gjort och skickar den data som ska visas. Låt oss sedan prova en rutt med parametrar. Ändra
testa()
funktion till följande:offentliga funktionstest ($ title) $ this-> render ("test", array ("title" => $ title, "name" => "Test"));Här tar vi det ett steg längre genom att hämta sidans titel från URI själv. Sist men inte minst, låt oss lägga till en funktion för 404-sidan:
allmän funktion notFound () $ this-> render ('error', array (), 404);Vi använder
göra()
funktionens tredje valfria parameter som anger svarets HTTP-statuskod.Vår sista redigering finns i
index.php
att införliva våra nya linjer:$ routes = array ('/' => ", '/ test /: title' => 'Main: test @ get'); $ router-> addRoutes ($ rutter); $ router-> set404Handler (" Main: notFound "); $ router-> run ();Du ska nu kunna navigera till de tre linjerna och se deras respektive åsikter.
Slutsats
Med allt som vi åstadkom, har du säkert några frågor om varför Slim inte redan erbjuder dessa ändringar. De verkar logiska, de avviker inte från Slims genomförande för långt, och de ger mycket mening. Josh Lockhart (Slim's Creator) gjorde det bäst:
"Slim är inte CodeIgniter, det är inte Symfony, och det är inte Laravel. Slim är Slim. Det byggdes för att vara lätt och roligt, men kan fortfarande lösa cirka 80% av de vanligaste problemen. I stället för att oroa sig för kanten fall fokuserar det på att vara enkelt och ha en lättläst kodbas. "
Ibland, som utvecklare, blir vi så vana upp som täcker galna scenarier som vi glömmer om vad som är väldigt viktigt: koden. Mods, som i den här handledningen, är bara möjliga på grund av kodens enkelhet och verbositet. Så ja, det kan finnas några kantfall som behöver särskild uppmärksamhet, men du får ett aktivt samhälle som enligt min mening väger mycket.
Jag hoppas att du haft den här artikeln. Om du har några frågor eller kommentarer, lämna ett meddelande nedan. Du kan också kontakta mig via IRC-kanalen på Freenode på #nettuts kanalisera.