0 follower

URL-hantering

Komplett URL-hantering för en webbapplikation involverar två aspekter. För det första, när en användar-request kommer in i form av en URL, behöver applikationen avkoda den till begripliga parametrar. För det andra behöver applikationen erbjuda ett sätt att skapa URL:er på ett sådant vis att de är begripliga för applikationen. En Yii-applikation åstadkommer detta med hjälp av CUrlManager.

1. Skapa URL:er

Även om URL:er kan hårdkodas i kontrollervyer, är det ofta mer flexibelt att skapa dem dynamiskt:

$url=$this->createUrl($route,$params);

där $this refererar till kontrollerinstansen; $route anger route för önskad request; $params är en lista med GET-parametrar som skall läggas till URL:en.

Som standard är URL:er som skapats med hjälp av createUrl av det så kallade get-formatet. Till exempel, givet $route='post/read' och $params=array('id'=>100), skulle vi erhålla följande URL:

/index.php?r=post/read&id=100

där parametrarna återfinns i frågesträngen sammanslagna till en lista av Namn=Värde-par separerade av och-tecken (&), och där r-parametern specificerar request-route. Detta URL-format är inte speciellt användarvänligt eftersom det erfordrar ett antal ordfrämmande tecken.

Ovanstående URL kan fås att se renare ut samt mer självförklarande genom användning av det så kallade path-formatet, vilket eliminerar frågesträngen och dessutom placerar GET-parametrarna i den del av URL:en som innehåller path-info:

/index.php/post/read/id/100

För att byta URL:format konfigurerar vi applikationskomponenten urlManager så att createUrl automatiskt kan byta till det nya formatet och så att applikationen korrekt kan begripa de nya URL:erna:

array(
    ......
    'components'=>array(
        ......
        'urlManager'=>array(
            'urlFormat'=>'path',
        ),
    ),
);

Lägg märke till att vi inte behöver klass för komponenten urlManager, den är fördeklarerad som CUrlManager i CWebApplication.

Tips: URL:en som genereras av metoden createUrl är en relativ sådan. För att få en absolut URL kan vi infoga ett prefix med hjälp av Yii::app()->hostInfo, alternativt anropa createAbsoluteUrl.

2. Användarvänliga URL:er

När path används dom URL-format kan vi specificera vissa URL-regler för att göra våra URL:er ännu mer användarvänliga. Vi kan till exempel generera en så kort URL som /post/100, i stället för det betydligt längre /index.php/post/read/id/100. URL-regler används av CUrlManager både för att skapa URL:er och för URL-parsning.

För att ange URL-regler behöver vi konfigurera propertyn rules i applikationskomponenten urlManager:

array(
    ......
    'components'=>array(
        ......
        'urlManager'=>array(
            'urlFormat'=>'path',
            'rules'=>array(
                'pattern1'=>'route1',
                'pattern2'=>'route2',
                'pattern3'=>'route3',
            ),
        ),
    ),
);

Reglerna specificeras i form av en array av mönster-routepar, vart och ett motsvarande en enstaka regel. Mönstret i en regel utgörs av en sträng som används till att matcha pathinfo-delen av URL:erna. Routedelen av en regel skall referera till en giltig kontrollerroute.

Info: med start fr o m version 1.0.6, kan en regel anpassas ytterligare med hjälp av dess urlSuffix- och caseSensitive-alternativ. Med start från version 1.0.8, kan en regel också ha defaultParams som representerar en lista med namn-värdepar att sammanfogas med $_GET. För att anpassa en regel med dessa alternativ, specificera routedelen av regeln i form av en array, i stil med följande:

'pattern1'=>array('route1', 'urlSuffix'=>'.xml', 'caseSensitive'=>false)

Using Named Parameters

En regel kan associeras med några GET-parametrar. Dessa GET-parametrar uppträder i regelns mönster som speciella symboler på följande format:

<ParamName:ParamPattern>

där ParamName specificerar namnet på en GET-parameter och det frivilliga ParamPattern specificerar det reguljära uttrycket som skall användas för att matcha GET-parameterns värde. Om ParamPattern utelämnas, innebär detta att parametern skall matcha alla tecken med undantag för snedstreck /. När en URL skapas kommer dessa parametersymboler att ersättas med motsvarande parametervärden; vid parsning av en URL, kommer de motsvarande GET-parametrarna att erhålla värden från resultatet av parsningen.

Några exempel följer nu för att belysa hur URL-regler fungerar. Regeluppsättningen antas innehålla tre regler:

array(
    'posts'=>'post/list',
    'post/<id:\d+>'=>'post/read',
    'post/<year:\d{4}>/<title>'=>'post/read',
)
  • Anropet $this->createUrl('post/list') genererar /index.php/posts. Den första regeln appliceras.

  • Anropet $this->createUrl('post/read',array('id'=>100)) genererar /index.php/post/100. Den andra regeln appliceras.

  • Anropet $this->createUrl('post/read',array('year'=>2008,'title'=>'a sample post')) genererar /index.php/post/2008/a%20sample%20post. Den tredje regeln appliceras.

  • Anropet $this->createUrl('post/read') genererar /index.php/post/read. Ingen av reglerna appliceras.

Sammanfattningsvis, när createUrl används för att generera en URL, används route- och GET-parametrarnas som lämnas till funktionen till att avgöra vilken URL-regel som skall appliceras. Om varje parameter associerad med en regel kan hittas bland GET-parametrarna som lämnats till createUrl, och om regelns route också matchar routeparametern, kommer regeln att användas för att generera URL:en.

Om GET-parametrarna som lämnas till createUrl är fler än de som behövs i en regel, hamnar de överflödiga parametrarna i en query- sträng. Till exempel, ur anropet $this->createUrl('post/read',array('id'=>100,'year'=>2008)), erhålls /index.php/post/100?year=2008. För att få dessa tillkommande parametrar att hamna i pathinfo-delen, kompletterar vi regeln med /*. Med regeln post/<id:\d+>/* erhåller vi URL:en /index.php/post/100/year/2008.

Som nämnts är det andra ändamålet med URL-regler parsning av request-URL:er. Detta är naturligtvis den omvända processen mot URL-generering. Till exempel, när en användare skickar en request /index.php/post/100, kommer den andra regeln i ovanstående exempel att appliceras, vilket löses upp till en route post/read och GET-parametern array('id'=>100) (kan nås via $_GET).

Märk: Användning av URL-regler försämrar applikationen prestanda. Detta beror på att vid parsning av request-URL:en, kommer CUrlManager att försöka matcha den mot varje regel tills någon kan appliceras. Ju fler regler, desto större prestandaförlust. Av denna anledning skall en webbapplikation med intensiv trafik minimera sin användning av URL-regler.

Parametrisering av route

Med start fr o m version 1.0.5, kan vi referera till namngivna parametrar i routedelen av en regel. Detta medger att regeln appliceras på multipla route baserat på matchningskriterium. Det kan även hjälpa till att reducera antalet regler i en applikation och därmed förbättra totalprestanda.

Följande exempelregler illustrerar hur route parametriseras med hjälp av namngivna parametrar:

array(
    '<_c:(post|comment)>/<id:\d+>/<_a:(create|update|delete)>' => '<_c>/<_a>',
    '<_c:(post|comment)>/<id:\d+>' => '<_c>/read',
    '<_c:(post|comment)>s' => '<_c>/list',
)

Ovan används två namngivna parametrar i routedeln av reglerna: _c och _a. Den förra matchar ett kontroller-ID till att vara antingen post eller comment, medan den senare matchar ett åtgärds-ID till att vara create, update eller delete. Parametrarna kan namnges annorlunda så länge de inte kommer i konflikt med GET-parametrar som kan finnas i URL:er.

Med användning av ovanstående regler kommer URL:en /index.php/post/123/create att tolkas som routen post/create med GET-parametern id=123. Och givet routen comment/list och GET-parametern page=2, kan vi generera URL:en /index.php/comments?page=2.

Gömma index.php

Det finns en sak till att göra för att ytterligare rensa upp URL:er, att eliminera startskriptet index.php från URL:en. Detta kräver att vi konfigurerar webbservern såväl som applikationskomponenten urlManager.

Webbservern behöver konfigureras så att URL:en utan startskriptdelen fortfarande kommer att hanteras av startskriptet. För Apache HTTP-server, kan detta åstadkommas genom att slå på URL rewriting engine och specificera några rewriting-regler. Vi t ex kan skapa filen /wwwroot/blog/.htaccess med nedanstående innehåll. Märk att samma innehåll även kan placeras i Apaches konfigurationsfil inuti elementet Directory för /wwwroot/blog.

Options +FollowSymLinks
IndexIgnore */*
RewriteEngine on

# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

# otherwise forward it to index.php
RewriteRule . index.php

Därefter konfigurerar vi propertyn showScriptName i komponenten urlManager till false.

Med anropet $this->createUrl('post/read',array('id'=>100)), erhålls nu URL:en /post/100. Och nog så viktigt, denna URL kan kännas igen korrekt av webbapplikationen.

Låtsat URL-suffix

Vi kan även lägga till något suffix till URL:er. Till exempel, kan vi erhålla /post/100.html i stället för /post/100. Detta liknar mer en URL till en statisk webbsida. För att göra så, konfigurera komponenten urlManager genom att sätta dess property urlSuffix till önskad suffixsträng.