Viime vuoden aikana osallistuin kolmeen suureen projektiin. Tehtäväni oli siirtyä pois vanhasta arkkitehtuurista, joka perustuu PHP- ja palvelinpuoleiseen HTML-sukupolveen, ja siirtyä REST-sovellusliittymään.
Vanhan lähestymistavan ansiosta taustakehittäjien odotettiin tietävän paljon enemmän käyttöliittymästä ja sovelluksen visuaalisista näkökohdista. Tämän vuoksi heidän oli kiinnitettävä huomiota sovelluksen eri segmentteihin sen sijaan, että keskityttäisiin ensisijaiseen tavoitteeseensa. Taustajärjestelmän sovellusliittymän erottaminen tiukasti käyttöliittymästä antoi kehittäjillemme mahdollisuuden keskittyä koodinsa laatuun.
API-palveluiden testaaminen on myös paljon helpompaa, koska REST-sovellusliittymä voidaan tarkistaa automaattisella yksikkötestaus .
Minulla on ollut jonkin verran kokemusta oman kehyksen kirjoittamisesta sekä työskentelystä Yii, CakePHP, CodeIgniter, Slim Framework, Symfony ja muutamien muiden avoimen lähdekoodin kehysten kanssa. Joka kerta olen kokenut toimivuuden puutteen tai hankalan lähestymistavan joihinkin ongelmiin.
Käytin Laravelia neljä kuukautta ennen kuin päätin valita sen alustaksi seuraavaan projektiimme. Itse projekti oli suuri menestys, ja tämä artikkeli on tämän kokemuksen tuote. Nyt voin kutsua itseäni a Laravel-kehittäjä .
Olen jo hahmotellut joitain syitä Laravelin käyttöön ja kokemukseni, joten katsotaanpa tarkemmin, mikä teki Laravelista paremman valinnan uusimmalle projektilleni:
Laravel-ydintä isännöidään GitHub . Ydin toteuttaa IoC-kuvio sallii kehyksen minkä tahansa osan mukauttaminen ja uudelleenkirjoittaminen (pyyntö, loki, todennus jne.).
Laravel-suunnittelijat eivät käyttäneet liikaa aikaa pyörän keksimiseen. Paljon ratkaisuja ja käytäntöjä siirretään muista kehyksistä. Hyvä esimerkki tästä lähestymistavasta on laajennettu Symfony-konsoli nimeltä Käsityöläinen , joka on Laravelin mukana tuleva komentoriviliitäntä.
Reitti Laravelissa on hämmästyttävää; se on hyvin samanlainen kuin Ruby on Rails (RoR) -toteutus, josta pidän paljon. Voit helposti ryhmitellä reittejä, luoda resursseja CRUD-sivuille, liittää suodattimia ja sitoa malleja automaattisesti kyselyparametreihin.
Sisäkkäiset reitit ovat erittäin hyödyllinen ominaisuus:
Route::group(['prefix'=>'level0'], function(){ Route::get('/', array('uses' => ' [email protected] ')); Route::group(['prefix'=>'/{level0}/level1'], function(){ Route::get('/', array('uses' => ' [email protected] ')); Route::post('/{custom_variable}/custom_route', array('uses' => ' [email protected] _route')); }); });
Versiointi voidaan toteuttaa ryhmänä ylimmällä tasolla kaikille sisäkkäisille reiteille käyttämällä etuliitettä ‘v1’. Kun muutamme sovellusliittymäversiota, voimme säilyttää vanhan version ja aloittaa reitin toteuttamisen uudella koodilla ja logiikalla 'v2', ts. Uudet viitteet ohjaimiin ja toimintoihin.
Tarkastellaan askel askeleelta kaikkea, mitä tässä Laravel-opetusohjelmassa käytetään:
Määritelty reittiryhmä polulla level0
API: n ylimmällä tasolla.
Jos meillä on puhelu BASEURL/level0
, Laravel ratkaisee sen ja kutsuu menetelmän level0()
TestControllerista pyynnön käsittelemiseksi.
Meillä on alaryhmä {level0}/level1
: n kanssa kuvio. Jos haluat käyttää API-resursseja tämän ryhmän sisällä, meidän on käytettävä pääryhmän polkua (level0)
ja vastaa alaryhmämme mallia ({level0}/level1)
Esimerkiksi level0/777/level1
on oikea polku tälle API: n alaryhmälle. Täällä meillä on 777 muuttujana0, jonka Laravel kuljettaa alaryhmän sisäisten reittien käsittelijälle.
Loppujen lopuksi meillä on kaksi näytereittiä:
BASEURL/level0/777/level1
- GET-pyyntö tälle URI: lle käsitellään menetelmällä level1($level0)
TestController, jossa ensimmäinen parametri on {level0}
ja se alustetaan arvolla 777.
BASEURL/level0/777/level1/888/custom_variable
- POST-pyyntö tälle URI: lle käsitellään custom_route($level0, $custom_variable)
-sovelluksella menetelmä CustomController.
Menetelmässä käytetyt parametrit tulevat reittimuuttujista.
Lopuksi voimme liittää muuttujamme {level0}
reitillä mallilla, eli LevelModelilla. Tässä tapauksessa kehys yrittää automaattisesti etsiä olemassa olevia tietokantatietueita ja välittää ne parametrina ohjaimen menetelmälle.
Se auttaa meitä kirjoittamaan vähemmän koodia, eikä meidän tarvitse kirjoittaa LevelModel::find($id)
tai LevelModel::findOrFail($id)
ohjaimissa.
Dingo API -paketti vie reitityksen yhden askeleen pidemmälle.
Tässä on muutamia ominaisuuksia, jotka Dingo tarjoaa kehykselle:
API::user()
-näppäimillä.Laravel perustuu Eloquent ORM: ään. Olen käyttänyt sitä PostgreSQL: n ja MySQL: n kanssa, ja molemmissa tapauksissa se toimi moitteettomasti.
Virallinen dokumentaatio on kattava, joten tässä artikkelissa olevia asioita ei ole syytä toistaa:
Kyselyn laajuus - kyselylogiikka luodaan toiminnolla, jolla on erityinen laajuuden etuliite.
Seuraava esimerkki näyttää tavallisen SQL-kyselyn, joka on muunnettu kyselyfunktioksi Eloquent ORM: ssä:
SELECT * WHERE hub_id = 100 AND (name LIKE `%searchkey%` OR surname LIKE `%searchkey%`):
function scopeByFieldListLike($query, $fields, $value){ $query->where(function($query) use ($fields, $value){ foreach($fields as $field){ $query->orWhere($field , 'like', '%'.$value.'%'); } }); return $query; }
Funktion käyttäminen koodissasi on yksinkertaista.
$model = new User; $model->byFieldListLike(['name', 'surname'], 'searchkey');
Paljon Eloquent-menetelmiä palauttaa QueryBuilder-ilmentymän. Voit käyttää melkein kaikkia näitä menetelmiä malleissa.
Yksikkötestien kirjoittaminen on yleensä erittäin aikaa vievää, mutta se on ehdottomasti ajan arvoinen, joten tee se.
Laravel luottaa tähän tehtävään TestCase-perusluokkaan. Se luo uuden sovelluksen ilmentymän, ratkaisee reitin ja suorittaa ohjainmenetelmän omassa hiekkalaatikossa. Se ei kuitenkaan suorita sovellussuodattimia (App :: before ja App :: after) tai monimutkaisempia reititysskenaarioita. Jotta nämä suodattimet otettaisiin käyttöön hiekkalaatikkoympäristössä, jouduin ottamaan ne käyttöön manuaalisesti Route::enableFilters()
-painikkeilla.
On selvää, että jos osaat käyttää Laravelia, tiedät, että se voisi käyttää enemmän työtä yksikkötestaussegmentissä. Olen määrittänyt muutaman toiminnon, jotka auttoivat minua luomaan edistyneempiä yksikötestejä. Voit vapaasti ottaa nämä ja käyttää niitä projekteissasi.
Suoritin edistyneempiä tosielämän testauksia ja 'kiharan kaltaisten' pyyntöjen toteuttamiseksi käytin kriswallsmith / buzz-kirjastoa. Tämä tarjosi minulle kaivatun testaukseen tarvittavan ominaisuusjoukon, mukaan lukien mukautetut otsikot ja tiedostojen lataaminen.
Alla oleva koodi näyttää toiminnon, jota voit käyttää tällaisen testin suorittamiseen:
public function browserRequest($method, $resource, $data = [], $headers = [], $files = []) { $host = $this->baseUrl(); if (count($files)){ // Use another form request for handling files uploading $this->_request = new BuzzMessageFormFormRequest($method, $resource, $host); if (isset($headers['Content-Type'])) { // we don't need application/json, it should form/multipart-data unset($headers['Content-Type']); } $this->_request->setHeaders($headers); $this->_request->setFields($data); foreach($files as $file) { $upload = new BuzzMessageFormFormUpload($file['path']); $upload->setName($file['name']); $this->_request->setField($file['name'], $upload); } $response = new BuzzMessageResponse(); $client = new BuzzClientFileGetContents(); $client->setTimeout(60);//Set longer timout, default is 5 $client->send($this->_request, $response); } else { $this->_request = new BuzzMessageRequest($method, $resource, $host); $this->_request->setContent(json_encode($data)); $this->_request->setHeaders($headers); $response = new BuzzMessageResponse(); $client = new BuzzClientFileGetContents(); $client->setTimeout(60);//Set longer timout, default is 5 $client->send($this->_request, $response); } return $response; }
Olen erittäin laiska kehittäjä, joten lisäsin valinnaiset parametrit, joiden avulla sain purkaa vastaukset, poimia tietoja ja tarkistaa vastauskoodit. Tämä johti toiseen menetelmään, joka sisältää oletusotsikot, valtuutuskoodit ja joitain lisätoimintoja.
public function request($method, $path, $data = [], $autoCheckStatus = true, $autoDecode = true, $files = []) { if (!is_array($data)){ $data = array(); } $servers = ['Content-Type' => 'application/json']; if ($this->_token){ $servers['authorization'] = 'Token ' . $this->_token; } $this->_response = $this->browserRequest($method, $path, $data, $servers, $files); if ($autoCheckStatus === true){ $this->assertTrue($this->_response->isOk()); } elseif(ctype_alnum($autoCheckStatus)){ $this->assertEquals($autoCheckStatus, $this->_response->getStatusCode()); } if ($autoDecode){ $dataObject = json_decode($this->_response->getContent()); if (is_object($dataObject)) { // we have object at response return $this->_dataKeyAtResponse && property_exists($dataObject, $this->_dataKeyAtResponse) ? $dataObject->{$this->_dataKeyAtResponse} : $dataObject; } elseif (is_array($dataObject)) { // perhaps we have a collection return $this->_dataKeyAtResponse && array_key_exists($this->_dataKeyAtResponse, $dataObject) ? $dataObject[$this->_dataKeyAtResponse] : $dataObject; } else { // Uknown result return $dataObject; } } else { return $this->_response->getContent(); } }
Jälleen kerran laiskat tottumukseni saivat minut lisäämään kääreitä, jotka on suunniteltu testaamaan CRUD-sivuja:
create($data = [], $autoCheckStatus = true, $autoDecode = true, $files = []) show($id, $data = [], $autoCheckStatus = true, $autoDecode = true) update($id, $data = [], $autoCheckStatus = true, $autoDecode = true, $files = []) delete($id, $data = [], $autoCheckStatus = 204, $autoDecode = false) index($data = [], $autoCheckStatus = true, $autoDecode = true)
Yksinkertainen testikoodi näyttäisi tältä:
// send wrong request // Validation error has code 422 in out specs $response = $this->create(['title'=>'', 'intro'=>'Ha-ha-ha. We have validators'], 422); // Try to create correct webshop $dataObject = $this->create( $data = [ 'title'=>'Super webshop', 'intro'=>'I am webshop', ] ); $this->assertGreaterThan(0, $dataObject->id); $this->assertData($data, $dataObject); // Try to request existing resource with method GET $checkData = $this->show($dataObject->id); // assertData is also a help method for validation objects with nested structure (not a part of PHPUnit). $this->assertData($data, $checkData); // Try to update with not valid data $this->update($dataObject->id, ['title'=> $data['title'] = ''], 422); // Try to update only title. Description should have old value. Title - changed $this->update($dataObject->id, ['title'=> $data['title'] = 'Super-Super SHOP!!!']); // Then check result with reading resource $checkData = $this->show($dataObject->id); $this->assertData($data, $checkData); // Read all created resources $list = $this->index(); $this->assertCount(1, $list); // TODO:: add checking for each item in the collection // Delete resoure $this->delete($dataObject->id); $this->show($dataObject->id, [], 404);
Tässä on toinen hyödyllinen toiminto vastaustietojen, mukaan lukien suhteiden ja sisäkkäisten tietojen, vahvistamiseksi:
public function assertData($input, $checkData){ // it could be stdClass object after decoding json response $checkData = (array)$checkData; foreach($input as $k=>$v){ if (is_array($v) && (is_object($checkData[$k]) || is_array($checkData[$k]))) { // checking nested data recursively only if it exists in both: response data($input) and expected($checkData) $this->assertData($v, $checkData[$k]); } else { $this->assertEquals($v, $checkData[$k]); } } }
Pitkät tehtävät ovat yleinen pullonkaula verkkosovelluksissa. Yksinkertainen esimerkki olisi PDF-raportin luominen ja jakelu organisaation sisällä, mikä voi viedä paljon aikaa.
Käyttäjäpyyntöjen estäminen tämän toiminnon suorittamiseksi ei ole toivottava tapa käsitellä ongelmaa. Käyttämällä Queue
Laravelissa on loistava tapa käsitellä ja asettaa jonoon taustalla olevia pitkäaikaisia tehtäviä.
Yksi viimeisistä aiheista oli PDF-tiedostojen luominen ja raporttien lähettäminen sähköpostitse. Käytin Beanstalkdille oletusjonoajuria, jota tuettiin paketilla pda / pheanstalk. Tehtävien lisääminen jonoon on erittäin helppoa
Esimerkiksi PDF-tiedostojen luominen ja lähettäminen voidaan tehdä näin:
Queue::push('FlexiCallQueuePdfSend', [....data for sending to job's handler..], 'default');
Meidän PdfSend
käsittelijä voitaisiin toteuttaa näin:
class PdfSend extends BaseQueue{ function fire($job, $data){ //............................. //..... OUR IMPLEMENTATION..... //............................. } }
Laravel-määritykset viittaavat jonon seuraamiseen --daemon
vaihtoehtoja, mutta käytän valvontademonia, joka pitää sen käynnissä pysyvästi:
php artisan queue:listen --env=YOUR_ENV
Jonot sopivat hyvin esimerkiksi tietojen tallentamiseen. Niitä voidaan käyttää epäonnistuneiden töiden toistamiseen, uniaikojen lisäämiseen ennen töiden suorittamista jne.
Olen maininnut muutamia keskeisiä kohtia, jotka liittyvät Laravel-kehitys tässä Laravel-katsauksessa. Se, miten kokoat kaiken yhteen ja rakennat sovelluksesi, riippuu omasta asetuksestasi ja projektistasi. Tässä on kuitenkin lyhyt tarkistuslista vaiheista, jotka kannattaa harkita:
Oletussuodatin 'ennen' luo maailmanlaajuisen laajuuden singletonina ja käynnistää ajastimen suorituskyvyn seuraamiseksi:
class AppBefore { function filter($request) { App::singleton('scope', function() { $scope = new AppScope();//My scope implementation $scope->startTimer(); return $scope; }); } }
”After” -suodatin pysäyttää ajastimen, kirjaa sen suorituskykylokiin ja lähettää CORS-otsikot.
class AppAfter{ function filter($request, $response){ $response->header('Access-Control-Allow-Origin', '*'); $response->header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); $response->header('Access-Control-Allow-Headers', 'Content-Type'); $response->header('Access-Control-Max-Age', '86400'); App::make('scope')->endTimer(); App::make('scope')->logTotalTime(); return $response; } }
Kunkin moduulin kehittäminen edellyttää todennäköisesti näitä vaiheita:
Määritä tietojen siirto ja siementen oletustiedot. Toteuta mallit ja suhteet, muuntajat, validoijat ja puhdistusaineet (tarvittaessa). Kirjoita yksikötestit. Toteuta ohjaimet ja suorita testit.
Olen käyttänyt Laravelia yli vuoden. Kuten minkä tahansa tekniikan kohdalla, oli joitain hampaiden puhkeamiseen liittyviä ongelmia, mutta uskon, että Laravelin oppiminen on vakuuttanut minut siitä, että se on hämmästyttävä kehys. On vielä muutama asia, jota en ole maininnut tässä Laravel-opetusohjelmassa, mutta jos olet kiinnostunut oppimaan lisää, kannattaa harkita näitä kohtia ja ominaisuuksia:
Onnea ja pysy kuulolla, Laravel on lupaava kehys, ja uskon sen olevan olemassa vuosien ajan.
Liittyvät: Täysi käyttäjän todennus ja kulunvalvonta - Laravel Passport Tutorial, Pt. 1