Laravel

De Cacauet Wiki
Salta a la navegació Salta a la cerca

#FpInfor #DawMp07 #DawMp07Uf2 #DawMp07Uf02 #DawMpDual


Intro i referències

Laravel és un framework web per a PHP que està agafant molta força.

Documentació oficial: https://laravel.com/docs/

Tutorials:


Plugins:

Temes a ampliar:


Instal·lació i setup

Prerequisits:

  • Laravel i PHP, és molt important tenir en compte les versions:
    • Laravel 5.3 : PHP >= 5.6.4
    • Laravel 5.5 : PHP == 7.0
    • Laravel 5.6 : PHP >= 7.1
    • Laravel 5.7 : PHP >= 7.1.3
    • Laravel 6.x : PHP >= 7.2
  • Si utilitzes Ubuntu 14 o menor actualitza la teva versió de PHP a la 7.0
  • Calen els paquets següents:
    $ sudo apt-get install php-mbstring php-zip php-xml php-mysql

Anem a posar-nos-hi. Tot i que en futures versions les passes no haurien de diferir molt, hi ha força detalls que acaben fer-nos la punyeta, gangues de l'ofici...:

  1. Instal·la el gestor de paquets per PHP Composer
    • El més fàcil és fer: (però no ho farem pq volem la darrera versió)
      $ sudo apt install composer
    • Prova primer la instal·lació genèrica : Instal.la PHP Composer
    • També tens aquesta altra forma d' instal·lar Composer per GNU/Linux. Descarrega composer-setup.php i instal·la'l així:
      $ php composer-setup.php --install-dir=~/bin --filename=composer
  2. Instal·la la darrera versió de Laravel
    • https://laravel.com/docs/5.7/installation
    • Bàsicament el què cal fer és aquesta comanda per instal·lar el binari laravel:
      $ composer global require laravel/installer
    • Laravel s'instal·la a $HOME/.config/composer però per poder executar les properes comandes necessitarem tenir $HOME/.config/composer/vendor/bin al nostre $PATH. Inserta això al teu $HOME/.profile:
      PATH=$PATH:~/.config/composer/vendor/bin
      Fes logout/login del sistema per activar aquests canvis
  3. Crea una app Laravel allà on et faci més ràbia:
    $ laravel new laravelapp1
    o també:
    $ composer create-project --prefer-dist laravel/laravel laravelapp1
    o si volem una versió específica de laravel:
    $ composer create-project --prefer-dist laravel/laravel=5.8.* laravelapp1
  4. Arrenca l'aplicació de prova:
    $ php artisan serve
  5. Comprova la app amb el navegador a
    http://localhost:8000


Si ja has completat la instal·lació, pots procedir a crear un altre projecte nou i realitzar el següent tutorial "tasklist":

https://laravel.com/docs/5.2/quickstart


Incidències vàries

Aquest és un bon tutorial:

https://ajgallego.gitbooks.io/laravel-5/content/index.html

Igualment, podríem trobar algunes incidències. Us dono pistes:

Treballant amb GIT i clonant

Al pujar el projecte a un repo GIT, i clonar-lo després caldrà:

  1. Re-instal·lar les dependències:
    $ composer install
  2. Regenerar arxiu .env : com que depèn de cada entorn no es fica al projecte (es posa a .gitignore), però pots copiar i modificar de .env.example
  3. Error The only supported ciphers are AES-128-CBC and AES-256-CBC with the correct key lengths. Es soluciona amb :
    $ php artisan key:generate

Creant controllers amb CRUD complert

Per crear un controller complert, és més simple si ho fem com a RESOURCE. Ens crearà tots els mètodes i les rutes necessàries per a un CRUD.

  1. Ja no es pot fer amb Route::controller sinó amb:
    Route::resource("cosa","CosaController");
  2. Per exemple, per crear un controller per al model "Cosa" ho faríem amb -r (de resource):
    $ php artisan make:controller -r CosaController

Treballant amb SQLite

Per configurar la BD amb SQLite cal crear el fitxer abans amb:

$ touch db.sqlite

Configurar la BD a .env:

DB_CONNECTION=sqlite
DB_DATABASE=/path/absolut/al/db.sqlite

Instal·lar els binaris necessaris de SQLite i de PHP:

$ sudo apt-get install sqlite php-sqlite3

I crear la BD inicial amb:

$ php artisan migrate

Per manipular la base de dades SQLite pot ser-te útil una interfície gràfica com sqliteman o sqlitebrowser, disponibles als repositoris del SO.

Eliminant models o migracions

Si en algun moment heu afegit algun model o migració innecessàries, i les voleu esborrar, només cal esborrar l'arxiu pertinent i, seguidament, fer:

$ composer dump-autoload

...i es tornaran a generar els arxius d'autoload sense els arxius que volíem esborrar.

Treballant amb proxies i composer

De vegades els proxies ens juguen males passades i impedeixen que es descarreguin normalment els paquets del composer. Si us trobeu que al fer composer update o alguns composer require us demana una autenticació de packagist.org com ara aquesta, NO us funcionarà (per molt que us creeu un usuari a packagist o el què sigui):

$ composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
(...demana user/password de packagist.org ...)

La solució és saltar-nos el proxy del centre amb un túnel i un altre proxy (squid en aquest cas). Si tenim un servidor por ai, podem connectar-nos i fer un pont:

$ ssh -L 3128:localhost:3128 [email protected]

I un cop logats, aprofitem per instal·lar el squid:

$ sudo apt install squid

Hem de mantenir la shell oberta mentre vulguem que estigui activat el túnel (l'hem assignat a localhost:3128).

Obrim una altra shell i anem al nostre projecte Laravel:

$ export http_proxy=localhost:3128
$ composer update

Un cop ho hagueu fet un cop, ja funcionarà bé sempre i no caldrà que feu més el túnel (podeu tancar les dues shells obertes i obrir una tercera per treballar normalment).

També podeu desinstal·lar el squid de la vostra màquina remota, potser no és bo tenir-lo obert, per molt firewall que pugui haver entremig:

$ ssh [email protected]
$ sudo apt remove squid


Tutorials

Després d'elaborar la documentació he trobat aquest tutorial bastant útil (només fins la v5.2):

https://laravel.com/docs/5.2/quickstart

Tutorial per a CRUD complert:

https://www.itsolutionstuff.com/post/laravel-6-crud-application-tutorialexample.html

Resum per a fer un CRUD

Setup projecte

Crear projecte:

$ laravel new proj1

Crear DB (en aquest cas SQLite:

$ touch db.sqlite

Modifica .env per configurar la DB com sqlite:

DB_CONNECTION=sqlite
DB_DATABASE=/path/absolut/al/db.sqlite

Model

Crear taules i migracions:

$ php artisan make:migration crea_taula_items --create=items

Editar la migració per crear les taules adequades. Mira't les principals referències:

Realitzar la migració:

$ php artisan migrate

Crear models:

$ php artisan make:model Item

Ajusta el model perquè apunti al nom correcte de la taula:

https://laravel.com/docs/5.5/eloquent#eloquent-model-conventions

Controller i rutes

Crear controllers amb els mètodes estàndard (index, create-store, show, edit-update, destroy):

$ php artisan make:controller -r ItemController

Crear rutes a routes/web.php:

Route::resource("item","ItemController");

Crear plantilles per als mètodes (l'exemple diu "tema" enlloc de "item"):

$ php artisan route:list
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+
| Domain | Method    | URI                   | Name           | Action                                        | Middleware   |
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+
|        | GET|HEAD  | /                     |                | Closure                                       | web          |
|        | GET|HEAD  | api/user              |                | Closure                                       | api,auth:api |
|        | GET|HEAD  | tema                  | tema.index     | App\Http\Controllers\TemaController@index     | web          |
|        | POST      | tema                  | tema.store     | App\Http\Controllers\TemaController@store     | web          |
|        | GET|HEAD  | tema/create           | tema.create    | App\Http\Controllers\TemaController@create    | web          |
|        | GET|HEAD  | tema/{tema}           | tema.show      | App\Http\Controllers\TemaController@show      | web          |
|        | PUT|PATCH | tema/{tema}           | tema.update    | App\Http\Controllers\TemaController@update    | web          |
|        | DELETE    | tema/{tema}           | tema.destroy   | App\Http\Controllers\TemaController@destroy   | web          |
|        | GET|HEAD  | tema/{tema}/edit      | tema.edit      | App\Http\Controllers\TemaController@edit      | web          |
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+

Crear les views (plantilles blade) adequades per a tots els mètodes necessaris (els arxius van a resources/views). Pots veure aqui alguns exemples.

  • index : llista tots els elements
  • show : mostra un element en concret, necessita que li passem un paràmetre per GET (id del element a mostrar)
  • create-store : "create és el form (no necessita codi), i "store" és el codi per insertar-ho a la BD (no necessita una plantilla)
  • edit-update : "edit" és el form, i "update" el codi per actualitzar la BD
  • destroy : elimina un element

Codi del Controller i View

Més docs

Una bona referència de la doc oficial per fer un CRUD és aquesta:

https://laravel.com/docs/5.2/quickstart

En particular per veure com utilitzar les templates oficials amb bootstrap ;)


Projecte d'exemple

Aquest és el projecte que he realitzat per entrenar-me, et pot servir d'exemple. El pots veure en producció aquí: https://jolgorio.tk

https://github.com/emieza/laravel-karaoke

Fes-li un cop d'ull al readme.md per veure com posar-lo en marxa.

MOLT IMPORTANT PEL PROJECTE: Cal crear un README.md (com per exemple aquest). No acceptaré cap projecte sense README.md

Per entrenar-vos amb el Markdown teniu aquest tester:

http://dillinger.io/

Anem per feina:

  1. Taules: llistes, temes, vots
  2. Rutes que vols implementar per al projecte. En el meu cas, tinc:
    • /llista/crea (GET per formulari + POST per store)
    • /llista (index de llistes)
    • /llista/{id} (show)
    • /llista/{id}/crea (GET + POST, per crear temes en les llistes)
    • /vota/{idtema}
  3. Codi:


ORM : Models i relacions

El ORM o Object-Relational Model és una eina molt potent que es permetrà accedir a la base de dades relacional amb objectes del nostre framework, facilitant-nos molt la feina d'accés a les dades.

Per facilitar el nostre codi dins de les views (templates) i controllers, serà important fer una sèrie d'ajustos en els models per permetre que des d'un objecte es pugui accedir a un altre.

El què anem a explicar està documentat a l'apartat "Eloquent ORM" de Laravel:

https://laravel.com/docs/5.7/eloquent-relationships
https://laravel.com/docs/6.x/eloquent-relationships

Accedint relacions 1-N de forma directa

El primer cas típic és accedir a les dades d'un element "pare" o amb el què el nostre objecte està relacionat. Per exemple, un comentari en un post d'un blog. Tenim l'objecte Comment, que té la seva pròpia FK a Post. Però el què tenim al model és la ID de la relació, i no l'objecte en sí.

L'objectiu serà poder accedir a l'objecte pare d'aquesta manera per mostrar el text del Post (pare).

 $comment = Comment::find(33);
 echo $comment->post->text;

Per aconseguir això, cal que indiquem la relació existent a les taules entre els models Post i Comment amb la relació belongsTo:

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
    /**
     * Accedeix al pare (Post)
     */
    public function post()
    {
        return $this->belongsTo('App\Post','post_id');
    }
}

Accedint relacions 1-N de forma inversa

El següent cas típic serà accedir des d'un objecte Post als diferents Comentaris, més o menys així:

 $comments = App\Post::find(1)->comments;
 foreach ($comments as $comment) {
     // ... el teu codi...
     echo $comment->text;
 }

El codi que veiem és per a un controller, però es pot aplicar també als templates, amb @foreach i similars.

Per poder utilitzar el codi anterior, però, abans caldrà que facis un ajust del model, tal i com s'explica aquí: https://laravel.com/docs/5.5/eloquent-relationships#one-to-many

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
    /**
     * Accedeix als comentaris relacionats amb el Post actual
     */
    public function comments()
    {
        return $this->hasMany('App\Comment','<ref_remota>','<ref_local>');
    }
}

On:

  • <ref_remota> és el camp de la taula de Comment que referencia el Post
  • <ref_local> és el camp de Post que fa de PK i on Comment apunta

Per accedir al objecte relacionat "pare" caldrà fer una altra funció, en concret belongsTo. Consulta la doc de les relacions 1-a-N (inversa).

Depenent del tipus de relació ens caldrà aplicar una funció o una altra. La més habitual serà la relació 1-a-N, però recorda que també hi ha 1-a-1 i també N-a-N:

https://laravel.com/docs/5.5/eloquent-relationships#one-to-many

Aniuant JSON en la API

Això que hem fet és particularment important quan volem elaborar respostes JSON amb dades aniuades. Normalment una query standard equival a un espai de 2 dimensions i no poden haver aniuaments. Però si definim correctament les relacions al model tal i com hem descrit a l'apartat anterior (en ambdues bandes, belongsTo i hasMany) podrem aniuar les dades utilitzant WITH en la query del ORM:

<?php
Route::get("/comentaris", function() {
    $post = Post::with("comments")->get();
    return $post;
});

...i ens retornarà les dades aniuades que volem! :)


Més coses

Alguns temes que no hem aprofundit però que convé conèixer.

Autenticació

Senzill d'implementar i imprescindible. Laravel incorpora un scaffold per facilitar una funció tan estàndard. Amb una sola instrucció ens crea les rutes, vistes i els controllers típics (login, logout).

Laravel 5.x

Autenticació en Laravel 5.x:

$ php artisan make:auth

Laravel 6.x

Autenticació en Laravel 6.x:

$ composer require laravel/ui --dev
$ php artisan ui vue --auth

Laravel 6.x utilitza el framework Vue i de vegades no compila automàticament els assets (recursos). En aquest cas el login screen no es renderitza correctament i apareix sense CSS. Es pot solucionar compilant-ho correctament amb:

$ npm install && npm run dev

També hi ha solucions al problema carregant els CSS i JS del CDN (només cal canviar un link en el head de app.blade.php.

Laravel 8.x

Ara el mòdul d'autenticació es diu Laravel Breeze.

ULL! Laravel Breeze està pensat per afegir-ho al projecte Laravel a l'inici de la creació d'aquest. Quan l'instal·lem, Breeze sobreescriurà arxius d'algunes views i routes. Si l'instal·leu en un projecte en curs, abans de procedir feu un backup dels possibles arxius que hagueu creat:

  • routes/web.php
  • resources/views/layouts/app.blade.php
  • resources/views/layouts/guest.blade.php
  • resources/views/layouts/navigation.blade.php
  • resources/views/auth/*
  • resources/views/components/*
  • resources/views/welcome.blade.php
  • resources/views/dashboard.blade.php

Resumint, per instal·lar Breeze:

$ composer require laravel/breeze --dev
$ php artisan breeze:install
$ npm install
$ npm run dev

Rols d'usuari

En molts moments pot interessar tenir diversos rols d'usuari (admin, usuari, redactor, etc.).

Aquest post explica com utiltizar rols d'usuari amb els sistemes bàsics d'autenticació de Laravel (Breeze, etc.).


Desactivar registre d'usuaris

Hi ha diverses maneres de desactivar el registre d'usuaris segons els mètodes d'autenticació triats (Breeze, JetStream o Fortify).

Una manera senzilla d'aconseguir-ho és anar a les rutes de registre i comentar-les.

Seeding

Una part molt important és la de crear dades per farcir la base de dades inicialment i poder així testejar amb comoditat.

https://laravel.com/docs/6.x/seeding

En algun moment donat convé utilitzar un factory que ens permet crear elements en massa:

https://laravel.com/docs/6.x/database-testing#writing-factories

El factory sol utilitzar una llibreria Faker que ens va molt bé per crear noms i cognoms aleatoris, lorem ipsum, etc. que ens facilitarà la creació de dades de prova.

https://github.com/fzaninotto/Faker

Validacions

Laravel ens ofereix un mecanisme de validació de formularis molt potent i efectiu.

https://laravel.com/docs/5.5/validation

Sessions

D'entrada és molt útil per emetre missatges "flash", i informar l'usuari del processament intern.

https://laravel.com/docs/5.5/session

Arxius: filesystem vs BLOBs en BD

Les imatges es poden guardar al sistema d'arxius o bé a la base de dades.

A solucionar

Alguns temes a solucionar:


Atacant 2 bases de dades simultàniament

En alguns casos podem necessitar configurar 2 instàncies de bases de dades separades per optimitzar el rendiment. Aquest post ho explica molt bé:

https://fideloper.com/laravel-multiple-database-connections

Caldrà configurar el .env , config/database.php i especificar quina DB ataca en les migracions i en els models que creem.


Laravel i LDAP

Aquest mòdul està pensat per a Active Directory, però també funciona amb OpenLDAP si s'ajusta bé:

https://github.com/Adldap2/Adldap2-Laravel

Primer cal configurar un servidor LDAP.

Després, tingues en compte que cal ajustar els següents paràmetres en el .env:

ADLDAP_CONTROLLERS=localhost
#ADLDAP_PORT=389
ADLDAP_ADMIN_USERNAME="cn=admin,dc=cacauet,dc=org"
ADLDAP_ADMIN_PASSWORD="enric123"
ADLDAP_BASEDN="dc=cacauet,dc=org"

Podem fer una autenticació seguint algun d'aquests exemples.

Exemple 1: cercar un element del directori

    $user = Adldap::search()->where("mail","=","[email protected]")->get();

Exemple 2: autenticar un usuari

    if( Adldap::auth()->attempt("cn=pepe,ou=usuaris,dc=cacauet,dc=org","pepe123")) {
        // autenticació exitosa
        return "Pepe OK!";
    }


Laravel en producció

Per posar en producció un projecte basat en Laravel cal tenir en compte:

  • IMPORTANT, SEGURETAT: Només cal publicar la carpeta /public . La resta de carpetes son les de desenvolupament, i son INTERNES del projecte. Ningú ha de tenir accés a elles. Tot el què necessita saber el webserver (probablement Apache) és quina carpeta és la pública, i la resta ha de romandre privat, inaccessible per .
    • Aquesta carpeta /public no figura inicialment quan creem o clonem un projecte (està a .gitignore), a l'igual que la carpeta /vendor, que es generen quan fem un $ composer install.
    • Reviseu la secció Laravel#Treballant_amb_GIT_i_clonant per fer el setup del projecte després de clonar.
  • mod_rewrite: Laravel es basa en RUTES i no en arxius en un filesystem, com sí que fa Apache per defecte. Per corregir això necessitem el mod_rewrite, que reescriu les URLS per traduïr-les de la versió route a la versió "Apache" (o equivalents per a altres web servers).
  • Caldrà corregir els permisos de carpetes i arxius de producció perquè Apache (www-data, _www o httpd depenent de la distribució) pugui accedir. En particular:
    • db.sqlite (si s'escau)
    • carpeta /storage
    • carpeta /bootstrap/cache

Desplegament en AWS amb Ubuntu i Apache

Guia pel desplegament en Ubuntu amb Apache:

  • Accedir al nostre servidor via SSH
  • Descarregar el codi Laravel (preferentment clonant amb GIT (tot i que també es pot fer un SCP) a una carpeta no-pública, però a la que Apache pugui accedir, típicament
    /var/www
  • Per veure detalls reviseu la secció Laravel#Treballant_amb_GIT_i_clonant. Recordeu que això implica:
    1. composer install
    2. configurar arxiu .env
    3. generar clau
  • Es requereix el mòdul mod_rewrite d'Apache (o Nginx)
    $ sudo a2enmod rewrite
  • Publicar la carpeta /public del projecte Laravel, d'alguna d'aquestes maneres:
    • Crear un VirtualHost i apuntar la ServerRoot del domini o subdomini a /var/www/<projecte>/public
    • Crear un link simbòlic de la carpeta pública d'Apache a la carpeta public del Laravel amb la comanda
      $ ln -s /var/www/<projecte>/public /var/www/html/lara1
  • Laravel es basa en RUTES i no en arxius en un filesystem, com sí que fa Apache per defecte. Per corregir això necessitem el mod_rewrite, que reescriu les URLS per traduïr-les de la versió route a la versió "Apache".
  • Ajusta els permisos de:
    • db.sqlite (si s'escau) i també de la carpeta que el conté (si no, no es podrà escriure-hi)
    • carpeta /storage
    • carpeta /bootstrap/cache
  • Cal activar els arxius .htaccess , afegint la directiva AllowOverride all

A l'arxiu de conf. del nostre VirtualHost (a /etc/apache2/sites-available):

<Directory /var/www/>
     AllowOverride All
</Directory>


És important remarcar que per SEGURETAT no hem de mostrar mai els arxius interns de Laravel, només cal publicar el contingut de /public


Heroku

Abans de procedir amb aquesta part hauries de llegir i treballar aquesta altra: Heroku on treballem amb PHP simple.

Pots posar en marxa un projecte Laravel a Heroku fàcilment seguint aquesta documentació. Segueix el tutorial per iniciar la app:

https://devcenter.heroku.com/articles/getting-started-with-laravel

L'inconvenient és posar en marxa la base de dades. Si ho fas amb sqlite utilitza el propi sistema d'arxius, però la contrapartida és que Heroku utilitza un sistema d'arxius efímer, i quan tornem a fer un push s'esborra tot.

En el cas de voler un MySQL, tot i que els termes d'ús són gratuïts si no hi ha gaire volum de dades i/o trànsit, demanarà que entris la targeta de crèdit.

En canvi, el add-on de POSTGRESQL és gratuït i sense targeta de crèdit! :) Som-hi, doncs!

Primer de tot, creeu el projecte Laravel i inicialitzeu GIT en cas que no el tingueu penjat a Github o similars:

$ git init

Tb caldrà afegir un Procfile adequat per Laravel:

$ echo "web: vendor/bin/heroku-php-apache2 public/" > Procfile

Inicialitzem projecte Heroku:

$ heroku create elmeuprojectedeguais

Afegim els arxius al repo local:

$ git add .
$ git commit -am "primer commit"

Afegim la BD PostgreSQL:

$ heroku addons:create heroku-postgresql:hobby-dev

I configurar la nostra base de dades perquè el Laravel la utilitzi. Primer de tot observem el connection string que ens dona Heroku quan hem creat la BBDD:

$ heroku config -s | grep -i post

Ens ho dona en la següent forma (exemple a continuació):

DATABASE_URL='postgres://<usuari>:<password>@<maquina>:<port>/<bbdd>'
DATABASE_URL='postgres://mxlsfebqyopadb:3e5af56b52cc06574645123ea9d9f7504564e207804dcc71a2db2848446ba064@ec2-156-73-167-43.compute-1.amazonaws.com:5432/d353ihheo564q7'

Així, doncs, només caldrà ajustar les següents variables d'entorn que necessita el Laravel perquè això funcioni:

DB_CONNECTION=pgsql
DB_HOST=ec2-156...
DB_PORT=5432
DB_DATABASE=d353...
DB_USERNAME=mxls...
DB_PASSWORD=3e5a...

Per fer-ho cal anar executant les següents ordres:

$ heroku config:set DB_CONNECTION=pgsql
$ ...etc...

I també carregueu una APP_KEY, que sol estar a l'arxiu .env. Si no la teniu, genereu un arxiu .env i genereu la clau:

$ cp .env.example .env
$ php artisan key:generate
$ heroku config:set APP_KEY=base64:tX2ikx...

En acabat, podem posar la app en producció:

$ git add .
$ git push heroku master

I un cop acabats, migrem la nostra base de dades:

$ heroku run php artisan migrate

I veure la nostra flamant web en producció (a elmeuprojectedeguais.herokuapp.com):

$ heroku open

...et voilà!


Serveis web amb Laravel

Serveis web amb Laravel