https://cacauet.org/wiki/api.php?action=feedcontributions&user=Enric&feedformat=atomCacauet Wiki - Contribucions de l'usuari [ca]2024-03-28T08:29:49ZContribucions de l'usuariMediaWiki 1.34.0https://cacauet.org/wiki/index.php?title=Fitxer:Teoria.email1.png&diff=4256Fitxer:Teoria.email1.png2023-04-18T18:32:39Z<p>Enric: Enric ha carregat una nova versió de Fitxer:Teoria.email1.png</p>
<hr />
<div></div>Enrichttps://cacauet.org/wiki/index.php?title=Fitxer:Webmail.png&diff=4255Fitxer:Webmail.png2023-04-18T18:29:48Z<p>Enric: Enric ha carregat una nova versió de Fitxer:Webmail.png</p>
<hr />
<div></div>Enrichttps://cacauet.org/wiki/index.php?title=Fitxer:Teoria.email1.png&diff=4254Fitxer:Teoria.email1.png2023-04-18T18:28:24Z<p>Enric: Enric ha carregat una nova versió de Fitxer:Teoria.email1.png</p>
<hr />
<div></div>Enrichttps://cacauet.org/wiki/index.php?title=Fitxer:Yeti_1.jpg&diff=4253Fitxer:Yeti 1.jpg2022-12-03T22:04:58Z<p>Enric: </p>
<hr />
<div></div>Enrichttps://cacauet.org/wiki/index.php?title=Programaci%C3%B3_web_entorn_servidor&diff=4252Programació web entorn servidor2022-09-09T09:10:22Z<p>Enric: </p>
<hr />
<div><nowiki>#FpInfor #DawMp07<br />
#DawMp07Uf01 #DawMp07Uf02 #DawMp07Uf03 #DawMp07Uf04<br />
</nowiki><br />
<br />
<br />
En aquesta assignatura treballarem bàsicament amb PHP, que actualment és el llenguatge més estès per a la programació web.<br />
<br />
Recursos:<br />
* Al cacauet.org disposeu del [[Curs de PHP]]<br />
* Al repositori Github del que va ser el [https://github.com/ctrl-alt-d/FpUf/tree/main/DAW/DAW-MP07 quadern d'exercicis del Daniel Herrera].<br />
<br />
<br><br />
<br />
== UF1 Programació web entorn servidor ==<br />
Per configurar adequadament el Apache, reviseu [[Php.ini]]<br />
<br />
[https://uf.ctrl-alt-d.net/material/mostra/288/abc-index-dexercicis Índex d'exercicis]<br />
<br />
Temes a tractar amb PHP:<br />
* [[Web_technology_overview|Execució servidor vs client]]<br />
* Servidor web<br />
* Tipus primitius de dades<br />
* Arrays i arrays associatius (aka "diccionaris")<br />
* Control de flux<br />
* Funcions<br />
* Objectes<br />
* Arxius<br />
* [[PHP Forms|Formularis]]<br />
* GET vs POST<br />
* Cookies i [[PHP sessions]]<br />
<br />
Exemples:<br />
* [[Batalla naval en PHP]] (versions amb i sense sessions)<br />
<br />
Exercicis entregables:<br />
# [https://uf.ctrl-alt-d.net/material/mostra/294/calendari-en-php Calendari]<br />
# [https://uf.ctrl-alt-d.net/material/mostra/40/php-els-ingredients-de-la-pizza La pizza]<br />
# [https://uf.ctrl-alt-d.net/material/mostra/299/php-sudoku-amb-formularis-i-sessions Sudoku]<br />
# [https://uf.ctrl-alt-d.net/material/mostra/307/moviment-duna-peca-descacs-en-php Moure una peça d'escacs].<br />
<br />
<br><br />
<br />
== UF3 Accés a dades ==<br />
En aquesta UF estudiarem diversos mètodes d'accés a bases de dades, imprescindibles per poder realitzar pàgines web dinàmiques.<br />
<br />
Índex UF3 al quadern d'exercicis:<br />
https://github.com/ctrl-alt-d/FpUf/tree/main/DAW/DAW-MP07/DAW-MP07-UF3/tecniques-dacces-a-dades-metacontingut<br />
<br />
Començarem, però, per alguns exemples clàssics: [[Imatge:Filtre-continent.png|thumb|Llistat de països filtrats per continents.]]<br />
# [[PHP MySQL select]]: accedirem a una base de dades de la manera més clàssica i menys eficient, amb instruccions específiques per a un SGBD concret (MySQL). Òbviament, això no és gaire òptim però està bé conèixer els mecanismes bàsics.<br />
# '''PDO''' o PHP Data Objects<br />
#* Llegeix-te aquest [https://github.com/ctrl-alt-d/FpUf/tree/main/DAW/DAW-MP07/DAW-MP07-UF3/php-acces-a-dades-amb-pdo exercici d'accés a dades amb PDO].<br />
#*:Para atenció en com es fa el ''foreach'' enlloc del ''for'' habitual.<br />
#* Exercici: Utilitza la base de dades WORLD vista al primer tutorial.<br />
#** Fes un formulari amb un desplegable dels CONTINENTS.<br />
#** Llista els països amb un filtre per continent.<br />
#** Mostra la població de cada país i un total de tot el continent.<br />
<br />
<br><br />
<br />
El projecte d'aquest any: [https://wiket.esteveterradas.cat/index.php/Projecte_Vota_-_Especificacions Projecte VOTA!]<br />
<br />
[[Imatge:Vota4.jpg|450px]]<br />
<br />
<br><br />
<br />
== UF2 Programació de webs dinàmiques ==<br />
Prèviament hem après a programar ja en PHP i amb bases de dades, però hem aprés de forma un tant anàrquica, i hem vist en el transcurs dels projectes que tendim a fer "codi espagueti" i acabem repetint moltes parts del mateix de forma recorrent. En aquesta UF aprendrem a programar de forma més ordenada i aprendrem una sèrie d'eines imprescindibles per desenvolupar de forma segura i metòdica: els '''''frameworks'''''. En particular utilitzarem [[Laravel]] que és el ''framework'' per a PHP més famós actualment (a principis de 2018).<br />
<br />
Un framework es sol definir com:<br />
- un conjunt d'eines i llibreries<br />
- un conjunt de bones pràctiques per treballar amb aquestes eines<br />
<br />
Introducció i referències:<br />
* [[Desenvolupament d'aplicacions web amb frameworks]] una mica de teoria.<br />
* [[Laravel]]: instal·lació i primeres passes<br />
* Apunts del Sergi Coll: https://seicoll.github.io/DAW-M07-UF2-Apunts/<br />
* Tutorial de referència: https://ajgallego.gitbooks.io/laravel-5/content/index.html<br />
* [[Laravel#Quickstart_per_a_fer_un_CRUD|Xuleta de referència ràpida per a projectes amb Laravel]]<br />
<br />
Una de les característiques més incòmodes dels frameworks és que tenen una certa "corba d'aprenentatge", és a dir, que al principi costa una mica ficar-se. Un cop superat el segon projecte, tot resulta més fàcil i comprensible, i ajuda a programar amb ordre i de forma estandarditzada.<br />
<br />
Farem servir el tutorial de AJ Gallego per a endinsar-nos en el món de Laravel. Com que té la seva complicació i costa retenir cada pas que fem, dividirem el tutorial en diverses parts i repetirem el procediment realitzat en un altre projecte. Per senzillesa repetirem el projecte de la UF anterior però implementat ara amb el ''framework'', cosa que ens permetrà comparar el codi resultant dels dos projectes.<br />
<br />
El tutorial és aquest:<br />
https://ajgallego.gitbooks.io/laravel-5/content/index.html<br />
Com que algunes parts han quedat obsoletes, utilitza la [[Laravel|documentació de cacauet.org sobre Laravel]] per solventar els problemes. <br />
<br />
I les seves diverses parts son:<br />
# Instal·lació i eines Composer: [[Laravel#Instal.C2.B7lació_i_setup]]<br />
# Vistes i Controladors<br />
# Model i base de dades<br />
# Autenticació i autorització (middleware)<br />
<br />
Realitzarem totes aquestes passes primer amb el propi tutorial, i amb el projecte de la UF anterior (Vota2) de forma individual, per consolidar la comprensió de la mecànica del ''framework''.<br />
<br />
Al final de la UF realitzarem un projecte en grups. Aquest any serà el [https://wiket.esteveterradas.cat/index.php/Projecte_Xat_-_Especificacions projecte Xat per a un Ajuntament].<br />
<br />
Els lliuraments finalment seran:<br />
* Repositori del Github del tutorial (individual)<br />
* Repositori del Github del projecte Vota2 (individual)<br />
* Repositori del Github del projecte Xat (en grup)<br />
<br />
<br><br />
<br />
== UF4 Serveis web ==<br />
Els [https://ca.wikipedia.org/wiki/Servei_web serveis web], simplificant, és una manera de realitzar '''crides a funcions remotes''' mitjançant el protocol HTTP. És la forma més còmoda per al programador web d'anar a buscar dades a un servidor, ja sigui des d'un altre servidor o des d'un client.<br />
<br />
Al tractar-se, com hem dit, de "crides a funcions remotes", solem anomenar-los [https://ca.wikipedia.org/wiki/Interf%C3%ADcie_de_programaci%C3%B3_d'aplicacions API : Application Programming Interface].<br />
<br />
Articles de referència:<br />
* [[Serveis Web]]<br />
* [[Serveis web amb Laravel]]<br />
* Pràctica entregable: [[Serveis Web amb Opendata]]<br />
* Material addicional en Python: [[Web Services: exemple Escacs]]<br />
* [https://ajgallego.gitbooks.io/laravel-5/content/capitulo_5.html REST i CURL del tutorial de Laravel de AJ Gallego]<br />
<br />
<br></div>Enrichttps://cacauet.org/wiki/index.php?title=Correu_electr%C3%B2nic&diff=4251Correu electrònic2022-05-16T14:15:19Z<p>Enric: /* Signatura, autenticitat i reputació dels nostres emails */</p>
<hr />
<div>Correu electrònic o e-mail.<br />
<br />
== Introducció ==<br />
Segons la Wikipèdia: ''"El correu electrònic o a vegades, correu-e (anomenat en anglès e-mail, o email) es refereix al sistema que permet redactar, enviar i rebre missatges o cartes (missives, lletres) utilitzant sistemes de comunicació electrònica. També s'hi poden adjuntar documents electrònics o altres fitxers."''<br />
<br />
Enllaç a "E-mail" o "Correu electrònic": http://ca.wikipedia.org/wiki/Correu_electr%C3%B2nic<br />
<br />
<br />
== Servidors de correu electrònic ==<br />
<br />
[[Fitxer:Teoria.email1.png|700px]]<br />
<br />
Diferents parts del servidor de correu:<br />
* '''MTA''': [http://en.wikipedia.org/wiki/Message_transfer_agent Message Transfer Agent] o també "Mail Transfer Agent" (valen els dos). El propi programa de SERVIDOR correu:<br />
** GNU/Linux:<br />
*** [[Sendmail]]<br />
*** [[Postfix]]<br />
*** [[Exim]]<br />
** Windows:<br />
*** [[Microsoft Exchange]]<br />
* '''MUA:''' [http://en.wikipedia.org/wiki/Mail_user_agent Mail User Agent]. El programa que utilitza el client.<br />
** GNU/Linux: Thunderbird, Evolution<br />
** Windows: Thunderbird, Outlook<br />
* '''MDA: Mail Delivery Agent'''. Programa intermig per filtrar SPAM, seleccionar usuari, etc.<br />
* '''Mailbox''': Arxius de disc on es guarden els missatges i ''attachments''.<br />
* '''Fetchmail''': programa que actua d'interfície amb el client (MUA) mitjançant els protocols POP i IMAP (entre d'altres).<br />
<br />
<br><br />
<br />
== Protocols implicats ==<br />
* '''SMTP: Simple Mail Transfer Protocol'''. Utilitza diversos ports:<br />
** Port 25: enviament de correus entre servidors.<br />
** Port 587 (submission) o 465 (no-standard): port per a enviament de correus per part de clients.<br />
* '''POP3: Post Office Protocol'''. (Port 110)<br />
* '''IMAP: Internet Message Access Protocol'''. (Port 143)<br />
* '''IMAPS''': IMAP over SSL (Port 993)<br />
* '''POP3S''': POP3 over SSL (port 995)<br />
<br />
<br><br />
<br />
== Seguretat ==<br />
La seguretat en els emails depèn de diversos factors a solucionar:<br />
* '''Autenticació''': l'usuari que vol accedir<br />
* '''[[Encriptació]]''': mitjançant la [[encriptació]] assegurem que la conversa serà confidencial, és a dir, que si algun intrús la escolta no podrà llegir-la (no podrà desencriptar-la).<br />
** SSL: Secure-Sockets Layer o "capa de sockets segurs". Per poder implementar-la cal un port a part que disposi d'aquesta capa de seguretat de bon principi.<br />
** STARTTLS: També conegut per "[https://en.wikipedia.org/wiki/Opportunistic_TLS TLS oportunístic]". Ens permet canviar a una versió segura "sobre la marxa" dins d'un protocol no segur inicialment. D'aquesta manera es pot reutilitzar el port original afegint-li algun ''middleware'' que encripti i desencripti.<br />
* '''Certificats''': amb els certificats, una empresa externa confiable (Verisign, etc.) dóna fe que qui estem contactant és qui diu ser. Per tant, en aquest procés no només intervindrà la nostra configuració, sinó que el client consultarà a la CA (Certification Authority) si el nostre site és de confiança.<br />
<br />
<br><br />
<br />
== Webmail ==<br />
En el cas del webmail al client nomé li cal un navegador o ''browser''. El servidor web es connecta amb el servidor d'email mitjançant els protocols estàndards (o d'altres) i serveix al client en forma de HTML (mitjançant el protocol HTTP o HTTPS).<br />
<br />
[[Fitxer:webmail.png|700px]]<br />
<br />
<br />
== Requisits per tenir un servidor d'email ==<br />
Diverses forces adverses es conjuren per no deixar-nos tenir un servidor d'email. És degut a les mesures de seguretat que posen tots els servidors als ''spammers''.<br />
<br />
Per poder tenir un servidor d'email funcionant heu d'assegurar-vos que:<br />
* Teniu una '''IP fixa''', és a dir, no val la típica IP dinàmica del ADSL. Això ens ho subministra el nostre ISP (vomistar, polafone, etc.) i cal pagar una quota mensual per tenir-la (abans era més raonable, ara resulta molt cara, entorn els 15€+IVA).<br />
* No hi ha un ''proxy'' que us tanqui el port 25 de sortida. A casa no sol passar, però als instituts i a moltes institucions ho fan per evitar spammers i així evitar que posin la IP del centre a llistes negres (recordem que tots sortim amb la mateixa IP pel NAT).<br />
** El efecte colateral del proxy que tenca el port 25 és que NO podem utilitzar cap client de correu sortint com el Thunderbird o Outlook (tot i que el correu entrant sí que funciona perquè va pels ports del POP i IMAP).<br />
* La nostra '''IP no està en una llista negra'''. Per comprovar-ho podeu anar aquí:<pre>https://www.spamhaus.org/lookup/</pre><br />
** En cas que la tingueu en una ''blacklist'' seguiu les instruccions de la web per (a) treure-la de la llista i (b) evitar que us la tornin a posar (típicament passa quan hi ha màquines dintre de la organització que envien ''spam'' per algun virus).<br />
* Si esteu fent servir [https://aws.amazon.com/premiumsupport/knowledge-center/ec2-port-25-throttle/ Amazon AWS, caldrà que desactiveu la restricció del port 25 de sortida d'emails].<br />
<br />
<br><br />
<br />
== Seguretat en servei de correu electrònic ==<br />
La seguretat del nostre servei gira entorn de 3 eixos principals:<br />
# '''Exploits''': si el nostre servei és "petable" (per un bug o alguna operació maliciosa que explota una debilitat) el nostre sistema es pot fer vulnerable a intrusions. Per combatre això convé:<br />
#* Estar a la darrera versió del sistema operatiu (al menys en el parxes de seguretat) i del servei que fem servir.<br />
#* Utilitzar docker per aïllar parts del sistema. Si el procés de correu és vulnerable, una possible intrusió només podrà accedir als arxius de correu, i no a altres serveis.<br />
# '''Virus''': l'email és una gran porta d'entrada al sistema. Poden entrar virus i usuaris incautes poden introduir-los involuntàriament en el sistema. Calen diverses eines:<br />
#* Antivirus servidor: Clam / Amavis (incloses al docker-mailserver)<br />
#* Antivirus PC client: Avast, Panda, .<br />
# '''SPAM''': el maldecap més gran per a la implantació d'un servidor de correu. Ens calen 2 tipus d'eines:<br />
#* SpamAssassin : ens permet filtrar els ''spam'' a la nostra ''inbox'' (inclòs al docker-mailserver). Sol aprendre sol en base a algorismes heurístics, però té algunes comandes per "ensenyar-lo" i apuntar-li quins son els autèntics SPAM. Tenir [https://es.wikipedia.org/wiki/Honeypot un '''''honeypot''''' sol ser interessant] pel bon funcionament del server.<br />
#* Sistemes de signatura per validació i reputació del nostre servidor de correu<br />
<br />
=== Signatura, autenticitat i reputació dels nostres emails ===<br />
El SPAM (correu no sol·licitat o ''correu brossa'') és una de les grans dificultats per desplegar un servidor d'email. Al ser un sistema obert, on tothom pot enviar a qualsevol adreça, el perill de tenir la inbox inundada i fer el servei inutilitzable obliga a algun tipus de protecció per tal que el sistema sigui usable pels usuaris finals.<br />
<br />
Els grans proveidors de comptes de correu (Google, Hotmail, Yahoo) van idear certes mesures per assegurar l'origen dels emails, i impedir que qualsevol pugues enviar un email amb qualsevol remitent (cosa que d'entrada era i segueix sent possible). D'aquests sistemes, en destaquem aquests 3:<br />
* [https://es.wikipedia.org/wiki/Sender_Policy_Framework SPF]: similar a DKIM, inclourem certa informació als registres TXT del DNS, però en aquest cas per associar unes IPs concretes des de les que serà vàlid enviar els correus del nostre domini.<br />
* [https://es.wikipedia.org/wiki/DomainKeys_Identified_Mail DKIM]: bàsicament consisteix en signar tots els emails amb una clau privada, i presentar la clau pública al servidor DNS.<br />
* [https://dmarc.org DMARC]: si anunciem al nostre domini les polítiques DMARC adequades estarem indicant als receptors dels nostres possibles emails que tenim implementades les mesures SPF i DKIM i s'explica què fer en cas de que no es superin aquests checks.<br />
<br />
Aquests mecanismes permeten als sistemes destinataris identificar si el correu que li arriba és bo. Si no quadra, la probabilitat de que sigui SPAM és molt alta i el filtra cap a la spam box.<br />
<br />
=== Comprovant la nostra reputació ===<br />
Utilitza aquesta eina per saber si has configurat correctament els diferents sistemes de signatura i validació d'autenticitat dels nostres emails.<br />
<br />
https://www.mail-tester.com/<br />
<br />
<br></div>Enrichttps://cacauet.org/wiki/index.php?title=Conceptes_generals_de_programaci%C3%B3&diff=4250Conceptes generals de programació2022-01-24T09:16:38Z<p>Enric: /* Accelerant les VMs: JIT i d'altres */</p>
<hr />
<div>...intro...<br />
<br />
== Codi font i executable ==<br />
Tipus de codi:<br />
* [http://en.wikipedia.org/wiki/Source_code Codi font]: conjunt d'arxius de text amb instruccions d'alt nivell, fàcilment llegible per humans, no executable per la computadora. L'objectiu és facilitar la tasca als programadors.<br />
* [http://en.wikipedia.org/wiki/Machine_code Codi màquina o executable]: conjunt d'instruccions directament executables per un microprocessador o CPU. Alta complexitat. Instruccions molt específiques que realitzen tasques de molt baix nivell.<br />
<br />
Característiques:<br />
* El procés per generar codi executable a partir del codi font és la compilació.<br />
* No és possible (o seria altíssimament complex) deduïr un codi font a partir d'un executable. D'aquí la importància del "codi lliure".<br />
* Una sola instrucció de codi font pot produïr centenars o milers d'instruccions màquina.<br />
* Una compilació és específica per una màquina i arquitectura. Els executables no són portables (tot i que sí es podrien executar amb un emulador).<br />
<br><br />
<br />
== Llenguatges compilats vs. interpretats ==<br />
<br />
Distingirem entre:<br />
* [http://es.wikipedia.org/wiki/Lenguaje_compilado Llenguatges compilats]. Utilitzen un compilador.<br />
* [http://es.wikipedia.org/wiki/Lenguaje_de_programaci%C3%B3n_interpretado Llenguatges interpretats]. Utilitzen un intèrpret.<br />
<br />
Llegiu els articles de la Wikipèdia al respecte.<br />
<br />
Algunes notes addicionals:<br />
* El llenguatge compilat revisa la correcció del tot el codi abans de generar l'executable.<br />
* El llenguatge interpretat agafa una instrucció a cada moment i no comprova la totalitat, només el què està a punt d'executar.<br />
* El compilador només tradueix un sol cop a codi màquina. A partir d'aquí l'execució del codi màquina (executable) és directa.<br />
* Un intèrpret ha de traduïr de cou el programa cada cop que s'executa.<br />
* Els llenguatges interpretats solen ser típicament 10 cops més lents que els executables.<br />
* Els llenguatges compilats permeten la ocultació del codi font. Els interpretats no.<br />
<br />
<br />
Avantatges de cadascun:<br />
* Compilats = rendiment: uns 10 cops més ràpids.<br />
* Interpretats = portabilitat: el mateix codi pot funcionar el diverses plataformes amb diferent hardware.<br />
<br><br />
<br />
=== Compiladors i intèrprets ===<br />
De fet, no son tan diferents. Consten de les següents parts, quasi totes comunes menys la darrera part.<br />
* '''Preprocessador''': expandeixen macros, substitueixen constants, etc.<br />
* '''Anàlisi lèxica''': separen els ''tokens'' (elements del llenguatge).<br />
* '''Anàlisi sintàctica''': comprovació dels tipus<br />
* '''Anàlisi semàntica''': (semàntica = significat) es decideix què fa la instrucció.<br />
* '''Generació/execució''':<br />
** El compilador enllaça les llibreries (linker) i genera un arxiu executable.<br />
** L'intèrpret executa directament les instruccions.<br />
<br><br />
<br />
== Codi intermig i màquines virtuals ==<br />
[[Imatge:Jvm-arquitectura.png|dreta|380px]]<br />
Hi ha un seguit de llenguatges com Java que venen a ser híbrids. Java es compila (arxiu *.class) però no sobre l'arquitectura de la màquina en què treballem, sinó sobre l'arquitectura de la Java Virtual Machine:<br />
* [http://en.wikipedia.org/wiki/Java_%28programming_language%29 Java].<br />
* [http://en.wikipedia.org/wiki/Java_Virtual_Machine JVM: Java Virtual Machine]<br />
<br />
Així, el codi resultant no es pot executar directament sobre el nostre hardware, sinó que cal una màquina virtual que realitzi la traducció final. L'objectiu és aconseguir un codi multiplataforma, fent que aquest codi sigui exectuable en qualsevol plataforma que implementi la JVM (Java Virtual Machine).<br />
<br />
=== Accelerant les VMs: JIT i d'altres ===<br />
<br />
La JVM fa que l'execució sigui molt més lenta, però l'aparició de l'intèrpret del la JVM anomenat JIT (Just In Time) va accelerar molt el rendiment. El què fa el JIT és permetre la reutiltizació del codi executable sobre la plataforma, tenint rendiments propers als del codi natiu.<br />
<br />
Llegir més a [https://es.wikipedia.org/wiki/Compilaci%C3%B3n_en_tiempo_de_ejecuci%C3%B3n JIT a Wikipèdia].<br />
<br />
Python, té un altre model, no té una VM com el Java, sinó un intèrpret clàssic. Però també implementa un sistema per millorar el rendiment realitzant traduccions al C del codi Python, que es poden compilar sobre la plataforma. Això ho realitza automàticament (com el JIT) i és transparent al desenvolupador.<br />
<br />
És per aquest motiu que en determinats ''frameworks'' podeu trobar arxius *.pyc al cosat del vostre *.py<br />
<br />
<br><br />
<br />
== Tipatge estàtic i dinàmic ==<br />
Amb el tipatge ens referim a si les variables emprades en el llenguatge contenen un tipus de dades prefixat des de la seva definició (sencer, string, etc.) o si una mateixa variable pot contenir diferents tipus de dades segons com l'emprem.<br />
<br />
* Tipatge estàtic (Java, C/C++): la variable conté un tipus de dada fixat (pot canviar el valor, però no el tipus)<br />
* Tipatge dinàmic (PHP, Python): la mateixa variable pot contenir un tipus de dades diferents segons com l'emprem.<br />
<br />
=== Exemple en Java (tipus estàtic) ===<br />
Observa i posa en pràctica aquest exemple:<br />
<syntaxhighlight lang="java"><br />
class suma<br />
{ <br />
public static void main(String args[])<br />
{<br />
// Creem string del missatge<br />
String missatge = new String("Hola! el resultat de la suma és = ");<br />
int primer, segon, resultat;<br />
<br />
// Comprovem l'entrada de paràmetres<br />
if (args.length!=2) {<br />
System.out.println( "ERROR: has de passar 2 nombres" );<br />
return;<br />
}<br />
<br />
// Capturem els paràmetres entrats i calculem<br />
primer = Integer.parseInt( args[0] );<br />
segon = Integer.parseInt( args[1] );<br />
resultat = primer + segon; // aquí "+" és suma<br />
<br />
// mostrem per consola<br />
System.out.println( missatge + resultat ); // aquí "+" és concatenació (String)<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
#Crea el programa anterior en un fitxer '''suma.java'''<br />
#'''Compila'l''' amb:<pre>$ javac suma</pre><br />
#Apareixerà un arxiu '''suma.class''' . Executa'l amb: <pre>$ java suma</pre><br />
#:(et donarà un error perquè no has posat arguments)<br />
#Executa'l amb paràmetres: <pre>$ java suma 10 6</pre><br />
<br />
=== Exemple amb Python (tipus dinàmic) ===<br />
En aquest cas no cal indicar de quin tipus son les variables al definir-les.<br />
<br />
<syntaxhighlight lang="python"><br />
import sys<br />
<br />
# Definim la funcio main()<br />
def main():<br />
msg = "El resultat es = "<br />
<br />
if len(sys.argv)!=3:<br />
print("Has d'introduir 2 nombres")<br />
return False<br />
<br />
primer = int(sys.argv[1])<br />
segon = int(sys.argv[2])<br />
resultat = primer + segon<br />
<br />
print( msg + str(resultat) )<br />
<br />
if __name__=="__main__":<br />
main()<br />
</syntaxhighlight><br />
<br />
<br />
<br />
== Exercicis ==<br />
<div class="exercici"><br />
#Realitza els exemples anteriors però canviant els ''integers'' per ''floats''.<br />
<br />
</div></div>Enrichttps://cacauet.org/wiki/index.php?title=SQL_injection&diff=4249SQL injection2021-11-12T18:13:38Z<p>Enric: /* Protecció */</p>
<hr />
<div>SQL injection és una forma d'atac cibernètic per manipular la base de dades remota a través dels formularis.<br />
<br />
#FpInfor #Daw #DawMp07 #DawMp07Uf3 #DawMp07Uf03 #Ceti #Ciber #CetiMp03 #CiberMp03<br />
<br />
== Introducció ==<br />
Una bona manera d'introduir-se a aquest tema és amb aquest acudit:<br />
<br />
http://stackoverflow.com/questions/332365/how-does-the-sql-injection-from-the-bobby-tables-xkcd-comic-work?rq=1<br />
<br />
Fes-li un cop d'ull a aquests articles també per veure solucions:<br />
<br />
http://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php?rq=1<br />
https://diego.com.es/tutorial-de-pdo<br />
<br />
<br><br />
<br />
== Coneixements previs ==<br />
Cal que coneixem el llenguatge de programació PHP i el llenguatge de manipulació de dades SQL.<br />
* [[Curs de PHP]]<br />
* [[Curs de SQL]]<br />
* Partirem d'aquests exemples:<br />
** Utilitzant [https://uf.ctrl-alt-d.net/material/mostra/50/php-acces-a-dades-amb-pdo PDO]<br />
** Utilitzant mysqli [[PHP MySQL select]]<br />
<br />
<br><br />
<br />
== Un petit exemple amb LOGIN ==<br />
Qualsevol formulari on l'usuari pugui entrar text lliure pot ser un punt vulnerable. Per exemple, el formulari de ''login'' típic per entrar al sistema.<br />
<br />
En aquest exemple tenim la taula d'usuaris típica:<br />
mysql> desc users;<br />
+----------+--------------+------+-----+---------+----------------+<br />
| Field | Type | Null | Key | Default | Extra |<br />
+----------+--------------+------+-----+---------+----------------+<br />
| id | int(11) | NO | PRI | NULL | auto_increment |<br />
| username | varchar(200) | YES | | NULL | |<br />
| name | varchar(200) | YES | | NULL | |<br />
| password | varchar(600) | YES | | NULL | |<br />
+----------+--------------+------+-----+---------+----------------+<br />
4 rows in set (0,01 sec)<br />
<br />
En aquest cas, tenim diversos usuaris: enric, crypto, pepa i manolo. La password està encriptada amb SHA2-512<br />
<br />
El més habitual és entrar el teu nom d'usuari i la password, i llavors entraríem amb l'usuari.<br />
<br />
Fixeu-vos en què la sentència SQL que apareix abans del formulari no hi hauria de ser, la hem posat per il·lustrar quin serà la manera de perpetrar la injecció.<br />
<br />
[[Fitxer:Sqlinjection1.png|600px]]<br />
<br />
----<br />
<br />
La sentència que hem executat utilitza el ''username'' i ''password'' que l'usuari ha subministrat.<br />
<br />
Però si enlloc de posar el nom d'usuari posem una sentència SQL hàbil i preclara, podem manipular la ''query'' que finalment enviarem a la base de dades. En el següent exemple, '''enlloc del nom d'usuari entrarem''':<br />
<br />
enric' or 1=1; -- lala'<br />
<br />
...que es transformarà en el següent:<br />
<br />
SELECT * FROM users WHERE username='enric' or 1=1; -- lala' AND password=SHA2('asd',512);<br />
<br />
El què hi ha després de la "--" es transforma en un comentari, pel que s'ignora. I al haver posat "OR 1=1", ens donarà TRUE per a tots els registres.<br />
<br />
I el resultat serà aquest:<br />
<br />
[[Fitxer:Sqlinjection3.png|600px]]<br />
<br />
...que com podreu imaginar, és una possible manera de liar el codi i efectuar un "fals positiu" i entrar amb el nom d'usuari que vulguem (o que puguem, que en segons quina situació pot ser suficient per entrar en algun lloc amb privilegis).<br />
<br />
<br><br />
<br />
== Llibreries ==<br />
Hi ha 2 llibreries per accedir MySQL des de PHP. Ambdúes se suposa que NO permeten fer 2 queries seguides (per seguretat).<br />
* [https://uf.ctrl-alt-d.net/material/mostra/50/php-acces-a-dades-amb-pdo PDO]<br />
* [http://php.net/manual/es/book.mysql.php mysql original] (obsoleta)<br />
* [http://php.net/manual/es/book.mysqli.php mysqli : mysql millorada]<br />
<br />
Si es permetés això (en anteriors versions sí que passava), què creus que passaria si introdueixo això com a nom d'usuari?<br />
enric' or 1=1; drop table usuaris; -- lala<br />
<br />
<br />
<br />
== Protecció ==<br />
<br />
En aquest exemple amb PDO es pot veure [https://www.php.net/manual/es/pdostatement.bindparam.php#refsect1-pdostatement.bindparam-examples com protegir la query PDO] perquè no sigui vulnerable a SQL injection.<br />
<br />
Es tracta d'utilitzar les sentències '''prepare''' i '''bindParam''' abans de l'execute.</div>Enrichttps://cacauet.org/wiki/index.php?title=SQL_injection&diff=4248SQL injection2021-11-12T18:13:18Z<p>Enric: /* Llibreries */</p>
<hr />
<div>SQL injection és una forma d'atac cibernètic per manipular la base de dades remota a través dels formularis.<br />
<br />
#FpInfor #Daw #DawMp07 #DawMp07Uf3 #DawMp07Uf03 #Ceti #Ciber #CetiMp03 #CiberMp03<br />
<br />
== Introducció ==<br />
Una bona manera d'introduir-se a aquest tema és amb aquest acudit:<br />
<br />
http://stackoverflow.com/questions/332365/how-does-the-sql-injection-from-the-bobby-tables-xkcd-comic-work?rq=1<br />
<br />
Fes-li un cop d'ull a aquests articles també per veure solucions:<br />
<br />
http://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php?rq=1<br />
https://diego.com.es/tutorial-de-pdo<br />
<br />
<br><br />
<br />
== Coneixements previs ==<br />
Cal que coneixem el llenguatge de programació PHP i el llenguatge de manipulació de dades SQL.<br />
* [[Curs de PHP]]<br />
* [[Curs de SQL]]<br />
* Partirem d'aquests exemples:<br />
** Utilitzant [https://uf.ctrl-alt-d.net/material/mostra/50/php-acces-a-dades-amb-pdo PDO]<br />
** Utilitzant mysqli [[PHP MySQL select]]<br />
<br />
<br><br />
<br />
== Un petit exemple amb LOGIN ==<br />
Qualsevol formulari on l'usuari pugui entrar text lliure pot ser un punt vulnerable. Per exemple, el formulari de ''login'' típic per entrar al sistema.<br />
<br />
En aquest exemple tenim la taula d'usuaris típica:<br />
mysql> desc users;<br />
+----------+--------------+------+-----+---------+----------------+<br />
| Field | Type | Null | Key | Default | Extra |<br />
+----------+--------------+------+-----+---------+----------------+<br />
| id | int(11) | NO | PRI | NULL | auto_increment |<br />
| username | varchar(200) | YES | | NULL | |<br />
| name | varchar(200) | YES | | NULL | |<br />
| password | varchar(600) | YES | | NULL | |<br />
+----------+--------------+------+-----+---------+----------------+<br />
4 rows in set (0,01 sec)<br />
<br />
En aquest cas, tenim diversos usuaris: enric, crypto, pepa i manolo. La password està encriptada amb SHA2-512<br />
<br />
El més habitual és entrar el teu nom d'usuari i la password, i llavors entraríem amb l'usuari.<br />
<br />
Fixeu-vos en què la sentència SQL que apareix abans del formulari no hi hauria de ser, la hem posat per il·lustrar quin serà la manera de perpetrar la injecció.<br />
<br />
[[Fitxer:Sqlinjection1.png|600px]]<br />
<br />
----<br />
<br />
La sentència que hem executat utilitza el ''username'' i ''password'' que l'usuari ha subministrat.<br />
<br />
Però si enlloc de posar el nom d'usuari posem una sentència SQL hàbil i preclara, podem manipular la ''query'' que finalment enviarem a la base de dades. En el següent exemple, '''enlloc del nom d'usuari entrarem''':<br />
<br />
enric' or 1=1; -- lala'<br />
<br />
...que es transformarà en el següent:<br />
<br />
SELECT * FROM users WHERE username='enric' or 1=1; -- lala' AND password=SHA2('asd',512);<br />
<br />
El què hi ha després de la "--" es transforma en un comentari, pel que s'ignora. I al haver posat "OR 1=1", ens donarà TRUE per a tots els registres.<br />
<br />
I el resultat serà aquest:<br />
<br />
[[Fitxer:Sqlinjection3.png|600px]]<br />
<br />
...que com podreu imaginar, és una possible manera de liar el codi i efectuar un "fals positiu" i entrar amb el nom d'usuari que vulguem (o que puguem, que en segons quina situació pot ser suficient per entrar en algun lloc amb privilegis).<br />
<br />
<br><br />
<br />
== Llibreries ==<br />
Hi ha 2 llibreries per accedir MySQL des de PHP. Ambdúes se suposa que NO permeten fer 2 queries seguides (per seguretat).<br />
* [https://uf.ctrl-alt-d.net/material/mostra/50/php-acces-a-dades-amb-pdo PDO]<br />
* [http://php.net/manual/es/book.mysql.php mysql original] (obsoleta)<br />
* [http://php.net/manual/es/book.mysqli.php mysqli : mysql millorada]<br />
<br />
Si es permetés això (en anteriors versions sí que passava), què creus que passaria si introdueixo això com a nom d'usuari?<br />
enric' or 1=1; drop table usuaris; -- lala<br />
<br />
<br />
<br />
== Protecció ==<br />
<br />
En aquest exemple amb PDO es pot veure [[https://www.php.net/manual/es/pdostatement.bindparam.php#refsect1-pdostatement.bindparam-examples com protegir la query PDO]] perquè no sigui vulnerable a SQL injection.<br />
<br />
Es tracta d'utilitzar les sentències '''prepare''' i '''bindParam''' abans de l'execute.</div>Enrichttps://cacauet.org/wiki/index.php?title=PHP_MySQL_select&diff=4247PHP MySQL select2021-11-11T18:35:42Z<p>Enric: tags #fipinfor</p>
<hr />
<div>Utilitzarem les [http://es2.php.net/manual/en/book.mysql.php funcions PHP] per accedir al SGBD MySQL. Consulteu-les [http://es2.php.net/manual/en/book.mysql.php aquí].<br />
<br />
#FpInfor #Daw #DawMp07 #DawMp07Uf3 #DawMp07Uf03<br />
<br />
A grans trets, el procés general per atacar un SGBD és aquest:<br />
#Connexió a la BBDD<br />
#Crear i enviar query<br />
#Obtenir resultats i mostrar-los per pantalla<br />
<br />
<br />
En aquest darrer pas (obtenir i mostrar resultats) cal fixar-se especialment en l' '''estructura de control''' que necessitarem:<br />
*'''Bucle de registres''': (''while'') iterarà per cadascuna de les files de la taula. Haurà de ser un bucle tipus '''''while''''' ja que no sabem quan arribarem a la darrera fila.<br />
<br />
<br />
== Procés detallat per extreure dades de MySQL ==<br />
<br />
Per obtenir dades d'una taula MySQL i visualitzar-la utilitzant PHP seguirem les següents passes:<br />
#Connexió<br />
##'''Connectar''' a MySQL amb l'ordre '''''mysql_connect()'''''<br />
##'''Triar la BBDD''' de treball amb '''''mysql_select_db()'''''<br />
#Crear i enviar consulta (query):<br />
##'''Crear la consulta''' i desar-la en una variable, típicament '''''$query = "SELECT ... FROM ... WHERE ..."'''''<br />
##'''Enviar la consulta''' al sistema (SGBD) per obtenir el resultat amb '''''[http://es2.php.net/manual/es/function.mysql-query.php mysql_query()]'''''<br />
##Si no hi ha resultat (0 files o bé hi ha algun error a la sintaxi) posem un missatge d'error i acabem l'execució de la pàgina web amb '''''die($missatge)'''''<br />
#Obtenir resultats i mostrar-los:<br />
##Obrim taula HTML amb <nowiki><table></nowiki> i la capçalera amb <nowiki><thead></nowiki><br />
##'''Bucle while''' pels registres de la taula: com que poden haver-ne varis, farem un bucle (''loop''). Típicament s'utiltiza un '''''while''''' perquè no sabem quan arribarem a la darrera fila<br />
##:(Dins del while) Extreure les dades d'un registre (fila de la BBDD) i emmagatzemar-les en un ''array'' amb alguna d'aquestes funcions:<br />
##*''[http://es2.php.net/manual/es/function.mysql-fetch-row.php mysql_fetch_row()]'': extreu els camps de la fila en un array numèric clàssic.<br />
##*:Per exemple: echo $registre[0]<br />
##*''[http://es2.php.net/manual/es/function.mysql-fetch-assoc.php mysql_fetch_assoc()]'': extreu els camps de la fila en un array associatiu.<br />
##*:Per exemple: echo $registre["titol_original"]<br />
##*''[http://es2.php.net/manual/es/function.mysql-fetch-object.php mysql_fetch_object()]'': extreu els camps en un objecte.<br />
##*:Per exemple: echo $registre->titol_original;<br />
##Obrim la fila de la taula HTML amb <nowiki><tr></nowiki><br />
##Mostrem dades dins de cel·les d'una taula HTML. Haurem de concatenar diverses cadenes de caràcters:<br />
##*Obrir la cel·la de la taula utiltizant <nowiki><td></nowiki><br />
##*Imprimir resultat amb les dades de l'array. Per exemple, $registre["titol_original"]<br />
##*Tancar la cel·la de la taula utiltizant <nowiki></td></nowiki><br />
##Tanquem la fila de la taula HTML amb <nowiki></tr></nowiki><br />
##Tanquem la taula amb <nowiki></table></nowiki><br />
<br />
<br />
== Codi font de l'exemple ==<br />
Per crear i importar la base de dades d'exemple pots consultar [[SQL creacio]]. Utilitzarem la BBDD d'exemple "World" que hi ha a la pàgina oficial de MySQL. La podeu descarregar d'aquí:<br />
https://dev.mysql.com/doc/index-other.html<br />
<br />
Examineu a fons i proveu aquest codi:<br />
<br />
<syntaxhighlight lang="php"><br />
<html><br />
<head><br />
<title>Exemple de lectura de dades a MySQL</title><br />
<style><br />
body{<br />
}<br />
table,td {<br />
border: 1px solid black;<br />
border-spacing: 0px;<br />
}<br />
</style><br />
</head><br />
<br />
<body><br />
<h1>Exemple de lectura de dades a MySQL</h1><br />
<br />
<?php<br />
# (1.1) Connectem a MySQL (host,usuari,contrassenya)<br />
$conn = mysqli_connect('localhost','enric','enric123');<br />
<br />
# (1.2) Triem la base de dades amb la que treballarem<br />
mysqli_select_db($conn, 'world');<br />
<br />
# (2.1) creem el string de la consulta (query)<br />
$consulta = "SELECT * FROM city;";<br />
<br />
# (2.2) enviem la query al SGBD per obtenir el resultat<br />
$resultat = mysqli_query($conn, $consulta);<br />
<br />
# (2.3) si no hi ha resultat (0 files o bé hi ha algun error a la sintaxi)<br />
# posem un missatge d'error i acabem (die) l'execució de la pàgina web<br />
if (!$resultat) {<br />
$message = 'Consulta invàlida: ' . mysqli_error($conn) . "\n";<br />
$message .= 'Consulta realitzada: ' . $consulta;<br />
die($message);<br />
}<br />
?><br />
<br />
<!-- (3.1) aquí va la taula HTML que omplirem amb dades de la BBDD --><br />
<table><br />
<!-- la capçalera de la taula l'hem de fer nosaltres --><br />
<thead><td colspan="4" align="center" bgcolor="cyan">Llistat de ciutats</td></thead><br />
<?php<br />
# (3.2) Bucle while<br />
while( $registre = mysqli_fetch_assoc($resultat) )<br />
{<br />
# els \t (tabulador) i els \n (salt de línia) son perquè el codi font quedi llegible<br />
<br />
# (3.3) obrim fila de la taula HTML amb <tr><br />
echo "\t<tr>\n";<br />
<br />
# (3.4) cadascuna de les columnes ha d'anar precedida d'un <td><br />
# després concatenar el contingut del camp del registre<br />
# i tancar amb un </td><br />
echo "\t\t<td>".$registre["Name"]."</td>\n";<br />
echo "\t\t<td>".$registre['CountryCode']."</td>\n";<br />
echo "\t\t<td>".$registre["District"]."</td>\n";<br />
echo "\t\t<td>".$registre['Population']."</td>\n";<br />
<br />
# (3.5) tanquem la fila<br />
echo "\t</tr>\n";<br />
}<br />
?><br />
<!-- (3.6) tanquem la taula --><br />
</table> <br />
</body><br />
</html><br />
</syntaxhighlight><br />
<br />
== Exercicis ==<br />
Posa en marxa aquest exemple en la teva màquina Linux. Hauràs de:<br />
* Instal·lar apache2 i php5<br />
* Comproveu que el servidor Apache funciona apuntant el ''browser'' a http://localhost<br />
* Rearrencar apache amb<br />
*: '''$ sudo apache2ctl restart'''<br />
* Importar la base de dades [[Fitxer:Videoclub.sql]] al vostre servidor MySQL. Si no sabeu com fer-ho, consulteu-ho a [[SQL_creacio]]<br />
* Si no us deixa haureu de donar permisos a la carpeta per poder escriure amb<br />
*: '''$ sudo chmod 777 /var/www'''<br />
*: ULL! Aquesta és una mesura molt poc segura. Només ho fem per anar ràpid. No ho feu mai en un servidor en producció. Si voleu poder escriure en un directori d'usuari es recomana activar el mòdul ''userdir'' de l'apache amb la comanda<br />
*: ''$> sudo a2enmod userdir''<br />
* Copiar i enganxar el codi PHP de l'exemple de més amunt a l'arxiu /var/www/ex1.php<br />
* Apunta el ''browser'' a la direcció: http://localhost/ex1.php<br />
<br />
Opcionalment pots esborrar l'arxiu /var/www/index.html . Així l'apache ens mostrarà els arxius continguts a la carpeta.<br />
<br />
<br />
=== Exercici de filtratge amb WORLD ===<br />
<br />
Amplia l'exemple de les ciutats amb la BBDD World de forma que puguem filtrar les ciutats mostrades amb un menú desplegable (SELECT).<br />
<br />
Guia:<br />
# Pàgina 1: Comença per fer un llistat dels països utilitzant la taula COUNTRY.<br />
# La FK que lliga la taula CITY i la taula COUNTRY és el CountryCode. El formulari ''select'' (ja sigui desplegable o ''radio button'') ha de mostrar el nom del país, però ha d'enviar el CountryCode com a ''value'' a través de GET o POST a la pagina 2.<br />
# Pàgina 2: Agafa el país enviat per l'usuari (GET o POST) i fes una ''query'' que filtri els resultats de la taula CITY i que només mostri les ciutats del país seleccionat.<br />
# Puja aquest projecte a Github i crea un README.md que expliqui com posar en marxa l'exercici perquè funcioni correctament.<br />
# Indica també el nom del país de la ciutat. No ens val el CountryCode, volem el nom del país literal (per exemple, no ens val "FRA" sinó que haria de sortir "France"). Per a fer això caldrà que facis un JOIN.<br />
# Afegeix les banderes dels països al formulari (caldrà cercar-les per internet).<br />
# Afegeix un formulari que permeti afegir noves ciutats. Els països s'han de poder entrar amb un desplegable.<br />
<br />
<br><br />
<br />
=== Exercicis de queries ===<br />
<br />
Realitza els següents exercicis amb la [[Fitxer:Ufs.sql|base de dades de UFs]]. Si no saps com crear-la pots consultar-ho a [[SQL_creacio]].<br />
*'''ex2.php''': mostra les assignatures de 2n de SMX. Cal, doncs, tenir instal·lada la base de dades.<br />
*'''ex3.php''': mostra les assignatures de la ESO.<br />
*'''ex4.php''': mostra el nom dels tots els alumnes.<br />
<br />
Exercicis amb el videoclub [[Fitxer:Videoclub.sql]]:<br />
*'''ex5.php''': mostra tots els lloguers ordenats descendentment per data de sortida.<br />
*'''ex6.php''': mostra els diferents gèneres disponibles ordenats alfabèticament.<br />
<br />
<br />
=== Exercicis amb JOIN ===<br />
IMPORTANT:<br />
*Tituleu adequadament cada pàgina perquè quedi clar quina consulta estem realitzant.<br />
*No val utilitzar IDs al WHERE (per això justament son amb JOIN). Heu de fer servir la paraula o dada tal i com apareix a l'enunciat de cada exercici.<br />
*A totes les consultes ha d'aparèixer, com a mínim, totes les dades que apareixen a l'enunciat.<br />
*:Per exemple, si demanem totes els alumnes matriculats a la ESO ha d'aparèixer no només al nom dels alumnes, sinó també la titulació (ESO).<br />
*Poseu encapçalament a les columnes.<br />
*MOLT IMPORTANT: tingueu en compte que quan es fa un select amb join, poden haver camps de diverses taules amb el mateix nom de columna. A l'utiltizar arrays associatius, la clau de l'array amb la que ens adreçem pot estar superposada i llavors només visualitzarem les dades del darrer camp que apareix en els SELECT. Per solucionar-ho, utilitzeu el AS per reanomenar la columna amb un altre nom que us convingui.<br />
*: Per exemple, al exercici "join1.php", si fem un "SELECT assignatures.*, professors.* FROM ..." tindrem un conflicte entre les columnes "nom" del professor i el "nom" de l'assignatura. Per poder accedir a les dues dades, cal que les expliciteu totes dues (no valen, doncs, els *) i reanomenar-les a ''nom_profe'' i ''nom_assignautra'' amb un "AS".<br />
<br />
<br />
Exercicis:<br />
#'''join1.php''': mostra les assignatures que imparteix el professor Enric Mieza.<br />
#:Resultat: hauria de sortir-vos només l'assignatura de Muntatge i la de Bases de Dades.<br />
#'''join2.php''': llistat de les UFs de l'assignatura "Sistemes Operatius Monolloc".<br />
#'''join3.php''': llistat d'assignatures amb la seva titulació.<br />
#'''join4.php''': nombre de matrícules del curs 2009-2010<br />
#'''join5.php''': recompte de matrícules per curs.<br />
#'''join6.php''': recompte de UFs per assignatura.<br />
#'''join7.php''': llistat de les UFs de les assignatures de SMX, ordenades per número del mòdul (assignatura).<br />
#'''join8.php''': llistat de les assignatures en què està matriculat en Pere Escribano.<br />
#'''join9.php''': llistat de qualificacions (assigntura i UF) de l'alumne Òscar Tabuada.<br />
#'''join10.php''': llistat de qualificacions aprovades dels alumnes del curs 2009-2010.<br />
#'''join11.php''': mitjana de les qualificacions de l'alumne David Dalmau. <br />
#'''join12.php''': llistat d'alumnes aprovats de les UFs de l'assignatura "Sistemes Operatius Monolloc".</div>Enrichttps://cacauet.org/wiki/index.php?title=SQL_injection&diff=4246SQL injection2021-11-11T18:34:41Z<p>Enric: </p>
<hr />
<div>SQL injection és una forma d'atac cibernètic per manipular la base de dades remota a través dels formularis.<br />
<br />
#FpInfor #Daw #DawMp07 #DawMp07Uf3 #DawMp07Uf03 #Ceti #Ciber #CetiMp03 #CiberMp03<br />
<br />
== Introducció ==<br />
Una bona manera d'introduir-se a aquest tema és amb aquest acudit:<br />
<br />
http://stackoverflow.com/questions/332365/how-does-the-sql-injection-from-the-bobby-tables-xkcd-comic-work?rq=1<br />
<br />
Fes-li un cop d'ull a aquests articles també per veure solucions:<br />
<br />
http://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php?rq=1<br />
https://diego.com.es/tutorial-de-pdo<br />
<br />
<br><br />
<br />
== Coneixements previs ==<br />
Cal que coneixem el llenguatge de programació PHP i el llenguatge de manipulació de dades SQL.<br />
* [[Curs de PHP]]<br />
* [[Curs de SQL]]<br />
* Partirem d'aquests exemples:<br />
** Utilitzant [https://uf.ctrl-alt-d.net/material/mostra/50/php-acces-a-dades-amb-pdo PDO]<br />
** Utilitzant mysqli [[PHP MySQL select]]<br />
<br />
<br><br />
<br />
== Un petit exemple amb LOGIN ==<br />
Qualsevol formulari on l'usuari pugui entrar text lliure pot ser un punt vulnerable. Per exemple, el formulari de ''login'' típic per entrar al sistema.<br />
<br />
En aquest exemple tenim la taula d'usuaris típica:<br />
mysql> desc users;<br />
+----------+--------------+------+-----+---------+----------------+<br />
| Field | Type | Null | Key | Default | Extra |<br />
+----------+--------------+------+-----+---------+----------------+<br />
| id | int(11) | NO | PRI | NULL | auto_increment |<br />
| username | varchar(200) | YES | | NULL | |<br />
| name | varchar(200) | YES | | NULL | |<br />
| password | varchar(600) | YES | | NULL | |<br />
+----------+--------------+------+-----+---------+----------------+<br />
4 rows in set (0,01 sec)<br />
<br />
En aquest cas, tenim diversos usuaris: enric, crypto, pepa i manolo. La password està encriptada amb SHA2-512<br />
<br />
El més habitual és entrar el teu nom d'usuari i la password, i llavors entraríem amb l'usuari.<br />
<br />
Fixeu-vos en què la sentència SQL que apareix abans del formulari no hi hauria de ser, la hem posat per il·lustrar quin serà la manera de perpetrar la injecció.<br />
<br />
[[Fitxer:Sqlinjection1.png|600px]]<br />
<br />
----<br />
<br />
La sentència que hem executat utilitza el ''username'' i ''password'' que l'usuari ha subministrat.<br />
<br />
Però si enlloc de posar el nom d'usuari posem una sentència SQL hàbil i preclara, podem manipular la ''query'' que finalment enviarem a la base de dades. En el següent exemple, '''enlloc del nom d'usuari entrarem''':<br />
<br />
enric' or 1=1; -- lala'<br />
<br />
...que es transformarà en el següent:<br />
<br />
SELECT * FROM users WHERE username='enric' or 1=1; -- lala' AND password=SHA2('asd',512);<br />
<br />
El què hi ha després de la "--" es transforma en un comentari, pel que s'ignora. I al haver posat "OR 1=1", ens donarà TRUE per a tots els registres.<br />
<br />
I el resultat serà aquest:<br />
<br />
[[Fitxer:Sqlinjection3.png|600px]]<br />
<br />
...que com podreu imaginar, és una possible manera de liar el codi i efectuar un "fals positiu" i entrar amb el nom d'usuari que vulguem (o que puguem, que en segons quina situació pot ser suficient per entrar en algun lloc amb privilegis).<br />
<br />
<br><br />
<br />
== Llibreries ==<br />
Hi ha 2 llibreries per accedir MySQL des de PHP. Ambdúes se suposa que NO permeten fer 2 queries seguides (per seguretat).<br />
* [https://uf.ctrl-alt-d.net/material/mostra/50/php-acces-a-dades-amb-pdo PDO]<br />
* [http://php.net/manual/es/book.mysql.php mysql original] (obsoleta)<br />
* [http://php.net/manual/es/book.mysqli.php mysqli : mysql millorada]<br />
<br />
Si es permetés això (en anteriors versions sí que passava), què creus que passaria si introdueixo això com a nom d'usuari?<br />
enric' or 1=1; drop table usuaris; -- lala</div>Enrichttps://cacauet.org/wiki/index.php?title=SQL_injection&diff=4245SQL injection2021-11-11T18:33:59Z<p>Enric: </p>
<hr />
<div>SQL injection és una forma d'atac cibernètic per manipular la base de dades remota a través dels formularis.<br />
<br />
#FpInfor #Daw #DawMp07 #DawMp07Uf3 #DawMp07Uf03 #Ceti #Ciber #CetiMp03 #CiberMp03<br />
<br />
== Introducció ==<br />
Una bona manera d'introduir-se a aquest tema és amb aquest acudit:<br />
<br />
http://stackoverflow.com/questions/332365/how-does-the-sql-injection-from-the-bobby-tables-xkcd-comic-work?rq=1<br />
<br />
Fes-li un cop d'ull a aquests articles també per veure solucions:<br />
<br />
http://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php?rq=1<br />
https://diego.com.es/tutorial-de-pdo<br />
<br />
<br><br />
<br />
== Coneixements previs ==<br />
Cal que coneixem el llenguatge de programació PHP i el llenguatge de manipulació de dades SQL.<br />
* [[Curs de PHP]]<br />
* [[Curs de SQL]]<br />
* Partirem d'aquests exemples:<br />
** Utilitzant [https://uf.ctrl-alt-d.net/material/mostra/50/php-acces-a-dades-amb-pdo PDO]<br />
** Utilitzant mysqli [[PHP MySQL select]]<br />
<br />
<br><br />
<br />
== Un petit exemple amb LOGIN ==<br />
Qualsevol formulari on l'usuari pugui entrar text lliure pot ser un punt vulnerable. Per exemple, el formulari de ''login'' típic per entrar al sistema.<br />
<br />
En aquest exemple tenim la taula d'usuaris típica:<br />
mysql> desc users;<br />
+----------+--------------+------+-----+---------+----------------+<br />
| Field | Type | Null | Key | Default | Extra |<br />
+----------+--------------+------+-----+---------+----------------+<br />
| id | int(11) | NO | PRI | NULL | auto_increment |<br />
| username | varchar(200) | YES | | NULL | |<br />
| name | varchar(200) | YES | | NULL | |<br />
| password | varchar(600) | YES | | NULL | |<br />
+----------+--------------+------+-----+---------+----------------+<br />
4 rows in set (0,01 sec)<br />
<br />
En aquest cas, tenim diversos usuaris: enric, crypto, pepa i manolo. La password està encriptada amb SHA2-512<br />
<br />
El més habitual és entrar el teu nom d'usuari i la password, i llavors entraríem amb l'usuari.<br />
<br />
Fixeu-vos en què la sentència SQL que apareix abans del formulari no hi hauria de ser, la hem posat per il·lustrar quin serà la manera de perpetrar la injecció.<br />
<br />
[[Fitxer:Sqlinjection1.png|600px]]<br />
<br />
----<br />
<br />
La sentència que hem executat utilitza el ''username'' i ''password'' que l'usuari ha subministrat.<br />
<br />
Però si enlloc de posar el nom d'usuari posem una sentència SQL hàbil i preclara, podem manipular la ''query'' que finalment enviarem a la base de dades. En el següent exemple, '''enlloc del nom d'usuari entrarem''':<br />
<br />
enric' or 1=1; -- lala'<br />
<br />
...que es transformarà en el següent:<br />
<br />
SELECT * FROM users WHERE username='enric' or 1=1; -- lala' AND password=SHA2('asd',512);<br />
<br />
El què hi ha després de la "--" es transforma en un comentari, pel que s'ignora. I al haver posat "OR 1=1", ens donarà TRUE per a tots els registres.<br />
<br />
I el resultat serà aquest:<br />
<br />
[[Fitxer:Sqlinjection3.png|600px]]<br />
<br />
...que com podreu imaginar, és una possible manera de liar el codi i efectuar un "fals positiu" i entrar amb el nom d'usuari que vulguem (o que puguem, que en segons quina situació pot ser suficient per entrar en algun lloc amb privilegis).<br />
<br />
<br><br />
<br />
== Llibreries ==<br />
Hi ha 2 llibreries per accedir MySQL des de PHP. Ambdúes se suposa que NO permeten fer 2 queries seguides (per seguretat).<br />
* [https://uf.ctrl-alt-d.net/material/mostra/50/php-acces-a-dades-amb-pdo PDO]<br />
* [http://php.net/manual/es/book.mysql.php mysql original] (obsoleta)<br />
* [http://php.net/manual/es/book.mysqli.php mysqli : mysql millorada]<br />
<br />
Si es permetés això (en anteriors versions sí que passava), què creus que passaria si introdueixo això com a nom d'usuari?<br />
enric' or 1=1; drop table usuaris; -- lala</div>Enrichttps://cacauet.org/wiki/index.php?title=Git:_comandes&diff=4244Git: comandes2021-09-29T15:59:28Z<p>Enric: </p>
<hr />
<div><nowiki>#FpInfor #DawMp08 #DawMp08Uf04 #DawMp08Uf4</nowiki><br />
<br />
GIT és un sistema de control de versionat semblant a SVN (Subversion). Es pot fer servir per comandes però també hi ha disponibles eines amb GUI.<br />
<br />
Els nous apunts els teniu a: https://bytes.cat/git<br />
<br />
<br />
== Introducció ==<br />
* Conceptes previs: [[Control de versions]]<br />
* Llibre de referència (en espanyol) http://git-scm.com/book/es<br />
* Interfície gràfica per GIT:<br />
** http://www.rabbitvcs.org/<br />
** http://askubuntu.com/questions/4788/nautilus-git-integration<br />
* Una bona xuleta de totes les funcions de GIT: https://ndpsoftware.com/git-cheatsheet.html<br />
* Un model avançat de com utilitzar GIT: https://nvie.com/posts/a-successful-git-branching-model/<br />
<br />
Un dels principals atractius és el repositori públic https://github.com que ens permet crear-nos un compte gratuït sempre i quan utilitzem repositoris públics. Pels repositoris privats cal pagar.<br />
<br />
En qualsevol moment podem demanar ajuda sobre una comanda mitjançant:<br />
$ man git-<comanda><br />
Per exemple:<br />
$ man git-status<br />
<br />
== Exemple: clonar un projecte ==<br />
Pots provar de clonar un parell de projectes:<br />
* [https://github.com/emieza/pyges Pyges]: un CMS basat en Pyramid per Google App Engine (GAE).<br />
* [https://github.com/emieza/egipcis Egipcis]: senzill exemple d'autenticació amb Pyramid.<br />
<br />
Instal·la el git al teu PC:<br />
$ sudo apt-get install git<br />
<br />
Clona el projecte Faceschool:<br />
$ git clone https://github.com/lacetans/faceschool.git<br />
<br />
Se't descarregarà a la teva màquina. Activa el virtualenv i posa'l en marxa:<br />
$ source ~/env/bin/activate<br />
$ python manage.py runserver<br />
<br />
Prova-ho també amb el projecte "Egipcis" (és més senzill i triga menys a descarregar).<br />
https://github.com/emieza/egipcis.git<br />
<br />
== Crear un projecte nou ==<br />
# Crea el teu compte a http://github.com<br />
# Crea el nou repositori des de la web (és més fàcil).<br />
#* També ho pots fer amb comandes: https://help.github.com/articles/create-a-repo<br />
# Abans de fer un commit penseu a fer un [https://help.github.com/articles/set-up-git setup del GIT] a la vostra màquina (no és imprescindible però convenient més que res per deixar el nom d'usuari i email a cada commit que fem).<br />
# Feu un '''clone''' del repositori creat.<br />
# Afegiu l''''arxiu .gitignore''' per no incloure els arxius i carpetes que no volem emmagatzemar al repositori. Com a mínim seran (pel cas dels Pyramid ''scaffolds''):<br />
#* *.pyc<br />
#* <nomdelpaquet>-egg.info<br />
# Copiar els arxius del scaffold (o el projecte que sigui) dins del directori clonat.<br />
# Fer un '''add''' de tots els arxius (git add "*").<br />
# Fer un '''commit''' i un '''push''' per actualitzar.<br />
<br />
=== Nou projecte a GITHUB amb comandes locals ===<br />
Crear nou projecte a Github:<br />
$ curl -u 'USER' https://api.github.com/user/repos -d '{"name":"REPO"}'<br />
...òbviament canviant USER pel teu usuari i REPO pel nom del repositori que vols crear. La URL es queda tal qual.<br />
<br />
Si vols crear un projecte en una organització enlloc de dins d'un compte d'usuari:<br />
$ curl -u 'USER' https://api.github.com/orgs/:org_name/repos -d '{"name":"REPO"}'<br />
<br />
Si volem crear un nou projecte i pujar-lo seguidament:<br />
* Crear un projecte del què sigui (PHP, Python, C++, etc.)<br />
* Inicialitzar la carpeta del projecte:<pre>$ git init</pre><br />
* Afegir .gitignore a l'arrel del projecte per evitar afegir arxius indesitjats (com per exemple els .pyc)<br />
* Afegir tots els arxius:<pre>$ git add .</pre><br />
* Consolidar canvis locals:<pre>$ git commit -am "primer commit"</pre><br />
* Afegir remot del Github:<pre>$ git remote add origin https://github.com/USER/REPO.git</pre><br />
* Pujar els arxius al repo:<pre>$ git push origin master</pre><br />
<br />
<br><br />
<br />
== Comandes ==<br />
Per crear un projete el més fàcil és fer-ho des de la interfície web del github.<br />
<br />
Per afegir arxius, directoris, etc. al projecte<br />
$ git add <arxiu1> <arxiu2> ...<br />
<br />
Per descarregar un projecte de nou:<br />
$ git clone <url><br />
La "url" del github sol ser https://github.com/username/projecte.git<br />
<br />
<br />
Per conèixer l'estat del projecte (arxius modificats, afegits, esborrats, etc.):<br />
$ git status<br />
<br />
Per "gravar" tots els canvis fets durant la sessió:<br />
$ git commit -a<br />
Per "gravar" els canvis d'un sol arxiu:<br />
$ git commit <arxiu1> <arxiu2> ...<br />
<br />
Per carregar els canvis al repositori:<br />
$ git push<br />
<br />
Per descarregar els canvis del repositori:<br />
$ git pull<br />
<br />
<br><br />
<br />
== Branch ==<br />
Per fer "branques" al nostre repositori, primer l'heu d'haver clonat, per exemple el [https://github.com/AWS2/welcome projecte Welcome].<br />
<br />
Al ser GIT un sistema de control de versions distribuit, hem de tenir en compte que hi haurà '''branques locals''' i '''branques remotes'''. Normalment la idea és senzilla:<br />
* Crear branca remota en Github (via web, recorda exactament el nom_branca)<br />
* Descarregar (clone) o actualitzar (pull) el repo local.<br />
* Crear la branca. Si es diu igual la branca remota i la local, quedaran enllaçades automàticament.<pre>$ git branch <nom_branca></pre><br />
* Canviar-se localment a la nova branca de treball.<pre>$ git checkout <nom_branca></pre><br />
* Anar fent ''commits'' i ''push''<br />
<br />
Abans de res, serà més fàcil si creem la branca des de la web de GitHub. Això és important abans de fer el PUSH.<br />
<br />
Crear una branca en el nostre repositori local:<br />
$ git branch <nom_branca><br />
<br />
I després pujar-la al nostre repositori:<br />
$ git push origin <nom_branca><br />
<br />
Per exemple:<br />
$ git branch auth<br />
$ git push origin auth<br />
<br />
<br />
Per veure quines branques estan disponibles i quina tenim activa (*):<br />
$ git branch -a<br />
<br />
Per canviar-nos de branca:<br />
$ git checkout <nom_branca><br />
<br />
<code>...editem el nostre codi...</code><br />
<br />
En aquest punt, cal que creem la branca en el remot a través de la web del projecte en GitHub.com (si no ho hem fet ja).<br />
<br />
Finalment carreguem els canvis:<br />
$ git push<br />
(ens demanarà ususari i contrasenya, i òbviament hem de tenir permsisos d'escriptura en el projecte)<br />
<br />
=== Seguir una branca remota ===<br />
Si en el moment de crear la branca local no s'ha enllaçat a la branca remota, ho podem fer amb:<br />
$ git checkout <branca_local><br />
$ git branch -u origin <branca_remota><br />
<br />
<br><br />
<br />
== Merge ==<br />
Una bona referència: http://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging<br />
<br />
En realitat cal 1r fer un checkout de la branca principal i després unir-li la que vols fusionar (que desapareixerà):<br />
<pre><br />
$ git checkout master<br />
$ git merge hotfix<br />
Updating f42c576..3a0874c<br />
Fast-forward<br />
index.html | 2 ++<br />
1 file changed, 2 insertions(+)<br />
</pre><br />
<br />
<br><br />
<br />
== Creant un repo accessible per SSH ==<br />
Aquí veurem com crear un repositori en un servidor on tenim accés per SSH.<br />
<br />
Al '''servidor''' podem crear un repositori remot amb:<br />
$ git init --bare <nom_carpeta><br />
<br />
Al '''client''' podem crear un repositori local entrant a la carpeta i fent (ull, carpeta remota amb path absolut):<br />
$ git init<br />
$ git remote add origin <usuari>@<servidor>:<carpeta_remota><br />
$ touch README<br />
$ git add .<br />
$ git commit -a<br />
$ git push origin master<br />
<br />
...i ja el tenim.<br />
<br />
Podem clonar des de qualsevol lloc amb:<br />
$ git clone <usuari>@<servidor>:<carpeta_remota><br />
<br />
<br><br />
<br />
== Creant una versió Release ==<br />
Ens solem referir a una ''Release'' a una versió concreta d'un programari que "lliurem" al públic o a un client. La traducció literal de ''release'' és exactament "lliurar".<br />
<br />
Quan parlem de ''releases'' parlem de publicar-les a una web, com Github o Gitlab.<br />
<br />
El sistema de versionat GIT només pot etiquetar un commit concret del nostre repositori. Per poder fer una ''release'' a Github, caldrà que abans etiqueteu (tag) el vostre commit de la vostra branca desitjada, i posteriorment creeu la ''release'' amb la interfície de Github.<br />
<br />
Aquí teniu la doc oficial:<br />
<br />
* Git tagging (etiquetado): https://git-scm.com/book/es/v1/Fundamentos-de-Git-Creando-etiquetas<br />
* Github relases: https://help.github.com/articles/creating-releases/</div>Enrichttps://cacauet.org/wiki/index.php?title=Git:_comandes&diff=4243Git: comandes2021-09-26T23:27:26Z<p>Enric: /* Introducció */</p>
<hr />
<div><nowiki>#FpInfor #DawMp08 #DawMp08Uf04 #DawMp08Uf4</nowiki><br />
<br />
GIT és un sistema de control de versionat semblant a SVN (Subversion). Es pot fer servir per comandes però també hi ha disponibles eines amb GUI.<br />
<br />
== Introducció ==<br />
* Conceptes previs: [[Control de versions]]<br />
* Llibre de referència (en espanyol) http://git-scm.com/book/es<br />
* Interfície gràfica per GIT:<br />
** http://www.rabbitvcs.org/<br />
** http://askubuntu.com/questions/4788/nautilus-git-integration<br />
* Una bona xuleta de totes les funcions de GIT: https://ndpsoftware.com/git-cheatsheet.html<br />
* Un model avançat de com utilitzar GIT: https://nvie.com/posts/a-successful-git-branching-model/<br />
<br />
Un dels principals atractius és el repositori públic https://github.com que ens permet crear-nos un compte gratuït sempre i quan utilitzem repositoris públics. Pels repositoris privats cal pagar.<br />
<br />
En qualsevol moment podem demanar ajuda sobre una comanda mitjançant:<br />
$ man git-<comanda><br />
Per exemple:<br />
$ man git-status<br />
<br />
== Exemple: clonar un projecte ==<br />
Pots provar de clonar un parell de projectes:<br />
* [https://github.com/emieza/pyges Pyges]: un CMS basat en Pyramid per Google App Engine (GAE).<br />
* [https://github.com/emieza/egipcis Egipcis]: senzill exemple d'autenticació amb Pyramid.<br />
<br />
Instal·la el git al teu PC:<br />
$ sudo apt-get install git<br />
<br />
Clona el projecte Faceschool:<br />
$ git clone https://github.com/lacetans/faceschool.git<br />
<br />
Se't descarregarà a la teva màquina. Activa el virtualenv i posa'l en marxa:<br />
$ source ~/env/bin/activate<br />
$ python manage.py runserver<br />
<br />
Prova-ho també amb el projecte "Egipcis" (és més senzill i triga menys a descarregar).<br />
https://github.com/emieza/egipcis.git<br />
<br />
== Crear un projecte nou ==<br />
# Crea el teu compte a http://github.com<br />
# Crea el nou repositori des de la web (és més fàcil).<br />
#* També ho pots fer amb comandes: https://help.github.com/articles/create-a-repo<br />
# Abans de fer un commit penseu a fer un [https://help.github.com/articles/set-up-git setup del GIT] a la vostra màquina (no és imprescindible però convenient més que res per deixar el nom d'usuari i email a cada commit que fem).<br />
# Feu un '''clone''' del repositori creat.<br />
# Afegiu l''''arxiu .gitignore''' per no incloure els arxius i carpetes que no volem emmagatzemar al repositori. Com a mínim seran (pel cas dels Pyramid ''scaffolds''):<br />
#* *.pyc<br />
#* <nomdelpaquet>-egg.info<br />
# Copiar els arxius del scaffold (o el projecte que sigui) dins del directori clonat.<br />
# Fer un '''add''' de tots els arxius (git add "*").<br />
# Fer un '''commit''' i un '''push''' per actualitzar.<br />
<br />
=== Nou projecte a GITHUB amb comandes locals ===<br />
Crear nou projecte a Github:<br />
$ curl -u 'USER' https://api.github.com/user/repos -d '{"name":"REPO"}'<br />
...òbviament canviant USER pel teu usuari i REPO pel nom del repositori que vols crear. La URL es queda tal qual.<br />
<br />
Si vols crear un projecte en una organització enlloc de dins d'un compte d'usuari:<br />
$ curl -u 'USER' https://api.github.com/orgs/:org_name/repos -d '{"name":"REPO"}'<br />
<br />
Si volem crear un nou projecte i pujar-lo seguidament:<br />
* Crear un projecte del què sigui (PHP, Python, C++, etc.)<br />
* Inicialitzar la carpeta del projecte:<pre>$ git init</pre><br />
* Afegir .gitignore a l'arrel del projecte per evitar afegir arxius indesitjats (com per exemple els .pyc)<br />
* Afegir tots els arxius:<pre>$ git add .</pre><br />
* Consolidar canvis locals:<pre>$ git commit -am "primer commit"</pre><br />
* Afegir remot del Github:<pre>$ git remote add origin https://github.com/USER/REPO.git</pre><br />
* Pujar els arxius al repo:<pre>$ git push origin master</pre><br />
<br />
<br><br />
<br />
== Comandes ==<br />
Per crear un projete el més fàcil és fer-ho des de la interfície web del github.<br />
<br />
Per afegir arxius, directoris, etc. al projecte<br />
$ git add <arxiu1> <arxiu2> ...<br />
<br />
Per descarregar un projecte de nou:<br />
$ git clone <url><br />
La "url" del github sol ser https://github.com/username/projecte.git<br />
<br />
<br />
Per conèixer l'estat del projecte (arxius modificats, afegits, esborrats, etc.):<br />
$ git status<br />
<br />
Per "gravar" tots els canvis fets durant la sessió:<br />
$ git commit -a<br />
Per "gravar" els canvis d'un sol arxiu:<br />
$ git commit <arxiu1> <arxiu2> ...<br />
<br />
Per carregar els canvis al repositori:<br />
$ git push<br />
<br />
Per descarregar els canvis del repositori:<br />
$ git pull<br />
<br />
<br><br />
<br />
== Branch ==<br />
Per fer "branques" al nostre repositori, primer l'heu d'haver clonat, per exemple el [https://github.com/AWS2/welcome projecte Welcome].<br />
<br />
Al ser GIT un sistema de control de versions distribuit, hem de tenir en compte que hi haurà '''branques locals''' i '''branques remotes'''. Normalment la idea és senzilla:<br />
* Crear branca remota en Github (via web, recorda exactament el nom_branca)<br />
* Descarregar (clone) o actualitzar (pull) el repo local.<br />
* Crear la branca. Si es diu igual la branca remota i la local, quedaran enllaçades automàticament.<pre>$ git branch <nom_branca></pre><br />
* Canviar-se localment a la nova branca de treball.<pre>$ git checkout <nom_branca></pre><br />
* Anar fent ''commits'' i ''push''<br />
<br />
Abans de res, serà més fàcil si creem la branca des de la web de GitHub. Això és important abans de fer el PUSH.<br />
<br />
Crear una branca en el nostre repositori local:<br />
$ git branch <nom_branca><br />
<br />
I després pujar-la al nostre repositori:<br />
$ git push origin <nom_branca><br />
<br />
Per exemple:<br />
$ git branch auth<br />
$ git push origin auth<br />
<br />
<br />
Per veure quines branques estan disponibles i quina tenim activa (*):<br />
$ git branch -a<br />
<br />
Per canviar-nos de branca:<br />
$ git checkout <nom_branca><br />
<br />
<code>...editem el nostre codi...</code><br />
<br />
En aquest punt, cal que creem la branca en el remot a través de la web del projecte en GitHub.com (si no ho hem fet ja).<br />
<br />
Finalment carreguem els canvis:<br />
$ git push<br />
(ens demanarà ususari i contrasenya, i òbviament hem de tenir permsisos d'escriptura en el projecte)<br />
<br />
=== Seguir una branca remota ===<br />
Si en el moment de crear la branca local no s'ha enllaçat a la branca remota, ho podem fer amb:<br />
$ git checkout <branca_local><br />
$ git branch -u origin <branca_remota><br />
<br />
<br><br />
<br />
== Merge ==<br />
Una bona referència: http://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging<br />
<br />
En realitat cal 1r fer un checkout de la branca principal i després unir-li la que vols fusionar (que desapareixerà):<br />
<pre><br />
$ git checkout master<br />
$ git merge hotfix<br />
Updating f42c576..3a0874c<br />
Fast-forward<br />
index.html | 2 ++<br />
1 file changed, 2 insertions(+)<br />
</pre><br />
<br />
<br><br />
<br />
== Creant un repo accessible per SSH ==<br />
Aquí veurem com crear un repositori en un servidor on tenim accés per SSH.<br />
<br />
Al '''servidor''' podem crear un repositori remot amb:<br />
$ git init --bare <nom_carpeta><br />
<br />
Al '''client''' podem crear un repositori local entrant a la carpeta i fent (ull, carpeta remota amb path absolut):<br />
$ git init<br />
$ git remote add origin <usuari>@<servidor>:<carpeta_remota><br />
$ touch README<br />
$ git add .<br />
$ git commit -a<br />
$ git push origin master<br />
<br />
...i ja el tenim.<br />
<br />
Podem clonar des de qualsevol lloc amb:<br />
$ git clone <usuari>@<servidor>:<carpeta_remota><br />
<br />
<br><br />
<br />
== Creant una versió Release ==<br />
Ens solem referir a una ''Release'' a una versió concreta d'un programari que "lliurem" al públic o a un client. La traducció literal de ''release'' és exactament "lliurar".<br />
<br />
Quan parlem de ''releases'' parlem de publicar-les a una web, com Github o Gitlab.<br />
<br />
El sistema de versionat GIT només pot etiquetar un commit concret del nostre repositori. Per poder fer una ''release'' a Github, caldrà que abans etiqueteu (tag) el vostre commit de la vostra branca desitjada, i posteriorment creeu la ''release'' amb la interfície de Github.<br />
<br />
Aquí teniu la doc oficial:<br />
<br />
* Git tagging (etiquetado): https://git-scm.com/book/es/v1/Fundamentos-de-Git-Creando-etiquetas<br />
* Github relases: https://help.github.com/articles/creating-releases/</div>Enrichttps://cacauet.org/wiki/index.php?title=Serveis_web_amb_Laravel&diff=4242Serveis web amb Laravel2021-03-18T15:29:14Z<p>Enric: /* Autenticació API amb Laravel Sanctum */</p>
<hr />
<div>Per poder seguir amb normalitat aquest article cal haver llegit i treballat [[Laravel]].<br />
<br />
<br />
== Introducció ==<br />
Articles previs:<br />
* [[Serveis Web]]<br />
* [[Laravel]]<br />
<br />
Articles següents:<br />
* [[Serveis Web amb Opendata]]<br />
<br />
=== Perquè Laravel per a serveis web? ===<br />
No és imprescindible utilitzar [[Laravel]] per implementar un servei web. Ens és convenient pels següents motius:<br />
# En el curs de M7 de DAW estem treballant amb aquest framework i ens interessa aprofundir el seu coneixement.<br />
# Integrarem la part del ''frontend'' de la nostra web juntament amb la API que farem.<br />
# Laravel facilita l'accés a la base de dades a través del ORM Eloquent, que resulta molt útil.<br />
<br />
<br><br />
<br />
== Primera prova de la API ==<br />
Anem a implementar una primera prova de API en un projecte [[Laravel]] nou. Si et cal, crea'n un.<br />
<br />
Totes les funcions que vulguem implementar per al nostre sistema hem de començar per indicar-les al arxiu de rutes:<br />
routes/api.php<br />
<br />
De fet, les podríem implementar al mateix arxiu. Quan es compliquin, però, convindrà crear un controlador com vam fer al tutorial de [[Laravel]].<br />
<br />
Afegiu el següent codi a '''routes/api.php''':<br />
<syntaxhighlight lang="php"><br />
Route::get('/ping', function(Request $request) {<br />
return "pong! :)";<br />
});<br />
</syntaxhighlight><br />
<br />
Poseu en marxa el servidor i proveu la funció amb:<br />
$ curl localhost:8000/api/ping<br />
'''pong! :)'''super@HPi5-07:~/dev/laraveltest1$ <br />
<br />
Noteu que:<br />
* Encara que hem definit la ruta "/ping", per poder-la cridar hem de fer "/api/ping". Ve predefinit pel Laravel, tot i que no té perquè ser així.<br />
* Ens contesta el què hem posat al RETURN final<br />
* No retorna HTML, retorna un text que pot ser qualsevol cosa<br />
* No hi ha \n final (s'enganxa amb el ''prompt'' de la ''shell'')<br />
<br />
=== Headers en la crida ''curl'' ===<br />
Per veure els ''headers'' de retorn, podem utilitzar "-i", pot ser molt útil per depurar:<br />
$ curl -i localhost:8000/api/ping<br />
<br />
Obtindrem algo com:<br />
HTTP/1.1 200 OK<br />
Host: localhost:8000<br />
Date: Wed, 17 Mar 2021 15:13:14 GMT<br />
Connection: close<br />
X-Powered-By: PHP/7.4.9<br />
Content-Type: text/html; charset=UTF-8<br />
Cache-Control: no-cache, private<br />
Date: Wed, 17 Mar 2021 15:13:14 GMT<br />
X-RateLimit-Limit: 60<br />
X-RateLimit-Remaining: 59<br />
Access-Control-Allow-Origin: *<br />
<br />
pong! :)super@HPi5-07:~/dev/laraveltest1$ <br />
<br />
<br><br />
<br />
== Autenticació API amb Laravel Sanctum ==<br />
Des de fa algunes versions Laravel ha incorporat diversos mètodes d'autenticació, entre ells Breeze (bàsic), Fortify (avançat) i Sanctum (API). Aquest darrer és el què ens interessa.<br />
<br />
Sanctum té diversos mecanismes, depenent de qui utilitzarà la API (app mòbil, una web externa, etc.). Agafarem l'exemple de la APP MÒBIL.<br />
<br />
Consulta aquí la [https://laravel.com/docs/8.x/sanctum documentació de Laravel Sanctum].<br />
<br />
En definitiva, les diferents passes que cal seguir son:<br />
# Crear projecte Laravel i afegir algun usuari (via Breeze o via Tinker).<br />
# '''Instal·lació''' de Sanctum (install, publish, migrate).<br />
# Anem a la [https://laravel.com/docs/8.x/sanctum#issuing-mobile-api-tokens secció per a generar tokens per a mòbils].<br />
#* Implementem el '''mètode d'autenticació''' mitjançant email i password a l'arxiu '''api.php'''. També cal passar-li el ''device_name'' que quedarà anotat junt al token.<br />
# Anem a la secció [https://laravel.com/docs/8.x/sanctum#issuing-api-tokens generate API tokens] i veiem que cal afegir el TRAIT <code>HasApiTokens</code> al model User.<br />
#: <syntaxhighlight lang="php">class User extends Authenticatable {<br />
use HasApiTokens, HasFactory, Notifiable;<br />
<br />
// ...<br />
}<br />
</syntaxhighlight><br />
# Protegim rutes amb '''->middleware("auth:sanctum")''' , per exemple:<br />
#: <syntaxhighlight lang="php">Route::middleware('auth:sanctum')->get("/ping", function(Request $request) {<br />
// ...<br />
}<br />
</syntaxhighlight><br />
# Ara simularem la crida per '''demanar el token''' (la que posteriorment faríem des d'un mòbil)<br />
#: <pre>curl localhost:8000/api/sanctum/token -X POST -d 'email=jo@domini.com&password=enric123&device_name=LolaPhone55'</pre><br />
#: Prendre nota del TOKEN que se'ns retorna.<br />
# Crida URL per '''accedir a la API amb el Header Bearer''' necessari :<br />
#: <pre>curl localhost:8000/api/ping -H 'Authorization: Bearer lL0a21yHy4MzU4FdV5Cm0xZzd35AJ97acOOnW83t'</pre><br />
#: Si no posem el token adequadament se'ns redireccionarà a la pàgina principal amb un codi 302<br />
<br />
<br><br />
<br />
== Exemples de API: laravel-karaoke ==<br />
En el projecte karaoke en Laravel, el podeu veure aquí:<br />
* [https://github.com/emieza/laravel-karaoke/commit/8ab648decd6b58380545c60b135bad849a622d77 Versió amb el codi a api.php]. Es pot fer, però és una solució una mica "guarrilla"<br />
* [https://github.com/emieza/laravel-karaoke/blob/master/routes/api.php Versió amb el codi en un ''controller'']. Només veiem les rutes, però és raonable que no posem mogollón de codi aquí, sinó al [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php TemaController] en aquest cas.<br />
<br />
Recordem que per crear un controller amb Laravel ho fem amb (per exemple):<br />
$ php artisan make:controller ApiController<br />
<br />
Si mireu [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php TemaController] pareu atenció que per poder fer crides com <code>TemaController::fet($id)</code> , necessitem que siguin funcions estàtiques (static).<br />
<br />
Ara, per poder mirar el nº de vots, a '''routes/api.php''' tindrem:<br />
<syntaxhighlight lang="php"><br />
Route::get('/nvots/{id}', function(Request $request, $id) {<br />
return TemaController::nvots( $id );<br />
});<br />
</syntaxhighlight><br />
<br />
<br><br />
<br />
== Especificacions d'una API ==<br />
És molt important especificar adequadament una API per tal que la pugui fer servir molta gent.<br />
<br />
En l'exemple del karaoke tenim 3 crides, i les especificacions les indiquem amb quadres com els que mostrem a continuació:<br />
* /api/'''nvots'''/{tema_id}<br />
* /api/'''vota'''/{tema_id}<br />
* /api/'''fet'''/{tema_id}<br />
<br />
<br />
=== nvots ===<br />
Al ser una crida GET, els paràmetres han d'anar a la URL. Si fos POST, anirien afegits en el cos de la ''request'':<br />
<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L68 Veure codi del TemaController@nvots]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/nvots/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
Aquesta response retorna les dades en format '''JSON''', però podria tenir altres formats (XML, plain text):<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/nvots/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| nvots<br />
| integer<br />
| Total de vots per al tema<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema consultat<br />
|}<br />
<br />
Per exemple, per testejar-la:<br />
$ curl http://localhost:8000/api/nvots/1<br />
{"status":"OK","tema_id":"1","nvots":1}<br />
<br />
Per testejar l'exemple en producció, podeu provar (el -k és important perquè no demani els certificats HTTPS):<br />
$ curl https://jolgorio.tk/api/nvots/1 '''-k'''<br />
{"status":"OK","tema_id":"1","nvots":2}<br />
<br />
<br><br />
<br />
=== vota ===<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L112 Veure codi de TemaController@vota]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| vot<br />
| true / false<br />
| Estat actual del nostre vot de la nostra IP<br />
|-<br />
| nvots<br />
| integer<br />
| Total de vots per al tema<br />
|-<br />
| message<br />
| text<br />
| Missatge de text amb la descripció de l'error o acció<br />
|}<br />
<br />
<br><br />
<br />
=== fet ===<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L86 Veure codi de TemaController@fet]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| fet<br />
| true / false<br />
| Estat actual del tema (fet / no fet)<br />
|-<br />
| message<br />
| text<br />
| Missatge de text amb la descripció de l'error o acció<br />
|}<br />
<br />
<br></div>Enrichttps://cacauet.org/wiki/index.php?title=Laravel&diff=4241Laravel2021-03-17T15:25:56Z<p>Enric: /* Heroku */</p>
<hr />
<div><nowiki>#FpInfor #DawMp07 #DawMp07Uf2 #DawMp07Uf02 #DawMpDual</nowiki><br />
<br />
<br />
== Intro i referències ==<br />
Laravel és un framework web per a PHP que està agafant molta força.<br />
<br />
Documentació oficial: https://laravel.com/docs/<br />
<br />
Tutorials:<br />
* [https://ajgallego.gitbooks.io/laravel-5/content/index.html Principal tutorial per seguir el curs]: <pre>https://ajgallego.gitbooks.io/laravel-5/content/index.html</pre><br />
* Forms: https://selftaughtcoders.com/from-idea-to-launch/lesson-23/laravel-5-application-form-model-binding-laravelcollective-forms-html-library-bootstrap-framework/<br />
* Forms i validació: https://scotch.io/tutorials/simple-laravel-crud-with-resource-controllers<br />
* Apunts del Sergi Coll: https://seicoll.github.io/DAW-M07-UF2-Apunts/<br />
* https://styde.net/laravel-5/<br />
* Per passar del schema SQL (per ex. de MySQL Workbench) a Laravel migration: https://adolfocuadros.com/sql_to_laravel/<br />
<br />
<br />
Plugins:<br />
* CORS (Cross-Origin Resource Sharing): https://github.com/barryvdh/laravel-cors<br />
* CRUD & admin : Hi ha molts plugins per crear ''admin panels'' automàticament. Alguns son:<br />
** Voyager: https://voyager.devdojo.com/<br />
** Craftable: https://www.getcraftable.com/<br />
* https://iamacoder.com/post/5-must-have-laravel-5-packages/<br />
<br />
Temes a ampliar:<br />
* Forms: https://laravel.com/docs/4.2/html<br />
* Validació de forms: https://laravel.com/docs/5.5/validation<br />
* Autenticació: https://laravel.com/docs/5.5/authentication<br />
<br />
<br><br />
<br />
== Instal·lació i setup ==<br />
<br />
Prerequisits:<br />
* Laravel i PHP, és molt important tenir en compte les versions:<br />
** <strike>Laravel 5.3 : PHP >= 5.6.4<br />
** Laravel 5.5 : PHP == 7.0<br />
** Laravel 5.6 : PHP >= 7.1<br />
** Laravel 5.7 : PHP >= 7.1.3</strike><br />
** Laravel 6.x : PHP >= 7.2<br />
* Si utilitzes Ubuntu 14 o menor [https://www.digitalocean.com/community/tutorials/how-to-upgrade-to-php-7-on-ubuntu-14-04 actualitza la teva versió de PHP a la 7.0]<br />
* Calen els paquets següents: <pre>$ sudo apt-get install php-mbstring php-zip php-xml php-mysql</pre><br />
<br />
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...:<br />
# Instal·la el gestor de paquets per PHP Composer<br />
#* El més fàcil és fer: (però no ho farem pq volem la darrera versió)<pre>$ sudo apt install composer</pre><br />
#* Prova primer la instal·lació genèrica : [https://getcomposer.org/download/ Instal.la PHP Composer]<br />
#* També tens aquesta altra forma d' [https://getcomposer.org/doc/00-intro.md#installation-linux-unix-osx instal·lar Composer per GNU/Linux]. Descarrega composer-setup.php i instal·la'l així:<pre>$ php composer-setup.php --install-dir=~/bin --filename=composer</pre><br />
# Instal·la la darrera versió de Laravel<br />
#* https://laravel.com/docs/5.7/installation<br />
#* Bàsicament el què cal fer és aquesta comanda per instal·lar el binari ''laravel'':<pre>$ composer global require laravel/installer</pre><br />
#* Laravel s'instal·la a <code>$HOME/.config/composer</code> però per poder executar les properes comandes necessitarem tenir <code>$HOME/.config/composer/vendor/bin</code> al nostre $PATH. Inserta això al teu <code>$HOME/.profile</code>: <pre>PATH=$PATH:~/.config/composer/vendor/bin</pre><br />
#*: Fes logout/login del sistema per activar aquests canvis<br />
# Crea una app Laravel allà on et faci més ràbia: <pre>$ laravel new laravelapp1</pre><br />
#: o també: <pre>$ composer create-project --prefer-dist laravel/laravel laravelapp1</pre><br />
#: o si volem una versió específica de laravel: <pre>$ composer create-project --prefer-dist laravel/laravel=5.8.* laravelapp1</pre><br />
# Arrenca l'aplicació de prova: <pre>$ php artisan serve</pre><br />
# Comprova la app amb el navegador a<pre>http://localhost:8000</pre><br />
<br />
<br><br />
<br />
Si ja has completat la instal·lació, pots procedir a crear un altre projecte nou i realitzar el següent tutorial "tasklist":<br />
https://laravel.com/docs/5.2/quickstart<br />
<br />
<br><br />
<br />
== Incidències vàries ==<br />
Aquest és un bon tutorial:<br />
https://ajgallego.gitbooks.io/laravel-5/content/index.html<br />
<br />
Igualment, podríem trobar algunes incidències. Us dono pistes:<br />
<br />
=== Treballant amb GIT i clonant ===<br />
Al pujar el projecte a un repo GIT, i clonar-lo després caldrà:<br />
# Re-instal·lar les dependències:<pre>$ composer install</pre><br />
# Regenerar arxiu <code>.env</code> : com que depèn de cada entorn no es fica al projecte (es posa a <code>.gitignore</code>), però pots copiar i modificar de <code>.env.example</code><br />
# Error ''The only supported ciphers are AES-128-CBC and AES-256-CBC with the correct key lengths.'' Es soluciona amb :<pre>$ php artisan key:generate</pre><br />
<br />
=== Creant controllers amb CRUD complert ===<br />
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.<br />
# Ja no es pot fer amb <strike><code>Route::controller</code></strike> sinó amb:<pre>Route::resource("cosa","CosaController");</pre><br />
# Per exemple, per crear un controller per al model "Cosa" ho faríem amb -r (de resource): <pre>$ php artisan make:controller -r CosaController</pre><br />
<br />
=== Treballant amb SQLite ===<br />
Per configurar la BD amb SQLite cal crear el fitxer abans amb:<br />
$ touch db.sqlite<br />
<br />
Configurar la BD a .env:<br />
DB_CONNECTION=sqlite<br />
DB_DATABASE=/path/absolut/al/db.sqlite<br />
<br />
Instal·lar els binaris necessaris de SQLite i de PHP:<br />
$ sudo apt-get install sqlite php-sqlite3<br />
<br />
I crear la BD inicial amb:<br />
$ php artisan migrate<br />
<br />
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.<br />
<br />
=== Eliminant models o migracions ===<br />
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:<br />
$ composer dump-autoload<br />
...i es tornaran a generar els arxius d'autoload sense els arxius que volíem esborrar.<br />
<br />
=== Treballant amb proxies i composer ===<br />
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):<br />
$ composer update<br />
Loading composer repositories with package information<br />
Updating dependencies (including require-dev)<br />
(...demana user/password de packagist.org ...)<br />
<br />
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:<br />
$ ssh -L 3128:localhost:3128 jo@elmeuserver.com<br />
I un cop logats, aprofitem per instal·lar el squid:<br />
$ sudo apt install squid<br />
Hem de mantenir la shell oberta mentre vulguem que estigui activat el túnel (l'hem assignat a localhost:3128).<br />
<br />
Obrim una altra shell i anem al nostre projecte Laravel:<br />
$ export http_proxy=localhost:3128<br />
$ composer update<br />
<br />
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).<br />
<br />
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:<br />
$ ssh jo@elmeuserver.com<br />
$ sudo apt remove squid<br />
<br />
<br><br />
<br />
== Tutorials ==<br />
Després d'elaborar la documentació he trobat aquest tutorial bastant útil (només fins la v5.2):<br />
https://laravel.com/docs/5.2/quickstart<br />
<br />
Tutorial per a CRUD complert:<br />
https://www.itsolutionstuff.com/post/laravel-6-crud-application-tutorialexample.html<br />
<br />
== Resum per a fer un CRUD ==<br />
<br />
=== Setup projecte ===<br />
Crear projecte:<br />
$ laravel new proj1<br />
Crear DB (en aquest cas SQLite:<br />
$ touch db.sqlite<br />
Modifica .env per configurar la DB com sqlite:<br />
DB_CONNECTION=sqlite<br />
DB_DATABASE=/path/absolut/al/db.sqlite<br />
<br />
=== Model ===<br />
Crear taules i migracions:<br />
$ php artisan make:migration crea_taula_items --create=items<br />
Editar la migració per crear les taules adequades. Mira't les principals referències:<br />
* [https://laravel.com/docs/5.5/migrations#columns Tipus de columnes]<br />
* [https://laravel.com/docs/5.5/migrations#foreign-key-constraints Relacions i FKs]<br />
Realitzar la migració:<br />
$ php artisan migrate<br />
Crear models:<br />
$ php artisan make:model Item<br />
Ajusta el model perquè apunti al nom correcte de la taula:<br />
https://laravel.com/docs/5.5/eloquent#eloquent-model-conventions<br />
<br />
=== Controller i rutes ===<br />
Crear controllers amb els mètodes estàndard (index, create-store, show, edit-update, destroy):<br />
$ php artisan make:controller -r ItemController<br />
Crear rutes a <code>routes/web.php</code>:<br />
Route::resource("item","ItemController");<br />
Crear plantilles per als mètodes (l'exemple diu "tema" enlloc de "item"):<br />
$ php artisan route:list<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
| Domain | Method | URI | Name | Action | Middleware |<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
| | GET|HEAD | / | | Closure | web |<br />
| | GET|HEAD | api/user | | Closure | api,auth:api |<br />
| | GET|HEAD | tema | tema.index | App\Http\Controllers\TemaController@index | web |<br />
| | POST | tema | tema.store | App\Http\Controllers\TemaController@store | web |<br />
| | GET|HEAD | tema/create | tema.create | App\Http\Controllers\TemaController@create | web |<br />
| | GET|HEAD | tema/{tema} | tema.show | App\Http\Controllers\TemaController@show | web |<br />
| | PUT|PATCH | tema/{tema} | tema.update | App\Http\Controllers\TemaController@update | web |<br />
| | DELETE | tema/{tema} | tema.destroy | App\Http\Controllers\TemaController@destroy | web |<br />
| | GET|HEAD | tema/{tema}/edit | tema.edit | App\Http\Controllers\TemaController@edit | web |<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
<br />
Crear les views (plantilles blade) adequades per a tots els mètodes necessaris (els arxius van a <code>resources/views</code>). Pots veure [https://github.com/emieza/laravel-karaoke/tree/master/resources/views/llista aqui] alguns exemples.<br />
* '''index''' : llista tots els elements<br />
* '''show''' : mostra un element en concret, necessita que li passem un paràmetre per GET (id del element a mostrar)<br />
* '''create-store''' : "create és el form (no necessita codi), i "store" és el codi per insertar-ho a la BD (no necessita una plantilla)<br />
* '''edit-update''' : "edit" és el form, i "update" el codi per actualitzar la BD<br />
* '''destroy''' : elimina un element<br />
<br />
=== Codi del Controller i View ===<br />
* Crear views amb formularis d'entrada de dades: [https://github.com/emieza/laravel-karaoke/blob/master/resources/views/llista/crea.blade.php create.blade.php d'exemple]<br />
* Editar el codi del Controller per cridar pertinentment a les views: [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/LlistaController.php Controller d'exemple]<br />
<br />
=== Més docs ===<br />
Una bona referència de la doc oficial per fer un CRUD és aquesta:<br />
https://laravel.com/docs/5.2/quickstart<br />
En particular per veure com utilitzar les templates oficials amb bootstrap ;)<br />
<br />
<br><br />
<br />
== Projecte d'exemple ==<br />
Aquest és el projecte que he realitzat per entrenar-me, et pot servir d'exemple. El pots veure en producció aquí: https://jolgorio.tk<br />
https://github.com/emieza/laravel-karaoke<br />
<br />
Fes-li un cop d'ull al readme.md per veure com posar-lo en marxa.<br />
<br />
MOLT IMPORTANT PEL PROJECTE: Cal crear un README.md (com [https://github.com/emieza/laravel-karaoke/blob/master/readme.md per exemple aquest]). No acceptaré cap projecte sense README.md<br />
<br />
Per entrenar-vos amb el Markdown teniu aquest tester:<br />
http://dillinger.io/<br />
<br />
Anem per feina:<br />
# Taules: llistes, temes, vots<br />
# Rutes que vols implementar per al projecte. [https://github.com/emieza/laravel-karaoke/blob/master/routes/web.php En el meu cas, tinc]:<br />
#* /llista/crea (GET per formulari + POST per store)<br />
#* /llista (index de llistes)<br />
#* /llista/{id} (show)<br />
#* /llista/{id}/crea (GET + POST, per crear temes en les llistes)<br />
#* /vota/{idtema}<br />
# Codi:<br />
#* als Controllers pertinents. Mira't l'[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/LlistaController.php exemple de les llistes de karaoke].<br />
#* Plantilles: a resources/views/xxxx.blade.php . Mira't l'[https://github.com/emieza/laravel-karaoke/tree/master/resources/views/llista exemple un altre cop].<br />
<br />
<br><br />
<br />
== ORM : Models i relacions ==<br />
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.<br />
<br />
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. <br />
<br />
El què anem a explicar està documentat a l'apartat "Eloquent ORM" de Laravel:<br />
https://laravel.com/docs/5.7/eloquent-relationships<br />
https://laravel.com/docs/6.x/eloquent-relationships<br />
<br />
=== Accedint relacions 1-N de forma directa ===<br />
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í.<br />
<br />
L'objectiu serà poder accedir a l'objecte pare d'aquesta manera per mostrar el text del Post (pare).<br />
<syntaxhighlight lang="php"><br />
$comment = Comment::find(33);<br />
echo $comment->post->text;<br />
</syntaxhighlight><br />
<br />
Per aconseguir això, cal que indiquem la relació existent a les taules entre els models Post i Comment amb la relació <code>belongsTo</code>:<br />
<br />
<syntaxhighlight lang="php"><br />
<?php<br />
namespace App;<br />
use Illuminate\Database\Eloquent\Model;<br />
class Comment extends Model<br />
{<br />
/**<br />
* Accedeix al pare (Post)<br />
*/<br />
public function post()<br />
{<br />
return $this->belongsTo('App\Post','post_id');<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Accedint relacions 1-N de forma inversa ===<br />
El següent cas típic serà accedir des d'un objecte Post als diferents Comentaris, més o menys així:<br />
<br />
<syntaxhighlight lang="php"><br />
$comments = App\Post::find(1)->comments;<br />
foreach ($comments as $comment) {<br />
// ... el teu codi...<br />
echo $comment->text;<br />
}<br />
</syntaxhighlight><br />
El codi que veiem és per a un ''controller'', però es pot aplicar també als ''templates'', amb @foreach i similars.<br />
<br />
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<br />
<syntaxhighlight lang="php"><br />
<?php<br />
namespace App;<br />
use Illuminate\Database\Eloquent\Model;<br />
class Post extends Model<br />
{<br />
/**<br />
* Accedeix als comentaris relacionats amb el Post actual<br />
*/<br />
public function comments()<br />
{<br />
return $this->hasMany('App\Comment','<ref_remota>','<ref_local>');<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
On:<br />
* <ref_remota> és el camp de la taula de Comment que referencia el Post<br />
* <ref_local> és el camp de Post que fa de PK i on Comment apunta<br />
<br />
Per accedir al objecte relacionat "pare" caldrà fer una altra funció, en concret ''belongsTo''. Consulta la doc de les relacions 1-a-N (inversa).<br />
<br />
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:<br />
https://laravel.com/docs/5.5/eloquent-relationships#one-to-many<br />
<br />
=== Aniuant JSON en la API ===<br />
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:<br />
<br />
<syntaxhighlight lang="php"><br />
<?php<br />
Route::get("/comentaris", function() {<br />
$post = Post::with("comments")->get();<br />
return $post;<br />
});<br />
</syntaxhighlight><br />
<br />
...i ens retornarà les dades aniuades que volem! :)<br />
<br />
<br><br />
<br />
== Més coses ==<br />
Alguns temes que no hem aprofundit però que convé conèixer.<br />
<br />
=== Autenticació ===<br />
Senzill d'implementar i imprescindible. Laravel incorpora un ''scaffold'' per facilitar una funció tan estàndard.<br />
Amb una sola instrucció ens crea les rutes, vistes i els controllers típics (login, logout).<br />
<br />
==== Laravel 5.x ====<br />
[https://laravel.com/docs/5.5/authentication Autenticació en Laravel 5.x]:<br />
$ php artisan make:auth<br />
<br />
==== Laravel 6.x ====<br />
[https://laravel.com/docs/6.x/authentication Autenticació en Laravel 6.x]:<br />
$ composer require laravel/ui --dev<br />
$ php artisan ui vue --auth<br />
<br />
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:<br />
$ npm install && npm run dev<br />
<br />
També hi ha [https://laracasts.com/discuss/channels/laravel/laravel-60-appcss?page=1 solucions al problema carregant els CSS i JS del CDN] (només cal canviar un link en el ''head'' de <code>app.blade.php</code>.<br />
<br />
==== Laravel 8.x ====<br />
Ara el mòdul d'autenticació es diu [https://laravel.com/docs/8.x/starter-kits#laravel-breeze Laravel Breeze].<br />
<br />
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:<br />
* '''routes/web.php'''<br />
* '''resources/views/layouts/app.blade.php'''<br />
* resources/views/layouts/guest.blade.php<br />
* resources/views/layouts/navigation.blade.php<br />
* resources/views/auth/*<br />
* resources/views/components/*<br />
* resources/views/welcome.blade.php<br />
* resources/views/dashboard.blade.php<br />
<br />
Resumint, per instal·lar Breeze:<br />
$ composer require laravel/breeze --dev<br />
$ php artisan breeze:install<br />
$ npm install<br />
$ npm run dev<br />
<br />
==== Rols d'usuari ====<br />
En molts moments pot interessar tenir diversos rols d'usuari (admin, usuari, redactor, etc.).<br />
<br />
[https://medium.com/@otimfredrick/how-to-protect-admin-panel-route-in-laravel-70bb86168d87 Aquest post explica com utiltizar rols d'usuari] amb els sistemes bàsics d'autenticació de Laravel (Breeze, etc.).<br />
<br />
<br />
==== Desactivar registre d'usuaris ====<br />
Hi ha diverses maneres de desactivar el registre d'usuaris segons els mètodes d'autenticació triats (Breeze, JetStream o Fortify).<br />
<br />
Una manera senzilla d'aconseguir-ho és anar a les rutes de registre i comentar-les.<br />
<br />
=== Seeding ===<br />
Una part molt important és la de crear dades per farcir la base de dades inicialment i poder així testejar amb comoditat.<br />
<br />
https://laravel.com/docs/6.x/seeding<br />
<br />
En algun moment donat convé utilitzar un ''factory'' que ens permet crear elements en massa:<br />
<br />
https://laravel.com/docs/6.x/database-testing#writing-factories<br />
<br />
El ''factory'' sol utilitzar una llibreria <code>Faker</code> que ens va molt bé per crear noms i cognoms aleatoris, lorem ipsum, etc. que ens facilitarà la creació de dades de prova.<br />
<br />
https://github.com/fzaninotto/Faker<br />
<br />
=== Validacions ===<br />
Laravel ens ofereix un mecanisme de validació de formularis molt potent i efectiu.<br />
<br />
https://laravel.com/docs/5.5/validation<br />
<br />
=== Sessions ===<br />
D'entrada és molt útil per emetre missatges "flash", i informar l'usuari del processament intern.<br />
<br />
https://laravel.com/docs/5.5/session<br />
<br />
=== Arxius: filesystem vs BLOBs en BD ===<br />
Les imatges es poden guardar al sistema d'arxius o bé a la base de dades.<br />
* '''Filesystem''': En el propi tutorial hi ha una explicació de [https://ajgallego.gitbooks.io/laravel-5/content/capitulo_4_datos_de_entrada.html com guardar binaris amb el mètode clàssic del filesystem]<br />
* '''BLOBs en la BD''': Laravel ens permet crear models amb BLOBs i insertar les dades a la BD:<br />
** [https://www.daniweb.com/programming/web-development/threads/480731/how-to-inserting-files-on-mysql-using-laravel Insertant BLOBs amb Larvel]<br />
** Tingueu en compte, si ho feu així, de [https://stackoverflow.com/questions/8499633/how-to-display-base64-images-in-html com renderitzar continguts base64 (BLOBs) sobre un HTML]<br />
<br />
=== A solucionar ===<br />
Alguns temes a solucionar:<br />
* Quan utilitzem el scaffold d'autenticació, falla el logout. Això es deu a un canvi del mètode de GET a POST per motius de seguretat (amb POST, només podran fer logout des de la pròpia app Laravel ja que porta el csrf_token).<br />
*: https://laracasts.com/discuss/channels/laravel/laravel-53-logout-methodnotallowed<br />
<br />
<br><br />
<br />
=== Atacant 2 bases de dades simultàniament ===<br />
En alguns casos podem necessitar configurar 2 instàncies de bases de dades separades per optimitzar el rendiment. Aquest post ho explica molt bé:<br />
https://fideloper.com/laravel-multiple-database-connections<br />
<br />
Caldrà configurar el .env , config/database.php i especificar quina DB ataca en les migracions i en els models que creem.<br />
<br />
<br><br />
<br />
== Laravel i LDAP ==<br />
Aquest mòdul està pensat per a Active Directory, però [https://github.com/Adldap2/Adldap2-Laravel/issues/106 també funciona amb OpenLDAP si s'ajusta bé]:<br />
https://github.com/Adldap2/Adldap2-Laravel<br />
<br />
Primer cal configurar un servidor [[LDAP]].<br />
<br />
Després, tingues en compte que cal ajustar els següents paràmetres en el .env:<br />
ADLDAP_CONTROLLERS=localhost<br />
#ADLDAP_PORT=389<br />
ADLDAP_ADMIN_USERNAME="cn=admin,dc=cacauet,dc=org"<br />
ADLDAP_ADMIN_PASSWORD="enric123"<br />
ADLDAP_BASEDN="dc=cacauet,dc=org"<br />
<br />
Podem fer una autenticació seguint algun d'aquests exemples.<br />
<br />
Exemple 1: cercar un element del directori<br />
<syntaxhighlight lang="php"><br />
$user = Adldap::search()->where("mail","=","pepe@jolgorio.tk")->get();<br />
</syntaxhighlight><br />
<br />
Exemple 2: autenticar un usuari<br />
<syntaxhighlight lang="php"><br />
if( Adldap::auth()->attempt("cn=pepe,ou=usuaris,dc=cacauet,dc=org","pepe123")) {<br />
// autenticació exitosa<br />
return "Pepe OK!";<br />
}<br />
</syntaxhighlight><br />
<br />
<br><br />
<br />
== Laravel en producció ==<br />
Per posar en producció un projecte basat en Laravel cal tenir en compte:<br />
* '''IMPORTANT, SEGURETAT: Només cal publicar la carpeta <code>/public</code>''' . 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 .<br />
** Aquesta carpeta <code>/public</code> no figura inicialment quan creem o clonem un projecte (està a .gitignore), a l'igual que la carpeta <code>/vendor</code>, que es generen quan fem un <code>$ composer install</code>.<br />
** Reviseu la secció [[Laravel#Treballant_amb_GIT_i_clonant]] per fer el setup del projecte després de clonar.<br />
* '''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'').<br />
* 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:<br />
** db.sqlite (si s'escau)<br />
** carpeta <code>/storage</code><br />
** carpeta <code>/bootstrap/cache</code><br />
<br />
=== Desplegament en AWS amb Ubuntu i Apache ===<br />
Guia pel desplegament en Ubuntu amb Apache:<br />
* Accedir al nostre servidor via SSH<br />
* 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<pre>/var/www</pre><br />
* Per veure detalls reviseu la secció [[Laravel#Treballant_amb_GIT_i_clonant]]. Recordeu que això implica: <br />
*# composer install<br />
*# configurar arxiu .env<br />
*# generar clau<br />
* Es requereix el mòdul ''mod_rewrite'' d'Apache (o Nginx)<pre>$ sudo a2enmod rewrite</pre><br />
* Publicar la carpeta <code>/public</code> del projecte Laravel, d'alguna d'aquestes maneres:<br />
** Crear un VirtualHost i apuntar la ServerRoot del domini o subdomini a /var/www/<projecte>/public<br />
** Crear un link simbòlic de la carpeta pública d'Apache a la carpeta public del Laravel amb la comanda <pre>$ ln -s /var/www/<projecte>/public /var/www/html/lara1</pre><br />
* 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".<br />
* Ajusta els permisos de:<br />
** db.sqlite (si s'escau) i també de la carpeta que el conté (si no, no es podrà escriure-hi)<br />
** carpeta <code>/storage</code><br />
** carpeta <code>/bootstrap/cache</code><br />
* Cal activar els arxius <code>.htaccess</code> , afegint la directiva <code>AllowOverride all</code><br />
<br />
A l'arxiu de conf. del nostre VirtualHost (a <code>/etc/apache2/sites-available</code>):<br />
<Directory /var/www/><br />
AllowOverride All<br />
</Directory><br />
<br />
<br />
És important remarcar que per SEGURETAT no hem de mostrar mai els arxius interns de Laravel, només cal publicar el contingut de /public<br />
<br />
<br><br />
<br />
=== Heroku ===<br />
Abans de procedir amb aquesta part hauries de llegir i treballar aquesta altra: [[Heroku]] on treballem amb PHP simple.<br />
<br />
Pots posar en marxa un projecte Laravel a Heroku fàcilment seguint aquesta documentació. Segueix el tutorial per iniciar la app:<br />
https://devcenter.heroku.com/articles/getting-started-with-laravel<br />
<br />
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.<br />
<br />
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.<br />
<br />
En canvi, [https://devcenter.heroku.com/articles/heroku-postgresql el add-on de POSTGRESQL és gratuït i sense targeta de crèdit! :)] Som-hi, doncs!<br />
<br />
Primer de tot, creeu el projecte Laravel i inicialitzeu GIT en cas que no el tingueu penjat a Github o similars:<br />
$ git init<br />
<br />
Tb caldrà afegir un Procfile adequat per Laravel:<br />
$ echo "web: vendor/bin/heroku-php-apache2 public/" > Procfile<br />
<br />
Inicialitzem projecte Heroku:<br />
$ heroku create elmeuprojectedeguais<br />
<br />
Afegim els arxius al repo local:<br />
$ git add .<br />
$ git commit -am "primer commit"<br />
<br />
Afegim la BD PostgreSQL:<br />
$ heroku addons:create heroku-postgresql:hobby-dev<br />
<br />
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:<br />
$ heroku config -s | grep -i post<br />
<br />
Ens ho dona en la següent forma (exemple a continuació):<br />
DATABASE_URL='postgres://<usuari>:<password>@<maquina>:<port>/<bbdd>'<br />
DATABASE_URL='postgres://mxlsfebqyopadb:3e5af56b52cc06574645123ea9d9f7504564e207804dcc71a2db2848446ba064@ec2-156-73-167-43.compute-1.amazonaws.com:5432/d353ihheo564q7'<br />
<br />
Així, doncs, només caldrà ajustar les següents variables d'entorn que necessita el Laravel perquè això funcioni:<br />
DB_CONNECTION=pgsql<br />
DB_HOST=ec2-156...<br />
DB_PORT=5432<br />
DB_DATABASE=d353...<br />
DB_USERNAME=mxls...<br />
DB_PASSWORD=3e5a...<br />
<br />
Per fer-ho cal anar executant les següents ordres:<br />
$ heroku config:set DB_CONNECTION=pgsql<br />
$ ...etc...<br />
<br />
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:<br />
$ cp .env.example .env<br />
$ php artisan key:generate<br />
$ heroku config:set APP_KEY=base64:tX2ikx...<br />
<br />
En acabat, podem posar la app en producció:<br />
$ git add .<br />
$ git push heroku master<br />
<br />
I un cop acabats, migrem la nostra base de dades:<br />
$ heroku run php artisan migrate<br />
<br />
I veure la nostra flamant web en producció (a elmeuprojectedeguais.herokuapp.com):<br />
$ heroku open<br />
<br />
...et voilà!<br />
<br />
<br><br />
<br />
== Serveis web amb Laravel ==<br />
<br />
[[Serveis web amb Laravel]]</div>Enrichttps://cacauet.org/wiki/index.php?title=Serveis_web_amb_Laravel&diff=4240Serveis web amb Laravel2021-03-17T15:24:17Z<p>Enric: /* Autenticació API amb Laravel Sanctum */</p>
<hr />
<div>Per poder seguir amb normalitat aquest article cal haver llegit i treballat [[Laravel]].<br />
<br />
<br />
== Introducció ==<br />
Articles previs:<br />
* [[Serveis Web]]<br />
* [[Laravel]]<br />
<br />
Articles següents:<br />
* [[Serveis Web amb Opendata]]<br />
<br />
=== Perquè Laravel per a serveis web? ===<br />
No és imprescindible utilitzar [[Laravel]] per implementar un servei web. Ens és convenient pels següents motius:<br />
# En el curs de M7 de DAW estem treballant amb aquest framework i ens interessa aprofundir el seu coneixement.<br />
# Integrarem la part del ''frontend'' de la nostra web juntament amb la API que farem.<br />
# Laravel facilita l'accés a la base de dades a través del ORM Eloquent, que resulta molt útil.<br />
<br />
<br><br />
<br />
== Primera prova de la API ==<br />
Anem a implementar una primera prova de API en un projecte [[Laravel]] nou. Si et cal, crea'n un.<br />
<br />
Totes les funcions que vulguem implementar per al nostre sistema hem de començar per indicar-les al arxiu de rutes:<br />
routes/api.php<br />
<br />
De fet, les podríem implementar al mateix arxiu. Quan es compliquin, però, convindrà crear un controlador com vam fer al tutorial de [[Laravel]].<br />
<br />
Afegiu el següent codi a '''routes/api.php''':<br />
<syntaxhighlight lang="php"><br />
Route::get('/ping', function(Request $request) {<br />
return "pong! :)";<br />
});<br />
</syntaxhighlight><br />
<br />
Poseu en marxa el servidor i proveu la funció amb:<br />
$ curl localhost:8000/api/ping<br />
'''pong! :)'''super@HPi5-07:~/dev/laraveltest1$ <br />
<br />
Noteu que:<br />
* Encara que hem definit la ruta "/ping", per poder-la cridar hem de fer "/api/ping". Ve predefinit pel Laravel, tot i que no té perquè ser així.<br />
* Ens contesta el què hem posat al RETURN final<br />
* No retorna HTML, retorna un text que pot ser qualsevol cosa<br />
* No hi ha \n final (s'enganxa amb el ''prompt'' de la ''shell'')<br />
<br />
=== Headers en la crida ''curl'' ===<br />
Per veure els ''headers'' de retorn, podem utilitzar "-i", pot ser molt útil per depurar:<br />
$ curl -i localhost:8000/api/ping<br />
<br />
Obtindrem algo com:<br />
HTTP/1.1 200 OK<br />
Host: localhost:8000<br />
Date: Wed, 17 Mar 2021 15:13:14 GMT<br />
Connection: close<br />
X-Powered-By: PHP/7.4.9<br />
Content-Type: text/html; charset=UTF-8<br />
Cache-Control: no-cache, private<br />
Date: Wed, 17 Mar 2021 15:13:14 GMT<br />
X-RateLimit-Limit: 60<br />
X-RateLimit-Remaining: 59<br />
Access-Control-Allow-Origin: *<br />
<br />
pong! :)super@HPi5-07:~/dev/laraveltest1$ <br />
<br />
<br><br />
<br />
== Autenticació API amb Laravel Sanctum ==<br />
Des de fa algunes versions Laravel ha incorporat diversos mètodes d'autenticació, entre ells Breeze (bàsic), Fortify (avançat) i Sanctum (API). Aquest darrer és el què ens interessa.<br />
<br />
Sanctum té diversos mecanismes, depenent de qui utilitzarà la API (app mòbil, una web externa, etc.). Agafarem l'exemple de la APP MÒBIL.<br />
<br />
Consulta aquí la [https://laravel.com/docs/8.x/sanctum documentació de Laravel Sanctum].<br />
<br />
En definitiva, les diferents passes que cal seguir son:<br />
# '''Instal·lació''' de Sanctum (install, publish, migrate).<br />
# Anem a la [https://laravel.com/docs/8.x/sanctum#issuing-mobile-api-tokens secció per a generar tokens per a mòbils].<br />
#* Implementem el '''mètode d'autenticació''' mitjançant email i password a l'arxiu '''api.php'''. També cal passar-li el ''device_name'' que quedarà anotat junt al token.<br />
# Protegim rutes amb '''->middleware("auth:sanctum")''' , per exemple:<br />
#: <syntaxhighlight lang="php">Route::middleware('auth:sanctum')->get("/ping", function(Request $request) {<br />
// ...<br />
}<br />
</syntaxhighlight><br />
# Ara simularem la crida per '''demanar el token''' (la que posteriorment faríem des d'un mòbil)<br />
#: <pre>curl localhost:8000/api/sanctum/token -X POST -d 'email=jo@domini.com&password=enric123&device_name=LolaPhone55'</pre><br />
#: Prendre nota del TOKEN que se'ns retorna.<br />
# Crida URL per '''accedir a la API amb el Header Bearer''' necessari :<br />
#: <pre>curl localhost:8000/api/ping -H 'Authorization: Bearer lL0a21yHy4MzU4FdV5Cm0xZzd35AJ97acOOnW83t'</pre><br />
#: Si no posem el token adequadament se'ns redireccionarà a la pàgina principal amb un codi 302<br />
<br />
<br><br />
<br />
== Exemples de API: laravel-karaoke ==<br />
En el projecte karaoke en Laravel, el podeu veure aquí:<br />
* [https://github.com/emieza/laravel-karaoke/commit/8ab648decd6b58380545c60b135bad849a622d77 Versió amb el codi a api.php]. Es pot fer, però és una solució una mica "guarrilla"<br />
* [https://github.com/emieza/laravel-karaoke/blob/master/routes/api.php Versió amb el codi en un ''controller'']. Només veiem les rutes, però és raonable que no posem mogollón de codi aquí, sinó al [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php TemaController] en aquest cas.<br />
<br />
Recordem que per crear un controller amb Laravel ho fem amb (per exemple):<br />
$ php artisan make:controller ApiController<br />
<br />
Si mireu [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php TemaController] pareu atenció que per poder fer crides com <code>TemaController::fet($id)</code> , necessitem que siguin funcions estàtiques (static).<br />
<br />
Ara, per poder mirar el nº de vots, a '''routes/api.php''' tindrem:<br />
<syntaxhighlight lang="php"><br />
Route::get('/nvots/{id}', function(Request $request, $id) {<br />
return TemaController::nvots( $id );<br />
});<br />
</syntaxhighlight><br />
<br />
<br><br />
<br />
== Especificacions d'una API ==<br />
És molt important especificar adequadament una API per tal que la pugui fer servir molta gent.<br />
<br />
En l'exemple del karaoke tenim 3 crides, i les especificacions les indiquem amb quadres com els que mostrem a continuació:<br />
* /api/'''nvots'''/{tema_id}<br />
* /api/'''vota'''/{tema_id}<br />
* /api/'''fet'''/{tema_id}<br />
<br />
<br />
=== nvots ===<br />
Al ser una crida GET, els paràmetres han d'anar a la URL. Si fos POST, anirien afegits en el cos de la ''request'':<br />
<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L68 Veure codi del TemaController@nvots]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/nvots/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
Aquesta response retorna les dades en format '''JSON''', però podria tenir altres formats (XML, plain text):<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/nvots/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| nvots<br />
| integer<br />
| Total de vots per al tema<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema consultat<br />
|}<br />
<br />
Per exemple, per testejar-la:<br />
$ curl http://localhost:8000/api/nvots/1<br />
{"status":"OK","tema_id":"1","nvots":1}<br />
<br />
Per testejar l'exemple en producció, podeu provar (el -k és important perquè no demani els certificats HTTPS):<br />
$ curl https://jolgorio.tk/api/nvots/1 '''-k'''<br />
{"status":"OK","tema_id":"1","nvots":2}<br />
<br />
<br><br />
<br />
=== vota ===<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L112 Veure codi de TemaController@vota]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| vot<br />
| true / false<br />
| Estat actual del nostre vot de la nostra IP<br />
|-<br />
| nvots<br />
| integer<br />
| Total de vots per al tema<br />
|-<br />
| message<br />
| text<br />
| Missatge de text amb la descripció de l'error o acció<br />
|}<br />
<br />
<br><br />
<br />
=== fet ===<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L86 Veure codi de TemaController@fet]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| fet<br />
| true / false<br />
| Estat actual del tema (fet / no fet)<br />
|-<br />
| message<br />
| text<br />
| Missatge de text amb la descripció de l'error o acció<br />
|}<br />
<br />
<br></div>Enrichttps://cacauet.org/wiki/index.php?title=Serveis_web_amb_Laravel&diff=4239Serveis web amb Laravel2021-03-17T15:21:31Z<p>Enric: /* Autenticació API amb Laravel Sanctum */</p>
<hr />
<div>Per poder seguir amb normalitat aquest article cal haver llegit i treballat [[Laravel]].<br />
<br />
<br />
== Introducció ==<br />
Articles previs:<br />
* [[Serveis Web]]<br />
* [[Laravel]]<br />
<br />
Articles següents:<br />
* [[Serveis Web amb Opendata]]<br />
<br />
=== Perquè Laravel per a serveis web? ===<br />
No és imprescindible utilitzar [[Laravel]] per implementar un servei web. Ens és convenient pels següents motius:<br />
# En el curs de M7 de DAW estem treballant amb aquest framework i ens interessa aprofundir el seu coneixement.<br />
# Integrarem la part del ''frontend'' de la nostra web juntament amb la API que farem.<br />
# Laravel facilita l'accés a la base de dades a través del ORM Eloquent, que resulta molt útil.<br />
<br />
<br><br />
<br />
== Primera prova de la API ==<br />
Anem a implementar una primera prova de API en un projecte [[Laravel]] nou. Si et cal, crea'n un.<br />
<br />
Totes les funcions que vulguem implementar per al nostre sistema hem de començar per indicar-les al arxiu de rutes:<br />
routes/api.php<br />
<br />
De fet, les podríem implementar al mateix arxiu. Quan es compliquin, però, convindrà crear un controlador com vam fer al tutorial de [[Laravel]].<br />
<br />
Afegiu el següent codi a '''routes/api.php''':<br />
<syntaxhighlight lang="php"><br />
Route::get('/ping', function(Request $request) {<br />
return "pong! :)";<br />
});<br />
</syntaxhighlight><br />
<br />
Poseu en marxa el servidor i proveu la funció amb:<br />
$ curl localhost:8000/api/ping<br />
'''pong! :)'''super@HPi5-07:~/dev/laraveltest1$ <br />
<br />
Noteu que:<br />
* Encara que hem definit la ruta "/ping", per poder-la cridar hem de fer "/api/ping". Ve predefinit pel Laravel, tot i que no té perquè ser així.<br />
* Ens contesta el què hem posat al RETURN final<br />
* No retorna HTML, retorna un text que pot ser qualsevol cosa<br />
* No hi ha \n final (s'enganxa amb el ''prompt'' de la ''shell'')<br />
<br />
=== Headers en la crida ''curl'' ===<br />
Per veure els ''headers'' de retorn, podem utilitzar "-i", pot ser molt útil per depurar:<br />
$ curl -i localhost:8000/api/ping<br />
<br />
Obtindrem algo com:<br />
HTTP/1.1 200 OK<br />
Host: localhost:8000<br />
Date: Wed, 17 Mar 2021 15:13:14 GMT<br />
Connection: close<br />
X-Powered-By: PHP/7.4.9<br />
Content-Type: text/html; charset=UTF-8<br />
Cache-Control: no-cache, private<br />
Date: Wed, 17 Mar 2021 15:13:14 GMT<br />
X-RateLimit-Limit: 60<br />
X-RateLimit-Remaining: 59<br />
Access-Control-Allow-Origin: *<br />
<br />
pong! :)super@HPi5-07:~/dev/laraveltest1$ <br />
<br />
<br><br />
<br />
== Autenticació API amb Laravel Sanctum ==<br />
Des de fa algunes versions Laravel ha incorporat diversos mètodes d'autenticació, entre ells Breeze (bàsic), Fortify (avançat) i Sanctum (API). Aquest darrer és el què ens interessa.<br />
<br />
Sanctum té diversos mecanismes, depenent de qui utilitzarà la API (app mòbil, una web externa, etc.). Agafarem l'exemple de la APP MÒBIL.<br />
<br />
Consulta aquí la [https://laravel.com/docs/8.x/sanctum documentació de Laravel Sanctum].<br />
<br />
En definitiva, les diferents passes que cal seguir son:<br />
# '''Instal·lació''' de Sanctum (install, publish, migrate).<br />
# Anem a la [https://laravel.com/docs/8.x/sanctum#issuing-mobile-api-tokens secció per a generar tokens per a mòbils].<br />
#* Implementem el '''mètode d'autenticació''' mitjançant email i password a l'arxiu '''api.php'''. També cal passar-li el ''device_name'' que quedarà anotat junt al token.<br />
# Protegim rutes amb '''->middleware("auth:sanctum")''' , per exemple:<br />
#: <syntaxhighlight lang="php">Route::middleware('auth:sanctum')->get("/ping", function(Request $request) {<br />
// ...<br />
}<br />
</syntaxhighlight><br />
# Ara simularem la crida per '''demanar el token''' (la que posteriorment faríem des d'un mòbil)<br />
#: <pre>curl localhost:8000/api/sanctum/token -X POST -d 'email=jo@domini.com&password=enric123&device_name=LolaPhone55'</pre><br />
#: Prendre nota del TOKEN que se'ns retorna.<br />
# Crida URL per '''accedir a la API amb el Header Bearer''' necessari :<br />
#: <pre>curl localhost:8000/api/ping -H 'Authorization: Bearer lL0a21yHy4MzU4FdV5Cm0xZzd35AJ97acOOnW83t'</pre><br />
<br />
<br><br />
<br />
== Exemples de API: laravel-karaoke ==<br />
En el projecte karaoke en Laravel, el podeu veure aquí:<br />
* [https://github.com/emieza/laravel-karaoke/commit/8ab648decd6b58380545c60b135bad849a622d77 Versió amb el codi a api.php]. Es pot fer, però és una solució una mica "guarrilla"<br />
* [https://github.com/emieza/laravel-karaoke/blob/master/routes/api.php Versió amb el codi en un ''controller'']. Només veiem les rutes, però és raonable que no posem mogollón de codi aquí, sinó al [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php TemaController] en aquest cas.<br />
<br />
Recordem que per crear un controller amb Laravel ho fem amb (per exemple):<br />
$ php artisan make:controller ApiController<br />
<br />
Si mireu [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php TemaController] pareu atenció que per poder fer crides com <code>TemaController::fet($id)</code> , necessitem que siguin funcions estàtiques (static).<br />
<br />
Ara, per poder mirar el nº de vots, a '''routes/api.php''' tindrem:<br />
<syntaxhighlight lang="php"><br />
Route::get('/nvots/{id}', function(Request $request, $id) {<br />
return TemaController::nvots( $id );<br />
});<br />
</syntaxhighlight><br />
<br />
<br><br />
<br />
== Especificacions d'una API ==<br />
És molt important especificar adequadament una API per tal que la pugui fer servir molta gent.<br />
<br />
En l'exemple del karaoke tenim 3 crides, i les especificacions les indiquem amb quadres com els que mostrem a continuació:<br />
* /api/'''nvots'''/{tema_id}<br />
* /api/'''vota'''/{tema_id}<br />
* /api/'''fet'''/{tema_id}<br />
<br />
<br />
=== nvots ===<br />
Al ser una crida GET, els paràmetres han d'anar a la URL. Si fos POST, anirien afegits en el cos de la ''request'':<br />
<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L68 Veure codi del TemaController@nvots]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/nvots/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
Aquesta response retorna les dades en format '''JSON''', però podria tenir altres formats (XML, plain text):<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/nvots/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| nvots<br />
| integer<br />
| Total de vots per al tema<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema consultat<br />
|}<br />
<br />
Per exemple, per testejar-la:<br />
$ curl http://localhost:8000/api/nvots/1<br />
{"status":"OK","tema_id":"1","nvots":1}<br />
<br />
Per testejar l'exemple en producció, podeu provar (el -k és important perquè no demani els certificats HTTPS):<br />
$ curl https://jolgorio.tk/api/nvots/1 '''-k'''<br />
{"status":"OK","tema_id":"1","nvots":2}<br />
<br />
<br><br />
<br />
=== vota ===<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L112 Veure codi de TemaController@vota]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| vot<br />
| true / false<br />
| Estat actual del nostre vot de la nostra IP<br />
|-<br />
| nvots<br />
| integer<br />
| Total de vots per al tema<br />
|-<br />
| message<br />
| text<br />
| Missatge de text amb la descripció de l'error o acció<br />
|}<br />
<br />
<br><br />
<br />
=== fet ===<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L86 Veure codi de TemaController@fet]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| fet<br />
| true / false<br />
| Estat actual del tema (fet / no fet)<br />
|-<br />
| message<br />
| text<br />
| Missatge de text amb la descripció de l'error o acció<br />
|}<br />
<br />
<br></div>Enrichttps://cacauet.org/wiki/index.php?title=Serveis_web_amb_Laravel&diff=4238Serveis web amb Laravel2021-03-17T15:20:47Z<p>Enric: /* Autenticació API amb Laravel Sanctum */</p>
<hr />
<div>Per poder seguir amb normalitat aquest article cal haver llegit i treballat [[Laravel]].<br />
<br />
<br />
== Introducció ==<br />
Articles previs:<br />
* [[Serveis Web]]<br />
* [[Laravel]]<br />
<br />
Articles següents:<br />
* [[Serveis Web amb Opendata]]<br />
<br />
=== Perquè Laravel per a serveis web? ===<br />
No és imprescindible utilitzar [[Laravel]] per implementar un servei web. Ens és convenient pels següents motius:<br />
# En el curs de M7 de DAW estem treballant amb aquest framework i ens interessa aprofundir el seu coneixement.<br />
# Integrarem la part del ''frontend'' de la nostra web juntament amb la API que farem.<br />
# Laravel facilita l'accés a la base de dades a través del ORM Eloquent, que resulta molt útil.<br />
<br />
<br><br />
<br />
== Primera prova de la API ==<br />
Anem a implementar una primera prova de API en un projecte [[Laravel]] nou. Si et cal, crea'n un.<br />
<br />
Totes les funcions que vulguem implementar per al nostre sistema hem de començar per indicar-les al arxiu de rutes:<br />
routes/api.php<br />
<br />
De fet, les podríem implementar al mateix arxiu. Quan es compliquin, però, convindrà crear un controlador com vam fer al tutorial de [[Laravel]].<br />
<br />
Afegiu el següent codi a '''routes/api.php''':<br />
<syntaxhighlight lang="php"><br />
Route::get('/ping', function(Request $request) {<br />
return "pong! :)";<br />
});<br />
</syntaxhighlight><br />
<br />
Poseu en marxa el servidor i proveu la funció amb:<br />
$ curl localhost:8000/api/ping<br />
'''pong! :)'''super@HPi5-07:~/dev/laraveltest1$ <br />
<br />
Noteu que:<br />
* Encara que hem definit la ruta "/ping", per poder-la cridar hem de fer "/api/ping". Ve predefinit pel Laravel, tot i que no té perquè ser així.<br />
* Ens contesta el què hem posat al RETURN final<br />
* No retorna HTML, retorna un text que pot ser qualsevol cosa<br />
* No hi ha \n final (s'enganxa amb el ''prompt'' de la ''shell'')<br />
<br />
=== Headers en la crida ''curl'' ===<br />
Per veure els ''headers'' de retorn, podem utilitzar "-i", pot ser molt útil per depurar:<br />
$ curl -i localhost:8000/api/ping<br />
<br />
Obtindrem algo com:<br />
HTTP/1.1 200 OK<br />
Host: localhost:8000<br />
Date: Wed, 17 Mar 2021 15:13:14 GMT<br />
Connection: close<br />
X-Powered-By: PHP/7.4.9<br />
Content-Type: text/html; charset=UTF-8<br />
Cache-Control: no-cache, private<br />
Date: Wed, 17 Mar 2021 15:13:14 GMT<br />
X-RateLimit-Limit: 60<br />
X-RateLimit-Remaining: 59<br />
Access-Control-Allow-Origin: *<br />
<br />
pong! :)super@HPi5-07:~/dev/laraveltest1$ <br />
<br />
<br><br />
<br />
== Autenticació API amb Laravel Sanctum ==<br />
Des de fa algunes versions Laravel ha incorporat diversos mètodes d'autenticació, entre ells Breeze (bàsic), Fortify (avançat) i Sanctum (API). Aquest darrer és el què ens interessa.<br />
<br />
Sanctum té diversos mecanismes, depenent de qui utilitzarà la API (app mòbil, una web externa, etc.). Agafarem l'exemple de la APP MÒBIL.<br />
<br />
Consulta aquí la [https://laravel.com/docs/8.x/sanctum documentació de Laravel Sanctum].<br />
<br />
En definitiva, les diferents passes que cal seguir son:<br />
# '''Instal·lació''' de Sanctum (install, publish, migrate).<br />
# Anem a la [https://laravel.com/docs/8.x/sanctum#issuing-mobile-api-tokens secció per a generar tokens per a mòbils].<br />
#* Implementem el '''mètode d'autenticació''' mitjançant email i password a l'arxiu '''api.php'''. També cal passar-li el ''device_name'' que quedarà anotat junt al token.<br />
# Protegim rutes amb '''->middleware("auth:sanctum")''' , per exemple:<br />
#: <syntaxhighlight lang="php">Route::middleware('auth:sanctum')->get("/ping", function(Request $request) {<br />
// ...<br />
}<br />
</syntaxhighlight><br />
# Ara simularem la crida per '''demanar el token''' (la que posteriorment faríem des d'un mòbil)<br />
#: <pre>curl localhost:8000/api/sanctum/token -X POST -d 'email=jo@domini.com&password=enric123&device_name=LolaPhone55'</pre><br />
# Crida URL per '''accedir a la API amb el Header Bearer''' necessari :<br />
#: <pre>curl localhost:8000/api/ping -H 'Authorization: Bearer lL0a21yHy4MzU4FdV5Cm0xZzd35AJ97acOOnW83t'</pre><br />
<br />
<br><br />
<br />
== Exemples de API: laravel-karaoke ==<br />
En el projecte karaoke en Laravel, el podeu veure aquí:<br />
* [https://github.com/emieza/laravel-karaoke/commit/8ab648decd6b58380545c60b135bad849a622d77 Versió amb el codi a api.php]. Es pot fer, però és una solució una mica "guarrilla"<br />
* [https://github.com/emieza/laravel-karaoke/blob/master/routes/api.php Versió amb el codi en un ''controller'']. Només veiem les rutes, però és raonable que no posem mogollón de codi aquí, sinó al [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php TemaController] en aquest cas.<br />
<br />
Recordem que per crear un controller amb Laravel ho fem amb (per exemple):<br />
$ php artisan make:controller ApiController<br />
<br />
Si mireu [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php TemaController] pareu atenció que per poder fer crides com <code>TemaController::fet($id)</code> , necessitem que siguin funcions estàtiques (static).<br />
<br />
Ara, per poder mirar el nº de vots, a '''routes/api.php''' tindrem:<br />
<syntaxhighlight lang="php"><br />
Route::get('/nvots/{id}', function(Request $request, $id) {<br />
return TemaController::nvots( $id );<br />
});<br />
</syntaxhighlight><br />
<br />
<br><br />
<br />
== Especificacions d'una API ==<br />
És molt important especificar adequadament una API per tal que la pugui fer servir molta gent.<br />
<br />
En l'exemple del karaoke tenim 3 crides, i les especificacions les indiquem amb quadres com els que mostrem a continuació:<br />
* /api/'''nvots'''/{tema_id}<br />
* /api/'''vota'''/{tema_id}<br />
* /api/'''fet'''/{tema_id}<br />
<br />
<br />
=== nvots ===<br />
Al ser una crida GET, els paràmetres han d'anar a la URL. Si fos POST, anirien afegits en el cos de la ''request'':<br />
<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L68 Veure codi del TemaController@nvots]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/nvots/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
Aquesta response retorna les dades en format '''JSON''', però podria tenir altres formats (XML, plain text):<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/nvots/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| nvots<br />
| integer<br />
| Total de vots per al tema<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema consultat<br />
|}<br />
<br />
Per exemple, per testejar-la:<br />
$ curl http://localhost:8000/api/nvots/1<br />
{"status":"OK","tema_id":"1","nvots":1}<br />
<br />
Per testejar l'exemple en producció, podeu provar (el -k és important perquè no demani els certificats HTTPS):<br />
$ curl https://jolgorio.tk/api/nvots/1 '''-k'''<br />
{"status":"OK","tema_id":"1","nvots":2}<br />
<br />
<br><br />
<br />
=== vota ===<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L112 Veure codi de TemaController@vota]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| vot<br />
| true / false<br />
| Estat actual del nostre vot de la nostra IP<br />
|-<br />
| nvots<br />
| integer<br />
| Total de vots per al tema<br />
|-<br />
| message<br />
| text<br />
| Missatge de text amb la descripció de l'error o acció<br />
|}<br />
<br />
<br><br />
<br />
=== fet ===<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L86 Veure codi de TemaController@fet]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| fet<br />
| true / false<br />
| Estat actual del tema (fet / no fet)<br />
|-<br />
| message<br />
| text<br />
| Missatge de text amb la descripció de l'error o acció<br />
|}<br />
<br />
<br></div>Enrichttps://cacauet.org/wiki/index.php?title=Serveis_web_amb_Laravel&diff=4237Serveis web amb Laravel2021-03-17T15:20:23Z<p>Enric: /* Autenticació API amb Laravel Sanctum */</p>
<hr />
<div>Per poder seguir amb normalitat aquest article cal haver llegit i treballat [[Laravel]].<br />
<br />
<br />
== Introducció ==<br />
Articles previs:<br />
* [[Serveis Web]]<br />
* [[Laravel]]<br />
<br />
Articles següents:<br />
* [[Serveis Web amb Opendata]]<br />
<br />
=== Perquè Laravel per a serveis web? ===<br />
No és imprescindible utilitzar [[Laravel]] per implementar un servei web. Ens és convenient pels següents motius:<br />
# En el curs de M7 de DAW estem treballant amb aquest framework i ens interessa aprofundir el seu coneixement.<br />
# Integrarem la part del ''frontend'' de la nostra web juntament amb la API que farem.<br />
# Laravel facilita l'accés a la base de dades a través del ORM Eloquent, que resulta molt útil.<br />
<br />
<br><br />
<br />
== Primera prova de la API ==<br />
Anem a implementar una primera prova de API en un projecte [[Laravel]] nou. Si et cal, crea'n un.<br />
<br />
Totes les funcions que vulguem implementar per al nostre sistema hem de començar per indicar-les al arxiu de rutes:<br />
routes/api.php<br />
<br />
De fet, les podríem implementar al mateix arxiu. Quan es compliquin, però, convindrà crear un controlador com vam fer al tutorial de [[Laravel]].<br />
<br />
Afegiu el següent codi a '''routes/api.php''':<br />
<syntaxhighlight lang="php"><br />
Route::get('/ping', function(Request $request) {<br />
return "pong! :)";<br />
});<br />
</syntaxhighlight><br />
<br />
Poseu en marxa el servidor i proveu la funció amb:<br />
$ curl localhost:8000/api/ping<br />
'''pong! :)'''super@HPi5-07:~/dev/laraveltest1$ <br />
<br />
Noteu que:<br />
* Encara que hem definit la ruta "/ping", per poder-la cridar hem de fer "/api/ping". Ve predefinit pel Laravel, tot i que no té perquè ser així.<br />
* Ens contesta el què hem posat al RETURN final<br />
* No retorna HTML, retorna un text que pot ser qualsevol cosa<br />
* No hi ha \n final (s'enganxa amb el ''prompt'' de la ''shell'')<br />
<br />
=== Headers en la crida ''curl'' ===<br />
Per veure els ''headers'' de retorn, podem utilitzar "-i", pot ser molt útil per depurar:<br />
$ curl -i localhost:8000/api/ping<br />
<br />
Obtindrem algo com:<br />
HTTP/1.1 200 OK<br />
Host: localhost:8000<br />
Date: Wed, 17 Mar 2021 15:13:14 GMT<br />
Connection: close<br />
X-Powered-By: PHP/7.4.9<br />
Content-Type: text/html; charset=UTF-8<br />
Cache-Control: no-cache, private<br />
Date: Wed, 17 Mar 2021 15:13:14 GMT<br />
X-RateLimit-Limit: 60<br />
X-RateLimit-Remaining: 59<br />
Access-Control-Allow-Origin: *<br />
<br />
pong! :)super@HPi5-07:~/dev/laraveltest1$ <br />
<br />
<br><br />
<br />
== Autenticació API amb Laravel Sanctum ==<br />
Des de fa algunes versions Laravel ha incorporat diversos mètodes d'autenticació, entre ells Breeze (bàsic), Fortify (avançat) i Sanctum (API). Aquest darrer és el què ens interessa.<br />
<br />
Sanctum té diversos mecanismes, depenent de qui utilitzarà la API (app mòbil, una web externa, etc.). Agafarem l'exemple de la APP MÒBIL.<br />
<br />
Consulta aquí la [https://laravel.com/docs/8.x/sanctum documentació de Laravel Sanctum].<br />
<br />
En definitiva, les diferents passes que cal seguir son:<br />
# '''Instal·lació''' de Sanctum (install, publish, migrate).<br />
# Anem a la [https://laravel.com/docs/8.x/sanctum#issuing-mobile-api-tokens secció per a generar tokens per a mòbils].<br />
#* Implementem el '''mètode d'autenticació''' mitjançant email i password a l'arxiu '''api.php'''. També cal passar-li el ''device_name'' que quedarà anotat junt al token.<br />
# Protegim rutes amb '''->middleware("auth:sanctum")''' , per exemple:<br />
#: <syntaxhighlight lang="php">Route::middleware('auth:sanctum')->get("/ping", function(Request $request) {<br />
// ...<br />
}<br />
</syntaxhighlight><br />
# Ara simularem la crida per '''demanar el token''' (la que posteriorment faríem des d'un mòbil)<br />
#: <pre>curl localhost:8000/api/sanctum/token -X POST -d 'email=jo@domini.com&password=enric123&device_name=LolaPhone55'</pre><br />
# Crida URL per '''accedir a la API amb el Header Bearer''' necessari :<br />
#: <pre>curl localhost:8000/api/hola -H 'Authorization: Bearer lL0a21yHy4MzU4FdV5Cm0xZzd35AJ97acOOnW83t'</pre><br />
<br />
<br><br />
<br />
== Exemples de API: laravel-karaoke ==<br />
En el projecte karaoke en Laravel, el podeu veure aquí:<br />
* [https://github.com/emieza/laravel-karaoke/commit/8ab648decd6b58380545c60b135bad849a622d77 Versió amb el codi a api.php]. Es pot fer, però és una solució una mica "guarrilla"<br />
* [https://github.com/emieza/laravel-karaoke/blob/master/routes/api.php Versió amb el codi en un ''controller'']. Només veiem les rutes, però és raonable que no posem mogollón de codi aquí, sinó al [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php TemaController] en aquest cas.<br />
<br />
Recordem que per crear un controller amb Laravel ho fem amb (per exemple):<br />
$ php artisan make:controller ApiController<br />
<br />
Si mireu [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php TemaController] pareu atenció que per poder fer crides com <code>TemaController::fet($id)</code> , necessitem que siguin funcions estàtiques (static).<br />
<br />
Ara, per poder mirar el nº de vots, a '''routes/api.php''' tindrem:<br />
<syntaxhighlight lang="php"><br />
Route::get('/nvots/{id}', function(Request $request, $id) {<br />
return TemaController::nvots( $id );<br />
});<br />
</syntaxhighlight><br />
<br />
<br><br />
<br />
== Especificacions d'una API ==<br />
És molt important especificar adequadament una API per tal que la pugui fer servir molta gent.<br />
<br />
En l'exemple del karaoke tenim 3 crides, i les especificacions les indiquem amb quadres com els que mostrem a continuació:<br />
* /api/'''nvots'''/{tema_id}<br />
* /api/'''vota'''/{tema_id}<br />
* /api/'''fet'''/{tema_id}<br />
<br />
<br />
=== nvots ===<br />
Al ser una crida GET, els paràmetres han d'anar a la URL. Si fos POST, anirien afegits en el cos de la ''request'':<br />
<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L68 Veure codi del TemaController@nvots]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/nvots/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
Aquesta response retorna les dades en format '''JSON''', però podria tenir altres formats (XML, plain text):<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/nvots/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| nvots<br />
| integer<br />
| Total de vots per al tema<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema consultat<br />
|}<br />
<br />
Per exemple, per testejar-la:<br />
$ curl http://localhost:8000/api/nvots/1<br />
{"status":"OK","tema_id":"1","nvots":1}<br />
<br />
Per testejar l'exemple en producció, podeu provar (el -k és important perquè no demani els certificats HTTPS):<br />
$ curl https://jolgorio.tk/api/nvots/1 '''-k'''<br />
{"status":"OK","tema_id":"1","nvots":2}<br />
<br />
<br><br />
<br />
=== vota ===<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L112 Veure codi de TemaController@vota]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| vot<br />
| true / false<br />
| Estat actual del nostre vot de la nostra IP<br />
|-<br />
| nvots<br />
| integer<br />
| Total de vots per al tema<br />
|-<br />
| message<br />
| text<br />
| Missatge de text amb la descripció de l'error o acció<br />
|}<br />
<br />
<br><br />
<br />
=== fet ===<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L86 Veure codi de TemaController@fet]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| fet<br />
| true / false<br />
| Estat actual del tema (fet / no fet)<br />
|-<br />
| message<br />
| text<br />
| Missatge de text amb la descripció de l'error o acció<br />
|}<br />
<br />
<br></div>Enrichttps://cacauet.org/wiki/index.php?title=Serveis_web_amb_Laravel&diff=4236Serveis web amb Laravel2021-03-17T15:19:25Z<p>Enric: /* Autenticació API amb Laravel Sanctum */</p>
<hr />
<div>Per poder seguir amb normalitat aquest article cal haver llegit i treballat [[Laravel]].<br />
<br />
<br />
== Introducció ==<br />
Articles previs:<br />
* [[Serveis Web]]<br />
* [[Laravel]]<br />
<br />
Articles següents:<br />
* [[Serveis Web amb Opendata]]<br />
<br />
=== Perquè Laravel per a serveis web? ===<br />
No és imprescindible utilitzar [[Laravel]] per implementar un servei web. Ens és convenient pels següents motius:<br />
# En el curs de M7 de DAW estem treballant amb aquest framework i ens interessa aprofundir el seu coneixement.<br />
# Integrarem la part del ''frontend'' de la nostra web juntament amb la API que farem.<br />
# Laravel facilita l'accés a la base de dades a través del ORM Eloquent, que resulta molt útil.<br />
<br />
<br><br />
<br />
== Primera prova de la API ==<br />
Anem a implementar una primera prova de API en un projecte [[Laravel]] nou. Si et cal, crea'n un.<br />
<br />
Totes les funcions que vulguem implementar per al nostre sistema hem de començar per indicar-les al arxiu de rutes:<br />
routes/api.php<br />
<br />
De fet, les podríem implementar al mateix arxiu. Quan es compliquin, però, convindrà crear un controlador com vam fer al tutorial de [[Laravel]].<br />
<br />
Afegiu el següent codi a '''routes/api.php''':<br />
<syntaxhighlight lang="php"><br />
Route::get('/ping', function(Request $request) {<br />
return "pong! :)";<br />
});<br />
</syntaxhighlight><br />
<br />
Poseu en marxa el servidor i proveu la funció amb:<br />
$ curl localhost:8000/api/ping<br />
'''pong! :)'''super@HPi5-07:~/dev/laraveltest1$ <br />
<br />
Noteu que:<br />
* Encara que hem definit la ruta "/ping", per poder-la cridar hem de fer "/api/ping". Ve predefinit pel Laravel, tot i que no té perquè ser així.<br />
* Ens contesta el què hem posat al RETURN final<br />
* No retorna HTML, retorna un text que pot ser qualsevol cosa<br />
* No hi ha \n final (s'enganxa amb el ''prompt'' de la ''shell'')<br />
<br />
=== Headers en la crida ''curl'' ===<br />
Per veure els ''headers'' de retorn, podem utilitzar "-i", pot ser molt útil per depurar:<br />
$ curl -i localhost:8000/api/ping<br />
<br />
Obtindrem algo com:<br />
HTTP/1.1 200 OK<br />
Host: localhost:8000<br />
Date: Wed, 17 Mar 2021 15:13:14 GMT<br />
Connection: close<br />
X-Powered-By: PHP/7.4.9<br />
Content-Type: text/html; charset=UTF-8<br />
Cache-Control: no-cache, private<br />
Date: Wed, 17 Mar 2021 15:13:14 GMT<br />
X-RateLimit-Limit: 60<br />
X-RateLimit-Remaining: 59<br />
Access-Control-Allow-Origin: *<br />
<br />
pong! :)super@HPi5-07:~/dev/laraveltest1$ <br />
<br />
<br><br />
<br />
== Autenticació API amb Laravel Sanctum ==<br />
Des de fa algunes versions Laravel ha incorporat diversos mètodes d'autenticació, entre ells Breeze (bàsic), Fortify (avançat) i Sanctum (API). Aquest darrer és el què ens interessa.<br />
<br />
Sanctum té diversos mecanismes, depenent de qui utilitzarà la API (app mòbil, una web externa, etc.). Agafarem l'exemple de la APP MÒBIL.<br />
<br />
Consulta aquí la [https://laravel.com/docs/8.x/sanctum documentació de Laravel Sanctum].<br />
<br />
En definitiva, les diferents passes que cal seguir son:<br />
# '''Instal·lació''' de Sanctum (install, publish, migrate).<br />
# Anem a la [https://laravel.com/docs/8.x/sanctum#issuing-mobile-api-tokens secció per a generar tokens per a mòbils].<br />
#* Implementem el '''mètode d'autenticació''' mitjançant email i password a l'arxiu '''api.php'''. També cal passar-li el ''device_name'' que quedarà anotat junt al token.<br />
# Protegim rutes amb '''->middleware("auth:sanctum")''' , per exemple:<br />
#: <syntaxhighlight lang="php">Route::middleware('auth:sanctum')->get("/ping", function(Request $request) {<br />
// ...<br />
}<br />
</syntaxhighlight><br />
# Ara simularem la crida per demanar el token (la que posteriorment faríem des d'un mòbil)<br />
#: <pre>curl localhost:8000/api/sanctum/token -X POST -d 'email=jo@domini.com&password=enric123&device_name=LolaPhone55'</pre><br />
# Crida URL per <br />
#: <pre>curl localhost:8000/api/hola -H 'Authorization: Bearer lL0a21yHy4MzU4FdV5Cm0xZzd35AJ97acOOnW83t'</pre><br />
<br />
<br><br />
<br />
== Exemples de API: laravel-karaoke ==<br />
En el projecte karaoke en Laravel, el podeu veure aquí:<br />
* [https://github.com/emieza/laravel-karaoke/commit/8ab648decd6b58380545c60b135bad849a622d77 Versió amb el codi a api.php]. Es pot fer, però és una solució una mica "guarrilla"<br />
* [https://github.com/emieza/laravel-karaoke/blob/master/routes/api.php Versió amb el codi en un ''controller'']. Només veiem les rutes, però és raonable que no posem mogollón de codi aquí, sinó al [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php TemaController] en aquest cas.<br />
<br />
Recordem que per crear un controller amb Laravel ho fem amb (per exemple):<br />
$ php artisan make:controller ApiController<br />
<br />
Si mireu [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php TemaController] pareu atenció que per poder fer crides com <code>TemaController::fet($id)</code> , necessitem que siguin funcions estàtiques (static).<br />
<br />
Ara, per poder mirar el nº de vots, a '''routes/api.php''' tindrem:<br />
<syntaxhighlight lang="php"><br />
Route::get('/nvots/{id}', function(Request $request, $id) {<br />
return TemaController::nvots( $id );<br />
});<br />
</syntaxhighlight><br />
<br />
<br><br />
<br />
== Especificacions d'una API ==<br />
És molt important especificar adequadament una API per tal que la pugui fer servir molta gent.<br />
<br />
En l'exemple del karaoke tenim 3 crides, i les especificacions les indiquem amb quadres com els que mostrem a continuació:<br />
* /api/'''nvots'''/{tema_id}<br />
* /api/'''vota'''/{tema_id}<br />
* /api/'''fet'''/{tema_id}<br />
<br />
<br />
=== nvots ===<br />
Al ser una crida GET, els paràmetres han d'anar a la URL. Si fos POST, anirien afegits en el cos de la ''request'':<br />
<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L68 Veure codi del TemaController@nvots]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/nvots/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
Aquesta response retorna les dades en format '''JSON''', però podria tenir altres formats (XML, plain text):<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/nvots/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| nvots<br />
| integer<br />
| Total de vots per al tema<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema consultat<br />
|}<br />
<br />
Per exemple, per testejar-la:<br />
$ curl http://localhost:8000/api/nvots/1<br />
{"status":"OK","tema_id":"1","nvots":1}<br />
<br />
Per testejar l'exemple en producció, podeu provar (el -k és important perquè no demani els certificats HTTPS):<br />
$ curl https://jolgorio.tk/api/nvots/1 '''-k'''<br />
{"status":"OK","tema_id":"1","nvots":2}<br />
<br />
<br><br />
<br />
=== vota ===<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L112 Veure codi de TemaController@vota]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| vot<br />
| true / false<br />
| Estat actual del nostre vot de la nostra IP<br />
|-<br />
| nvots<br />
| integer<br />
| Total de vots per al tema<br />
|-<br />
| message<br />
| text<br />
| Missatge de text amb la descripció de l'error o acció<br />
|}<br />
<br />
<br><br />
<br />
=== fet ===<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L86 Veure codi de TemaController@fet]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| fet<br />
| true / false<br />
| Estat actual del tema (fet / no fet)<br />
|-<br />
| message<br />
| text<br />
| Missatge de text amb la descripció de l'error o acció<br />
|}<br />
<br />
<br></div>Enrichttps://cacauet.org/wiki/index.php?title=Serveis_web_amb_Laravel&diff=4235Serveis web amb Laravel2021-03-17T15:18:44Z<p>Enric: /* Autenticació API amb Laravel Sanctum */</p>
<hr />
<div>Per poder seguir amb normalitat aquest article cal haver llegit i treballat [[Laravel]].<br />
<br />
<br />
== Introducció ==<br />
Articles previs:<br />
* [[Serveis Web]]<br />
* [[Laravel]]<br />
<br />
Articles següents:<br />
* [[Serveis Web amb Opendata]]<br />
<br />
=== Perquè Laravel per a serveis web? ===<br />
No és imprescindible utilitzar [[Laravel]] per implementar un servei web. Ens és convenient pels següents motius:<br />
# En el curs de M7 de DAW estem treballant amb aquest framework i ens interessa aprofundir el seu coneixement.<br />
# Integrarem la part del ''frontend'' de la nostra web juntament amb la API que farem.<br />
# Laravel facilita l'accés a la base de dades a través del ORM Eloquent, que resulta molt útil.<br />
<br />
<br><br />
<br />
== Primera prova de la API ==<br />
Anem a implementar una primera prova de API en un projecte [[Laravel]] nou. Si et cal, crea'n un.<br />
<br />
Totes les funcions que vulguem implementar per al nostre sistema hem de començar per indicar-les al arxiu de rutes:<br />
routes/api.php<br />
<br />
De fet, les podríem implementar al mateix arxiu. Quan es compliquin, però, convindrà crear un controlador com vam fer al tutorial de [[Laravel]].<br />
<br />
Afegiu el següent codi a '''routes/api.php''':<br />
<syntaxhighlight lang="php"><br />
Route::get('/ping', function(Request $request) {<br />
return "pong! :)";<br />
});<br />
</syntaxhighlight><br />
<br />
Poseu en marxa el servidor i proveu la funció amb:<br />
$ curl localhost:8000/api/ping<br />
'''pong! :)'''super@HPi5-07:~/dev/laraveltest1$ <br />
<br />
Noteu que:<br />
* Encara que hem definit la ruta "/ping", per poder-la cridar hem de fer "/api/ping". Ve predefinit pel Laravel, tot i que no té perquè ser així.<br />
* Ens contesta el què hem posat al RETURN final<br />
* No retorna HTML, retorna un text que pot ser qualsevol cosa<br />
* No hi ha \n final (s'enganxa amb el ''prompt'' de la ''shell'')<br />
<br />
=== Headers en la crida ''curl'' ===<br />
Per veure els ''headers'' de retorn, podem utilitzar "-i", pot ser molt útil per depurar:<br />
$ curl -i localhost:8000/api/ping<br />
<br />
Obtindrem algo com:<br />
HTTP/1.1 200 OK<br />
Host: localhost:8000<br />
Date: Wed, 17 Mar 2021 15:13:14 GMT<br />
Connection: close<br />
X-Powered-By: PHP/7.4.9<br />
Content-Type: text/html; charset=UTF-8<br />
Cache-Control: no-cache, private<br />
Date: Wed, 17 Mar 2021 15:13:14 GMT<br />
X-RateLimit-Limit: 60<br />
X-RateLimit-Remaining: 59<br />
Access-Control-Allow-Origin: *<br />
<br />
pong! :)super@HPi5-07:~/dev/laraveltest1$ <br />
<br />
<br><br />
<br />
== Autenticació API amb Laravel Sanctum ==<br />
Des de fa algunes versions Laravel ha incorporat diversos mètodes d'autenticació, entre ells Breeze (bàsic), Fortify (avançat) i Sanctum (API). Aquest darrer és el què ens interessa.<br />
<br />
Sanctum té diversos mecanismes, depenent de qui utilitzarà la API (app mòbil, una web externa, etc.). Agafarem l'exemple de la APP MÒBIL.<br />
<br />
Consulta aquí la [https://laravel.com/docs/8.x/sanctum documentació de Laravel Sanctum].<br />
<br />
En definitiva, les diferents passes que cal seguir son:<br />
# '''Instal·lació''' de Sanctum (install, publish, migrate).<br />
# Anem a la [https://laravel.com/docs/8.x/sanctum#issuing-mobile-api-tokens secció per a generar tokens per a mòbils].<br />
#* Implementem el '''mètode d'autenticació''' mitjançant email i password. També cal passar-li el ''device_name'' que quedarà anotat junt al token.<br />
# Protegim rutes amb '''->middleware("auth:sanctum")''' , per exemple:<br />
#: <syntaxhighlight lang="php">Route::middleware('auth:sanctum')->get("/ping", function(Request $request) {<br />
// ...<br />
}<br />
</syntaxhighlight><br />
# Ara simularem la crida per demanar el token (la que posteriorment faríem des d'un mòbil)<br />
#: <pre>curl localhost:8000/api/sanctum/token -X POST -d 'email=jo@domini.com&password=enric123&device_name=LolaPhone55'</pre><br />
# Crida URL per <br />
#: <pre>curl localhost:8000/api/hola -H 'Authorization: Bearer lL0a21yHy4MzU4FdV5Cm0xZzd35AJ97acOOnW83t'</pre><br />
<br />
<br><br />
<br />
== Exemples de API: laravel-karaoke ==<br />
En el projecte karaoke en Laravel, el podeu veure aquí:<br />
* [https://github.com/emieza/laravel-karaoke/commit/8ab648decd6b58380545c60b135bad849a622d77 Versió amb el codi a api.php]. Es pot fer, però és una solució una mica "guarrilla"<br />
* [https://github.com/emieza/laravel-karaoke/blob/master/routes/api.php Versió amb el codi en un ''controller'']. Només veiem les rutes, però és raonable que no posem mogollón de codi aquí, sinó al [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php TemaController] en aquest cas.<br />
<br />
Recordem que per crear un controller amb Laravel ho fem amb (per exemple):<br />
$ php artisan make:controller ApiController<br />
<br />
Si mireu [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php TemaController] pareu atenció que per poder fer crides com <code>TemaController::fet($id)</code> , necessitem que siguin funcions estàtiques (static).<br />
<br />
Ara, per poder mirar el nº de vots, a '''routes/api.php''' tindrem:<br />
<syntaxhighlight lang="php"><br />
Route::get('/nvots/{id}', function(Request $request, $id) {<br />
return TemaController::nvots( $id );<br />
});<br />
</syntaxhighlight><br />
<br />
<br><br />
<br />
== Especificacions d'una API ==<br />
És molt important especificar adequadament una API per tal que la pugui fer servir molta gent.<br />
<br />
En l'exemple del karaoke tenim 3 crides, i les especificacions les indiquem amb quadres com els que mostrem a continuació:<br />
* /api/'''nvots'''/{tema_id}<br />
* /api/'''vota'''/{tema_id}<br />
* /api/'''fet'''/{tema_id}<br />
<br />
<br />
=== nvots ===<br />
Al ser una crida GET, els paràmetres han d'anar a la URL. Si fos POST, anirien afegits en el cos de la ''request'':<br />
<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L68 Veure codi del TemaController@nvots]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/nvots/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
Aquesta response retorna les dades en format '''JSON''', però podria tenir altres formats (XML, plain text):<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/nvots/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| nvots<br />
| integer<br />
| Total de vots per al tema<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema consultat<br />
|}<br />
<br />
Per exemple, per testejar-la:<br />
$ curl http://localhost:8000/api/nvots/1<br />
{"status":"OK","tema_id":"1","nvots":1}<br />
<br />
Per testejar l'exemple en producció, podeu provar (el -k és important perquè no demani els certificats HTTPS):<br />
$ curl https://jolgorio.tk/api/nvots/1 '''-k'''<br />
{"status":"OK","tema_id":"1","nvots":2}<br />
<br />
<br><br />
<br />
=== vota ===<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L112 Veure codi de TemaController@vota]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| vot<br />
| true / false<br />
| Estat actual del nostre vot de la nostra IP<br />
|-<br />
| nvots<br />
| integer<br />
| Total de vots per al tema<br />
|-<br />
| message<br />
| text<br />
| Missatge de text amb la descripció de l'error o acció<br />
|}<br />
<br />
<br><br />
<br />
=== fet ===<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L86 Veure codi de TemaController@fet]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| fet<br />
| true / false<br />
| Estat actual del tema (fet / no fet)<br />
|-<br />
| message<br />
| text<br />
| Missatge de text amb la descripció de l'error o acció<br />
|}<br />
<br />
<br></div>Enrichttps://cacauet.org/wiki/index.php?title=Serveis_web_amb_Laravel&diff=4234Serveis web amb Laravel2021-03-17T15:17:48Z<p>Enric: /* Autenticació API amb Laravel Sanctum */</p>
<hr />
<div>Per poder seguir amb normalitat aquest article cal haver llegit i treballat [[Laravel]].<br />
<br />
<br />
== Introducció ==<br />
Articles previs:<br />
* [[Serveis Web]]<br />
* [[Laravel]]<br />
<br />
Articles següents:<br />
* [[Serveis Web amb Opendata]]<br />
<br />
=== Perquè Laravel per a serveis web? ===<br />
No és imprescindible utilitzar [[Laravel]] per implementar un servei web. Ens és convenient pels següents motius:<br />
# En el curs de M7 de DAW estem treballant amb aquest framework i ens interessa aprofundir el seu coneixement.<br />
# Integrarem la part del ''frontend'' de la nostra web juntament amb la API que farem.<br />
# Laravel facilita l'accés a la base de dades a través del ORM Eloquent, que resulta molt útil.<br />
<br />
<br><br />
<br />
== Primera prova de la API ==<br />
Anem a implementar una primera prova de API en un projecte [[Laravel]] nou. Si et cal, crea'n un.<br />
<br />
Totes les funcions que vulguem implementar per al nostre sistema hem de començar per indicar-les al arxiu de rutes:<br />
routes/api.php<br />
<br />
De fet, les podríem implementar al mateix arxiu. Quan es compliquin, però, convindrà crear un controlador com vam fer al tutorial de [[Laravel]].<br />
<br />
Afegiu el següent codi a '''routes/api.php''':<br />
<syntaxhighlight lang="php"><br />
Route::get('/ping', function(Request $request) {<br />
return "pong! :)";<br />
});<br />
</syntaxhighlight><br />
<br />
Poseu en marxa el servidor i proveu la funció amb:<br />
$ curl localhost:8000/api/ping<br />
'''pong! :)'''super@HPi5-07:~/dev/laraveltest1$ <br />
<br />
Noteu que:<br />
* Encara que hem definit la ruta "/ping", per poder-la cridar hem de fer "/api/ping". Ve predefinit pel Laravel, tot i que no té perquè ser així.<br />
* Ens contesta el què hem posat al RETURN final<br />
* No retorna HTML, retorna un text que pot ser qualsevol cosa<br />
* No hi ha \n final (s'enganxa amb el ''prompt'' de la ''shell'')<br />
<br />
=== Headers en la crida ''curl'' ===<br />
Per veure els ''headers'' de retorn, podem utilitzar "-i", pot ser molt útil per depurar:<br />
$ curl -i localhost:8000/api/ping<br />
<br />
Obtindrem algo com:<br />
HTTP/1.1 200 OK<br />
Host: localhost:8000<br />
Date: Wed, 17 Mar 2021 15:13:14 GMT<br />
Connection: close<br />
X-Powered-By: PHP/7.4.9<br />
Content-Type: text/html; charset=UTF-8<br />
Cache-Control: no-cache, private<br />
Date: Wed, 17 Mar 2021 15:13:14 GMT<br />
X-RateLimit-Limit: 60<br />
X-RateLimit-Remaining: 59<br />
Access-Control-Allow-Origin: *<br />
<br />
pong! :)super@HPi5-07:~/dev/laraveltest1$ <br />
<br />
<br><br />
<br />
== Autenticació API amb Laravel Sanctum ==<br />
Des de fa algunes versions Laravel ha incorporat diversos mètodes d'autenticació, entre ells Breeze (bàsic), Fortify (avançat) i Sanctum (API). Aquest darrer és el què ens interessa.<br />
<br />
Sanctum té diversos mecanismes, depenent de qui utilitzarà la API (app mòbil, una web externa, etc.). Agafarem l'exemple de la APP MÒBIL.<br />
<br />
Consulta aquí la [https://laravel.com/docs/8.x/sanctum documentació de Laravel Sanctum].<br />
<br />
En definitiva, les diferents passes que cal seguir son:<br />
# '''Instal·lació''' de Sanctum (install, publish, migrate).<br />
# Anem a la [https://laravel.com/docs/8.x/sanctum#issuing-mobile-api-tokens secció per a generar tokens per a mòbils].<br />
#* Implementem el mètode per a autenticació mitjançant email i password. També cal passar-li el ''device_name'' que quedarà anotat junt al token.<br />
# Protegim rutes amb '''->middleware("auth:sanctum")''' , per exemple:<br />
#: <syntaxhighlight lang="php">Route::middleware('auth:sanctum')->get("/ping", function(Request $request) {<br />
// ...<br />
}<br />
</syntaxhighlight><br />
# Ara simularem la crida per demanar el token (la que posteriorment faríem des d'un mòbil)<br />
#: <pre>curl localhost:8000/api/sanctum/token -X POST -d 'email=jo@domini.com&password=enric123&device_name=LolaPhone55'</pre><br />
# Crida URL per <br />
#: <pre>curl localhost:8000/api/hola -H 'Authorization: Bearer lL0a21yHy4MzU4FdV5Cm0xZzd35AJ97acOOnW83t'</pre><br />
<br />
== Exemples de API: laravel-karaoke ==<br />
En el projecte karaoke en Laravel, el podeu veure aquí:<br />
* [https://github.com/emieza/laravel-karaoke/commit/8ab648decd6b58380545c60b135bad849a622d77 Versió amb el codi a api.php]. Es pot fer, però és una solució una mica "guarrilla"<br />
* [https://github.com/emieza/laravel-karaoke/blob/master/routes/api.php Versió amb el codi en un ''controller'']. Només veiem les rutes, però és raonable que no posem mogollón de codi aquí, sinó al [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php TemaController] en aquest cas.<br />
<br />
Recordem que per crear un controller amb Laravel ho fem amb (per exemple):<br />
$ php artisan make:controller ApiController<br />
<br />
Si mireu [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php TemaController] pareu atenció que per poder fer crides com <code>TemaController::fet($id)</code> , necessitem que siguin funcions estàtiques (static).<br />
<br />
Ara, per poder mirar el nº de vots, a '''routes/api.php''' tindrem:<br />
<syntaxhighlight lang="php"><br />
Route::get('/nvots/{id}', function(Request $request, $id) {<br />
return TemaController::nvots( $id );<br />
});<br />
</syntaxhighlight><br />
<br />
<br><br />
<br />
== Especificacions d'una API ==<br />
És molt important especificar adequadament una API per tal que la pugui fer servir molta gent.<br />
<br />
En l'exemple del karaoke tenim 3 crides, i les especificacions les indiquem amb quadres com els que mostrem a continuació:<br />
* /api/'''nvots'''/{tema_id}<br />
* /api/'''vota'''/{tema_id}<br />
* /api/'''fet'''/{tema_id}<br />
<br />
<br />
=== nvots ===<br />
Al ser una crida GET, els paràmetres han d'anar a la URL. Si fos POST, anirien afegits en el cos de la ''request'':<br />
<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L68 Veure codi del TemaController@nvots]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/nvots/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
Aquesta response retorna les dades en format '''JSON''', però podria tenir altres formats (XML, plain text):<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/nvots/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| nvots<br />
| integer<br />
| Total de vots per al tema<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema consultat<br />
|}<br />
<br />
Per exemple, per testejar-la:<br />
$ curl http://localhost:8000/api/nvots/1<br />
{"status":"OK","tema_id":"1","nvots":1}<br />
<br />
Per testejar l'exemple en producció, podeu provar (el -k és important perquè no demani els certificats HTTPS):<br />
$ curl https://jolgorio.tk/api/nvots/1 '''-k'''<br />
{"status":"OK","tema_id":"1","nvots":2}<br />
<br />
<br><br />
<br />
=== vota ===<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L112 Veure codi de TemaController@vota]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| vot<br />
| true / false<br />
| Estat actual del nostre vot de la nostra IP<br />
|-<br />
| nvots<br />
| integer<br />
| Total de vots per al tema<br />
|-<br />
| message<br />
| text<br />
| Missatge de text amb la descripció de l'error o acció<br />
|}<br />
<br />
<br><br />
<br />
=== fet ===<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L86 Veure codi de TemaController@fet]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| fet<br />
| true / false<br />
| Estat actual del tema (fet / no fet)<br />
|-<br />
| message<br />
| text<br />
| Missatge de text amb la descripció de l'error o acció<br />
|}<br />
<br />
<br></div>Enrichttps://cacauet.org/wiki/index.php?title=Serveis_web_amb_Laravel&diff=4233Serveis web amb Laravel2021-03-17T15:16:37Z<p>Enric: /* Autenticació API amb Laravel Sanctum */</p>
<hr />
<div>Per poder seguir amb normalitat aquest article cal haver llegit i treballat [[Laravel]].<br />
<br />
<br />
== Introducció ==<br />
Articles previs:<br />
* [[Serveis Web]]<br />
* [[Laravel]]<br />
<br />
Articles següents:<br />
* [[Serveis Web amb Opendata]]<br />
<br />
=== Perquè Laravel per a serveis web? ===<br />
No és imprescindible utilitzar [[Laravel]] per implementar un servei web. Ens és convenient pels següents motius:<br />
# En el curs de M7 de DAW estem treballant amb aquest framework i ens interessa aprofundir el seu coneixement.<br />
# Integrarem la part del ''frontend'' de la nostra web juntament amb la API que farem.<br />
# Laravel facilita l'accés a la base de dades a través del ORM Eloquent, que resulta molt útil.<br />
<br />
<br><br />
<br />
== Primera prova de la API ==<br />
Anem a implementar una primera prova de API en un projecte [[Laravel]] nou. Si et cal, crea'n un.<br />
<br />
Totes les funcions que vulguem implementar per al nostre sistema hem de començar per indicar-les al arxiu de rutes:<br />
routes/api.php<br />
<br />
De fet, les podríem implementar al mateix arxiu. Quan es compliquin, però, convindrà crear un controlador com vam fer al tutorial de [[Laravel]].<br />
<br />
Afegiu el següent codi a '''routes/api.php''':<br />
<syntaxhighlight lang="php"><br />
Route::get('/ping', function(Request $request) {<br />
return "pong! :)";<br />
});<br />
</syntaxhighlight><br />
<br />
Poseu en marxa el servidor i proveu la funció amb:<br />
$ curl localhost:8000/api/ping<br />
'''pong! :)'''super@HPi5-07:~/dev/laraveltest1$ <br />
<br />
Noteu que:<br />
* Encara que hem definit la ruta "/ping", per poder-la cridar hem de fer "/api/ping". Ve predefinit pel Laravel, tot i que no té perquè ser així.<br />
* Ens contesta el què hem posat al RETURN final<br />
* No retorna HTML, retorna un text que pot ser qualsevol cosa<br />
* No hi ha \n final (s'enganxa amb el ''prompt'' de la ''shell'')<br />
<br />
=== Headers en la crida ''curl'' ===<br />
Per veure els ''headers'' de retorn, podem utilitzar "-i", pot ser molt útil per depurar:<br />
$ curl -i localhost:8000/api/ping<br />
<br />
Obtindrem algo com:<br />
HTTP/1.1 200 OK<br />
Host: localhost:8000<br />
Date: Wed, 17 Mar 2021 15:13:14 GMT<br />
Connection: close<br />
X-Powered-By: PHP/7.4.9<br />
Content-Type: text/html; charset=UTF-8<br />
Cache-Control: no-cache, private<br />
Date: Wed, 17 Mar 2021 15:13:14 GMT<br />
X-RateLimit-Limit: 60<br />
X-RateLimit-Remaining: 59<br />
Access-Control-Allow-Origin: *<br />
<br />
pong! :)super@HPi5-07:~/dev/laraveltest1$ <br />
<br />
<br><br />
<br />
== Autenticació API amb Laravel Sanctum ==<br />
Des de fa algunes versions Laravel ha incorporat diversos mètodes d'autenticació, entre ells Breeze (bàsic), Fortify (avançat) i Sanctum (API). Aquest darrer és el què ens interessa.<br />
<br />
Sanctum té diversos mecanismes, depenent de qui utilitzarà la API (app mòbil, una web externa, etc.). Agafarem l'exemple de la APP MÒBIL.<br />
<br />
Consulta aquí la [https://laravel.com/docs/8.x/sanctum documentació de Laravel Sanctum].<br />
<br />
En definitiva, les diferents passes que cal seguir son:<br />
# '''Instal·lació''' de Sanctum (install, publish, migrate).<br />
# Anem a la [https://laravel.com/docs/8.x/sanctum#issuing-mobile-api-tokens secció per a generar tokens per a mòbils].<br />
#* Implementem el mètode per a autenticació mitjançant email i password. També cal passar-li el ''device_name'' que quedarà anotat junt al token.<br />
# Protegim rutes amb '''->middleware("auth:sanctum")''' , per exemple:<br />
#: <syntaxhighlight lang="php">Route::middleware('auth:sanctum')->get("/ping", function(Request $request) { ...</syntaxhighight><br />
# Ara simularem la crida per demanar el token (la que posteriorment faríem des d'un mòbil)<br />
#: <pre>curl localhost:8000/api/sanctum/token -X POST -d 'email=jo@domini.com&password=enric123&device_name=LolaPhone55'</pre><br />
# Crida URL per <br />
#: <pre>curl localhost:8000/api/hola -H 'Authorization: Bearer lL0a21yHy4MzU4FdV5Cm0xZzd35AJ97acOOnW83t'</pre><br />
<br />
== Exemples de API: laravel-karaoke ==<br />
En el projecte karaoke en Laravel, el podeu veure aquí:<br />
* [https://github.com/emieza/laravel-karaoke/commit/8ab648decd6b58380545c60b135bad849a622d77 Versió amb el codi a api.php]. Es pot fer, però és una solució una mica "guarrilla"<br />
* [https://github.com/emieza/laravel-karaoke/blob/master/routes/api.php Versió amb el codi en un ''controller'']. Només veiem les rutes, però és raonable que no posem mogollón de codi aquí, sinó al [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php TemaController] en aquest cas.<br />
<br />
Recordem que per crear un controller amb Laravel ho fem amb (per exemple):<br />
$ php artisan make:controller ApiController<br />
<br />
Si mireu [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php TemaController] pareu atenció que per poder fer crides com <code>TemaController::fet($id)</code> , necessitem que siguin funcions estàtiques (static).<br />
<br />
Ara, per poder mirar el nº de vots, a '''routes/api.php''' tindrem:<br />
<syntaxhighlight lang="php"><br />
Route::get('/nvots/{id}', function(Request $request, $id) {<br />
return TemaController::nvots( $id );<br />
});<br />
</syntaxhighlight><br />
<br />
<br><br />
<br />
== Especificacions d'una API ==<br />
És molt important especificar adequadament una API per tal que la pugui fer servir molta gent.<br />
<br />
En l'exemple del karaoke tenim 3 crides, i les especificacions les indiquem amb quadres com els que mostrem a continuació:<br />
* /api/'''nvots'''/{tema_id}<br />
* /api/'''vota'''/{tema_id}<br />
* /api/'''fet'''/{tema_id}<br />
<br />
<br />
=== nvots ===<br />
Al ser una crida GET, els paràmetres han d'anar a la URL. Si fos POST, anirien afegits en el cos de la ''request'':<br />
<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L68 Veure codi del TemaController@nvots]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/nvots/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
Aquesta response retorna les dades en format '''JSON''', però podria tenir altres formats (XML, plain text):<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/nvots/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| nvots<br />
| integer<br />
| Total de vots per al tema<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema consultat<br />
|}<br />
<br />
Per exemple, per testejar-la:<br />
$ curl http://localhost:8000/api/nvots/1<br />
{"status":"OK","tema_id":"1","nvots":1}<br />
<br />
Per testejar l'exemple en producció, podeu provar (el -k és important perquè no demani els certificats HTTPS):<br />
$ curl https://jolgorio.tk/api/nvots/1 '''-k'''<br />
{"status":"OK","tema_id":"1","nvots":2}<br />
<br />
<br><br />
<br />
=== vota ===<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L112 Veure codi de TemaController@vota]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| vot<br />
| true / false<br />
| Estat actual del nostre vot de la nostra IP<br />
|-<br />
| nvots<br />
| integer<br />
| Total de vots per al tema<br />
|-<br />
| message<br />
| text<br />
| Missatge de text amb la descripció de l'error o acció<br />
|}<br />
<br />
<br><br />
<br />
=== fet ===<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L86 Veure codi de TemaController@fet]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| fet<br />
| true / false<br />
| Estat actual del tema (fet / no fet)<br />
|-<br />
| message<br />
| text<br />
| Missatge de text amb la descripció de l'error o acció<br />
|}<br />
<br />
<br></div>Enrichttps://cacauet.org/wiki/index.php?title=Serveis_web_amb_Laravel&diff=4232Serveis web amb Laravel2021-03-17T15:14:06Z<p>Enric: /* Headers en la crida curl */</p>
<hr />
<div>Per poder seguir amb normalitat aquest article cal haver llegit i treballat [[Laravel]].<br />
<br />
<br />
== Introducció ==<br />
Articles previs:<br />
* [[Serveis Web]]<br />
* [[Laravel]]<br />
<br />
Articles següents:<br />
* [[Serveis Web amb Opendata]]<br />
<br />
=== Perquè Laravel per a serveis web? ===<br />
No és imprescindible utilitzar [[Laravel]] per implementar un servei web. Ens és convenient pels següents motius:<br />
# En el curs de M7 de DAW estem treballant amb aquest framework i ens interessa aprofundir el seu coneixement.<br />
# Integrarem la part del ''frontend'' de la nostra web juntament amb la API que farem.<br />
# Laravel facilita l'accés a la base de dades a través del ORM Eloquent, que resulta molt útil.<br />
<br />
<br><br />
<br />
== Primera prova de la API ==<br />
Anem a implementar una primera prova de API en un projecte [[Laravel]] nou. Si et cal, crea'n un.<br />
<br />
Totes les funcions que vulguem implementar per al nostre sistema hem de començar per indicar-les al arxiu de rutes:<br />
routes/api.php<br />
<br />
De fet, les podríem implementar al mateix arxiu. Quan es compliquin, però, convindrà crear un controlador com vam fer al tutorial de [[Laravel]].<br />
<br />
Afegiu el següent codi a '''routes/api.php''':<br />
<syntaxhighlight lang="php"><br />
Route::get('/ping', function(Request $request) {<br />
return "pong! :)";<br />
});<br />
</syntaxhighlight><br />
<br />
Poseu en marxa el servidor i proveu la funció amb:<br />
$ curl localhost:8000/api/ping<br />
'''pong! :)'''super@HPi5-07:~/dev/laraveltest1$ <br />
<br />
Noteu que:<br />
* Encara que hem definit la ruta "/ping", per poder-la cridar hem de fer "/api/ping". Ve predefinit pel Laravel, tot i que no té perquè ser així.<br />
* Ens contesta el què hem posat al RETURN final<br />
* No retorna HTML, retorna un text que pot ser qualsevol cosa<br />
* No hi ha \n final (s'enganxa amb el ''prompt'' de la ''shell'')<br />
<br />
=== Headers en la crida ''curl'' ===<br />
Per veure els ''headers'' de retorn, podem utilitzar "-i", pot ser molt útil per depurar:<br />
$ curl -i localhost:8000/api/ping<br />
<br />
Obtindrem algo com:<br />
HTTP/1.1 200 OK<br />
Host: localhost:8000<br />
Date: Wed, 17 Mar 2021 15:13:14 GMT<br />
Connection: close<br />
X-Powered-By: PHP/7.4.9<br />
Content-Type: text/html; charset=UTF-8<br />
Cache-Control: no-cache, private<br />
Date: Wed, 17 Mar 2021 15:13:14 GMT<br />
X-RateLimit-Limit: 60<br />
X-RateLimit-Remaining: 59<br />
Access-Control-Allow-Origin: *<br />
<br />
pong! :)super@HPi5-07:~/dev/laraveltest1$ <br />
<br />
<br><br />
<br />
== Autenticació API amb Laravel Sanctum ==<br />
Des de fa algunes versions Laravel ha incorporat diversos mètodes d'autenticació, entre ells Breeze (bàsic), Fortify (avançat) i Sanctum (API). Aquest darrer és el què ens interessa.<br />
<br />
Sanctum té diversos mecanismes, depenent de qui utilitzarà la API (app mòbil, una web externa, etc.). Agafarem l'exemple de la APP MÒBIL.<br />
<br />
Consulta aquí la [https://laravel.com/docs/8.x/sanctum documentació de Laravel Sanctum].<br />
<br />
En definitiva, les diferents passes que cal seguir son:<br />
# Instal·lació de Sanctum<br />
# Anem a la [https://laravel.com/docs/8.x/sanctum#issuing-mobile-api-tokens secció per a generar tokens per a mòbils].<br />
#* Implementem el mètode per a autenticació mitjançant email i password. També cal passar-li el ''device_name'' que quedarà anotat junt al token.<br />
# Protegim rutes amb <pre>->middleware("auth:sanctum")</pre> , per exemple:<br />
#: <pre>Route::middleware('auth:sanctum')->get("/ping", function(Request $request) { ...</pre><br />
# Ara simularem la crida per demanar el token (la que posteriorment faríem des d'un mòbil)<br />
#: <pre>curl localhost:8000/api/sanctum/token -X POST -d 'email=jo@domini.com&password=enric123&device_name=LolaPhone55'</pre><br />
# Crida URL per <br />
#: <pre>curl localhost:8000/api/hola -H 'Authorization: Bearer lL0a21yHy4MzU4FdV5Cm0xZzd35AJ97acOOnW83t'</pre><br />
<br />
== Exemples de API: laravel-karaoke ==<br />
En el projecte karaoke en Laravel, el podeu veure aquí:<br />
* [https://github.com/emieza/laravel-karaoke/commit/8ab648decd6b58380545c60b135bad849a622d77 Versió amb el codi a api.php]. Es pot fer, però és una solució una mica "guarrilla"<br />
* [https://github.com/emieza/laravel-karaoke/blob/master/routes/api.php Versió amb el codi en un ''controller'']. Només veiem les rutes, però és raonable que no posem mogollón de codi aquí, sinó al [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php TemaController] en aquest cas.<br />
<br />
Recordem que per crear un controller amb Laravel ho fem amb (per exemple):<br />
$ php artisan make:controller ApiController<br />
<br />
Si mireu [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php TemaController] pareu atenció que per poder fer crides com <code>TemaController::fet($id)</code> , necessitem que siguin funcions estàtiques (static).<br />
<br />
Ara, per poder mirar el nº de vots, a '''routes/api.php''' tindrem:<br />
<syntaxhighlight lang="php"><br />
Route::get('/nvots/{id}', function(Request $request, $id) {<br />
return TemaController::nvots( $id );<br />
});<br />
</syntaxhighlight><br />
<br />
<br><br />
<br />
== Especificacions d'una API ==<br />
És molt important especificar adequadament una API per tal que la pugui fer servir molta gent.<br />
<br />
En l'exemple del karaoke tenim 3 crides, i les especificacions les indiquem amb quadres com els que mostrem a continuació:<br />
* /api/'''nvots'''/{tema_id}<br />
* /api/'''vota'''/{tema_id}<br />
* /api/'''fet'''/{tema_id}<br />
<br />
<br />
=== nvots ===<br />
Al ser una crida GET, els paràmetres han d'anar a la URL. Si fos POST, anirien afegits en el cos de la ''request'':<br />
<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L68 Veure codi del TemaController@nvots]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/nvots/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
Aquesta response retorna les dades en format '''JSON''', però podria tenir altres formats (XML, plain text):<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/nvots/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| nvots<br />
| integer<br />
| Total de vots per al tema<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema consultat<br />
|}<br />
<br />
Per exemple, per testejar-la:<br />
$ curl http://localhost:8000/api/nvots/1<br />
{"status":"OK","tema_id":"1","nvots":1}<br />
<br />
Per testejar l'exemple en producció, podeu provar (el -k és important perquè no demani els certificats HTTPS):<br />
$ curl https://jolgorio.tk/api/nvots/1 '''-k'''<br />
{"status":"OK","tema_id":"1","nvots":2}<br />
<br />
<br><br />
<br />
=== vota ===<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L112 Veure codi de TemaController@vota]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| vot<br />
| true / false<br />
| Estat actual del nostre vot de la nostra IP<br />
|-<br />
| nvots<br />
| integer<br />
| Total de vots per al tema<br />
|-<br />
| message<br />
| text<br />
| Missatge de text amb la descripció de l'error o acció<br />
|}<br />
<br />
<br><br />
<br />
=== fet ===<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L86 Veure codi de TemaController@fet]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| fet<br />
| true / false<br />
| Estat actual del tema (fet / no fet)<br />
|-<br />
| message<br />
| text<br />
| Missatge de text amb la descripció de l'error o acció<br />
|}<br />
<br />
<br></div>Enrichttps://cacauet.org/wiki/index.php?title=Serveis_web_amb_Laravel&diff=4231Serveis web amb Laravel2021-03-17T15:12:31Z<p>Enric: /* Autenticació API amb Laravel Sanctum */</p>
<hr />
<div>Per poder seguir amb normalitat aquest article cal haver llegit i treballat [[Laravel]].<br />
<br />
<br />
== Introducció ==<br />
Articles previs:<br />
* [[Serveis Web]]<br />
* [[Laravel]]<br />
<br />
Articles següents:<br />
* [[Serveis Web amb Opendata]]<br />
<br />
=== Perquè Laravel per a serveis web? ===<br />
No és imprescindible utilitzar [[Laravel]] per implementar un servei web. Ens és convenient pels següents motius:<br />
# En el curs de M7 de DAW estem treballant amb aquest framework i ens interessa aprofundir el seu coneixement.<br />
# Integrarem la part del ''frontend'' de la nostra web juntament amb la API que farem.<br />
# Laravel facilita l'accés a la base de dades a través del ORM Eloquent, que resulta molt útil.<br />
<br />
<br><br />
<br />
== Primera prova de la API ==<br />
Anem a implementar una primera prova de API en un projecte [[Laravel]] nou. Si et cal, crea'n un.<br />
<br />
Totes les funcions que vulguem implementar per al nostre sistema hem de començar per indicar-les al arxiu de rutes:<br />
routes/api.php<br />
<br />
De fet, les podríem implementar al mateix arxiu. Quan es compliquin, però, convindrà crear un controlador com vam fer al tutorial de [[Laravel]].<br />
<br />
Afegiu el següent codi a '''routes/api.php''':<br />
<syntaxhighlight lang="php"><br />
Route::get('/ping', function(Request $request) {<br />
return "pong! :)";<br />
});<br />
</syntaxhighlight><br />
<br />
Poseu en marxa el servidor i proveu la funció amb:<br />
$ curl localhost:8000/api/ping<br />
'''pong! :)'''super@HPi5-07:~/dev/laraveltest1$ <br />
<br />
Noteu que:<br />
* Encara que hem definit la ruta "/ping", per poder-la cridar hem de fer "/api/ping". Ve predefinit pel Laravel, tot i que no té perquè ser així.<br />
* Ens contesta el què hem posat al RETURN final<br />
* No retorna HTML, retorna un text que pot ser qualsevol cosa<br />
* No hi ha \n final (s'enganxa amb el ''prompt'' de la ''shell'')<br />
<br />
=== Headers en la crida ''curl'' ===<br />
Per veure els ''headers'' de retorn, podem utilitzar "-i", pot ser molt útil per depurar:<br />
$ curl -i localhost:8000/api/ping<br />
<br />
Obtindrem:<br />
HTTP/1.1 200 OK<br />
Host: localhost:8000<br />
Connection: close<br />
X-Powered-By: PHP/7.0.15-0ubuntu0.16.04.4<br />
Cache-Control: no-cache<br />
Content-Type: text/html; charset=UTF-8<br />
X-RateLimit-Limit: 60<br />
X-RateLimit-Remaining: 59<br />
Date: Thu, 09 Mar 2017 17:25:32 GMT <br />
<br />
pong! :)super@HPi5-07:~/dev/laraveltest1$ <br />
<br />
<br><br />
<br />
== Autenticació API amb Laravel Sanctum ==<br />
Des de fa algunes versions Laravel ha incorporat diversos mètodes d'autenticació, entre ells Breeze (bàsic), Fortify (avançat) i Sanctum (API). Aquest darrer és el què ens interessa.<br />
<br />
Sanctum té diversos mecanismes, depenent de qui utilitzarà la API (app mòbil, una web externa, etc.). Agafarem l'exemple de la APP MÒBIL.<br />
<br />
Consulta aquí la [https://laravel.com/docs/8.x/sanctum documentació de Laravel Sanctum].<br />
<br />
En definitiva, les diferents passes que cal seguir son:<br />
# Instal·lació de Sanctum<br />
# Anem a la [https://laravel.com/docs/8.x/sanctum#issuing-mobile-api-tokens secció per a generar tokens per a mòbils].<br />
#* Implementem el mètode per a autenticació mitjançant email i password. També cal passar-li el ''device_name'' que quedarà anotat junt al token.<br />
# Protegim rutes amb <pre>->middleware("auth:sanctum")</pre> , per exemple:<br />
#: <pre>Route::middleware('auth:sanctum')->get("/ping", function(Request $request) { ...</pre><br />
# Ara simularem la crida per demanar el token (la que posteriorment faríem des d'un mòbil)<br />
#: <pre>curl localhost:8000/api/sanctum/token -X POST -d 'email=jo@domini.com&password=enric123&device_name=LolaPhone55'</pre><br />
# Crida URL per <br />
#: <pre>curl localhost:8000/api/hola -H 'Authorization: Bearer lL0a21yHy4MzU4FdV5Cm0xZzd35AJ97acOOnW83t'</pre><br />
<br />
== Exemples de API: laravel-karaoke ==<br />
En el projecte karaoke en Laravel, el podeu veure aquí:<br />
* [https://github.com/emieza/laravel-karaoke/commit/8ab648decd6b58380545c60b135bad849a622d77 Versió amb el codi a api.php]. Es pot fer, però és una solució una mica "guarrilla"<br />
* [https://github.com/emieza/laravel-karaoke/blob/master/routes/api.php Versió amb el codi en un ''controller'']. Només veiem les rutes, però és raonable que no posem mogollón de codi aquí, sinó al [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php TemaController] en aquest cas.<br />
<br />
Recordem que per crear un controller amb Laravel ho fem amb (per exemple):<br />
$ php artisan make:controller ApiController<br />
<br />
Si mireu [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php TemaController] pareu atenció que per poder fer crides com <code>TemaController::fet($id)</code> , necessitem que siguin funcions estàtiques (static).<br />
<br />
Ara, per poder mirar el nº de vots, a '''routes/api.php''' tindrem:<br />
<syntaxhighlight lang="php"><br />
Route::get('/nvots/{id}', function(Request $request, $id) {<br />
return TemaController::nvots( $id );<br />
});<br />
</syntaxhighlight><br />
<br />
<br><br />
<br />
== Especificacions d'una API ==<br />
És molt important especificar adequadament una API per tal que la pugui fer servir molta gent.<br />
<br />
En l'exemple del karaoke tenim 3 crides, i les especificacions les indiquem amb quadres com els que mostrem a continuació:<br />
* /api/'''nvots'''/{tema_id}<br />
* /api/'''vota'''/{tema_id}<br />
* /api/'''fet'''/{tema_id}<br />
<br />
<br />
=== nvots ===<br />
Al ser una crida GET, els paràmetres han d'anar a la URL. Si fos POST, anirien afegits en el cos de la ''request'':<br />
<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L68 Veure codi del TemaController@nvots]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/nvots/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
Aquesta response retorna les dades en format '''JSON''', però podria tenir altres formats (XML, plain text):<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/nvots/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| nvots<br />
| integer<br />
| Total de vots per al tema<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema consultat<br />
|}<br />
<br />
Per exemple, per testejar-la:<br />
$ curl http://localhost:8000/api/nvots/1<br />
{"status":"OK","tema_id":"1","nvots":1}<br />
<br />
Per testejar l'exemple en producció, podeu provar (el -k és important perquè no demani els certificats HTTPS):<br />
$ curl https://jolgorio.tk/api/nvots/1 '''-k'''<br />
{"status":"OK","tema_id":"1","nvots":2}<br />
<br />
<br><br />
<br />
=== vota ===<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L112 Veure codi de TemaController@vota]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| vot<br />
| true / false<br />
| Estat actual del nostre vot de la nostra IP<br />
|-<br />
| nvots<br />
| integer<br />
| Total de vots per al tema<br />
|-<br />
| message<br />
| text<br />
| Missatge de text amb la descripció de l'error o acció<br />
|}<br />
<br />
<br><br />
<br />
=== fet ===<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L86 Veure codi de TemaController@fet]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| fet<br />
| true / false<br />
| Estat actual del tema (fet / no fet)<br />
|-<br />
| message<br />
| text<br />
| Missatge de text amb la descripció de l'error o acció<br />
|}<br />
<br />
<br></div>Enrichttps://cacauet.org/wiki/index.php?title=Serveis_web_amb_Laravel&diff=4230Serveis web amb Laravel2021-03-17T15:03:19Z<p>Enric: /* Exemples de API: laravel-karaoke */</p>
<hr />
<div>Per poder seguir amb normalitat aquest article cal haver llegit i treballat [[Laravel]].<br />
<br />
<br />
== Introducció ==<br />
Articles previs:<br />
* [[Serveis Web]]<br />
* [[Laravel]]<br />
<br />
Articles següents:<br />
* [[Serveis Web amb Opendata]]<br />
<br />
=== Perquè Laravel per a serveis web? ===<br />
No és imprescindible utilitzar [[Laravel]] per implementar un servei web. Ens és convenient pels següents motius:<br />
# En el curs de M7 de DAW estem treballant amb aquest framework i ens interessa aprofundir el seu coneixement.<br />
# Integrarem la part del ''frontend'' de la nostra web juntament amb la API que farem.<br />
# Laravel facilita l'accés a la base de dades a través del ORM Eloquent, que resulta molt útil.<br />
<br />
<br><br />
<br />
== Primera prova de la API ==<br />
Anem a implementar una primera prova de API en un projecte [[Laravel]] nou. Si et cal, crea'n un.<br />
<br />
Totes les funcions que vulguem implementar per al nostre sistema hem de començar per indicar-les al arxiu de rutes:<br />
routes/api.php<br />
<br />
De fet, les podríem implementar al mateix arxiu. Quan es compliquin, però, convindrà crear un controlador com vam fer al tutorial de [[Laravel]].<br />
<br />
Afegiu el següent codi a '''routes/api.php''':<br />
<syntaxhighlight lang="php"><br />
Route::get('/ping', function(Request $request) {<br />
return "pong! :)";<br />
});<br />
</syntaxhighlight><br />
<br />
Poseu en marxa el servidor i proveu la funció amb:<br />
$ curl localhost:8000/api/ping<br />
'''pong! :)'''super@HPi5-07:~/dev/laraveltest1$ <br />
<br />
Noteu que:<br />
* Encara que hem definit la ruta "/ping", per poder-la cridar hem de fer "/api/ping". Ve predefinit pel Laravel, tot i que no té perquè ser així.<br />
* Ens contesta el què hem posat al RETURN final<br />
* No retorna HTML, retorna un text que pot ser qualsevol cosa<br />
* No hi ha \n final (s'enganxa amb el ''prompt'' de la ''shell'')<br />
<br />
=== Headers en la crida ''curl'' ===<br />
Per veure els ''headers'' de retorn, podem utilitzar "-i", pot ser molt útil per depurar:<br />
$ curl -i localhost:8000/api/ping<br />
<br />
Obtindrem:<br />
HTTP/1.1 200 OK<br />
Host: localhost:8000<br />
Connection: close<br />
X-Powered-By: PHP/7.0.15-0ubuntu0.16.04.4<br />
Cache-Control: no-cache<br />
Content-Type: text/html; charset=UTF-8<br />
X-RateLimit-Limit: 60<br />
X-RateLimit-Remaining: 59<br />
Date: Thu, 09 Mar 2017 17:25:32 GMT <br />
<br />
pong! :)super@HPi5-07:~/dev/laraveltest1$ <br />
<br />
<br><br />
<br />
== Autenticació API amb Laravel Sanctum ==<br />
Des de fa algunes versions Laravel ha incorporat diversos mètodes d'autenticació, entre ells Breeze (bàsic), Fortify (avançat) i Sanctum (API). Aquest darrer és el què ens interessa.<br />
<br />
Consulta aquí la [https://laravel.com/docs/8.x/sanctum documentació de Laravel Sanctum].<br />
<br />
<br />
<br />
<br />
<br />
<br />
== Exemples de API: laravel-karaoke ==<br />
En el projecte karaoke en Laravel, el podeu veure aquí:<br />
* [https://github.com/emieza/laravel-karaoke/commit/8ab648decd6b58380545c60b135bad849a622d77 Versió amb el codi a api.php]. Es pot fer, però és una solució una mica "guarrilla"<br />
* [https://github.com/emieza/laravel-karaoke/blob/master/routes/api.php Versió amb el codi en un ''controller'']. Només veiem les rutes, però és raonable que no posem mogollón de codi aquí, sinó al [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php TemaController] en aquest cas.<br />
<br />
Recordem que per crear un controller amb Laravel ho fem amb (per exemple):<br />
$ php artisan make:controller ApiController<br />
<br />
Si mireu [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php TemaController] pareu atenció que per poder fer crides com <code>TemaController::fet($id)</code> , necessitem que siguin funcions estàtiques (static).<br />
<br />
Ara, per poder mirar el nº de vots, a '''routes/api.php''' tindrem:<br />
<syntaxhighlight lang="php"><br />
Route::get('/nvots/{id}', function(Request $request, $id) {<br />
return TemaController::nvots( $id );<br />
});<br />
</syntaxhighlight><br />
<br />
<br><br />
<br />
== Especificacions d'una API ==<br />
És molt important especificar adequadament una API per tal que la pugui fer servir molta gent.<br />
<br />
En l'exemple del karaoke tenim 3 crides, i les especificacions les indiquem amb quadres com els que mostrem a continuació:<br />
* /api/'''nvots'''/{tema_id}<br />
* /api/'''vota'''/{tema_id}<br />
* /api/'''fet'''/{tema_id}<br />
<br />
<br />
=== nvots ===<br />
Al ser una crida GET, els paràmetres han d'anar a la URL. Si fos POST, anirien afegits en el cos de la ''request'':<br />
<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L68 Veure codi del TemaController@nvots]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/nvots/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
Aquesta response retorna les dades en format '''JSON''', però podria tenir altres formats (XML, plain text):<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/nvots/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| nvots<br />
| integer<br />
| Total de vots per al tema<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema consultat<br />
|}<br />
<br />
Per exemple, per testejar-la:<br />
$ curl http://localhost:8000/api/nvots/1<br />
{"status":"OK","tema_id":"1","nvots":1}<br />
<br />
Per testejar l'exemple en producció, podeu provar (el -k és important perquè no demani els certificats HTTPS):<br />
$ curl https://jolgorio.tk/api/nvots/1 '''-k'''<br />
{"status":"OK","tema_id":"1","nvots":2}<br />
<br />
<br><br />
<br />
=== vota ===<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L112 Veure codi de TemaController@vota]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| vot<br />
| true / false<br />
| Estat actual del nostre vot de la nostra IP<br />
|-<br />
| nvots<br />
| integer<br />
| Total de vots per al tema<br />
|-<br />
| message<br />
| text<br />
| Missatge de text amb la descripció de l'error o acció<br />
|}<br />
<br />
<br><br />
<br />
=== fet ===<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L86 Veure codi de TemaController@fet]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| fet<br />
| true / false<br />
| Estat actual del tema (fet / no fet)<br />
|-<br />
| message<br />
| text<br />
| Missatge de text amb la descripció de l'error o acció<br />
|}<br />
<br />
<br></div>Enrichttps://cacauet.org/wiki/index.php?title=Serveis_web_amb_Laravel&diff=4229Serveis web amb Laravel2021-03-17T14:59:17Z<p>Enric: /* L'exemple laravel-karaoke */</p>
<hr />
<div>Per poder seguir amb normalitat aquest article cal haver llegit i treballat [[Laravel]].<br />
<br />
<br />
== Introducció ==<br />
Articles previs:<br />
* [[Serveis Web]]<br />
* [[Laravel]]<br />
<br />
Articles següents:<br />
* [[Serveis Web amb Opendata]]<br />
<br />
=== Perquè Laravel per a serveis web? ===<br />
No és imprescindible utilitzar [[Laravel]] per implementar un servei web. Ens és convenient pels següents motius:<br />
# En el curs de M7 de DAW estem treballant amb aquest framework i ens interessa aprofundir el seu coneixement.<br />
# Integrarem la part del ''frontend'' de la nostra web juntament amb la API que farem.<br />
# Laravel facilita l'accés a la base de dades a través del ORM Eloquent, que resulta molt útil.<br />
<br />
<br><br />
<br />
== Primera prova de la API ==<br />
Anem a implementar una primera prova de API en un projecte [[Laravel]] nou. Si et cal, crea'n un.<br />
<br />
Totes les funcions que vulguem implementar per al nostre sistema hem de començar per indicar-les al arxiu de rutes:<br />
routes/api.php<br />
<br />
De fet, les podríem implementar al mateix arxiu. Quan es compliquin, però, convindrà crear un controlador com vam fer al tutorial de [[Laravel]].<br />
<br />
Afegiu el següent codi a '''routes/api.php''':<br />
<syntaxhighlight lang="php"><br />
Route::get('/ping', function(Request $request) {<br />
return "pong! :)";<br />
});<br />
</syntaxhighlight><br />
<br />
Poseu en marxa el servidor i proveu la funció amb:<br />
$ curl localhost:8000/api/ping<br />
'''pong! :)'''super@HPi5-07:~/dev/laraveltest1$ <br />
<br />
Noteu que:<br />
* Encara que hem definit la ruta "/ping", per poder-la cridar hem de fer "/api/ping". Ve predefinit pel Laravel, tot i que no té perquè ser així.<br />
* Ens contesta el què hem posat al RETURN final<br />
* No retorna HTML, retorna un text que pot ser qualsevol cosa<br />
* No hi ha \n final (s'enganxa amb el ''prompt'' de la ''shell'')<br />
<br />
=== Headers en la crida ''curl'' ===<br />
Per veure els ''headers'' de retorn, podem utilitzar "-i", pot ser molt útil per depurar:<br />
$ curl -i localhost:8000/api/ping<br />
<br />
Obtindrem:<br />
HTTP/1.1 200 OK<br />
Host: localhost:8000<br />
Connection: close<br />
X-Powered-By: PHP/7.0.15-0ubuntu0.16.04.4<br />
Cache-Control: no-cache<br />
Content-Type: text/html; charset=UTF-8<br />
X-RateLimit-Limit: 60<br />
X-RateLimit-Remaining: 59<br />
Date: Thu, 09 Mar 2017 17:25:32 GMT <br />
<br />
pong! :)super@HPi5-07:~/dev/laraveltest1$ <br />
<br />
<br><br />
<br />
== Exemples de API: laravel-karaoke ==<br />
En el projecte karaoke en Laravel, el podeu veure aquí:<br />
* [https://github.com/emieza/laravel-karaoke/commit/8ab648decd6b58380545c60b135bad849a622d77 Versió amb el codi a api.php]. Es pot fer, però és una solució una mica "guarrilla"<br />
* [https://github.com/emieza/laravel-karaoke/blob/master/routes/api.php Versió amb el codi en un ''controller'']. Només veiem les rutes, però és raonable que no posem mogollón de codi aquí, sinó al [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php TemaController] en aquest cas.<br />
<br />
Recordem que per crear un controller amb Laravel ho fem amb (per exemple):<br />
$ php artisan make:controller ApiController<br />
<br />
Si mireu [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php TemaController] pareu atenció que per poder fer crides com <code>TemaController::fet($id)</code> , necessitem que siguin funcions estàtiques (static).<br />
<br />
Ara, per poder mirar el nº de vots, a '''routes/api.php''' tindrem:<br />
<syntaxhighlight lang="php"><br />
Route::get('/nvots/{id}', function(Request $request, $id) {<br />
return TemaController::nvots( $id );<br />
});<br />
</syntaxhighlight><br />
<br />
<br><br />
<br />
== Especificacions d'una API ==<br />
És molt important especificar adequadament una API per tal que la pugui fer servir molta gent.<br />
<br />
En l'exemple del karaoke tenim 3 crides, i les especificacions les indiquem amb quadres com els que mostrem a continuació:<br />
* /api/'''nvots'''/{tema_id}<br />
* /api/'''vota'''/{tema_id}<br />
* /api/'''fet'''/{tema_id}<br />
<br />
<br />
=== nvots ===<br />
Al ser una crida GET, els paràmetres han d'anar a la URL. Si fos POST, anirien afegits en el cos de la ''request'':<br />
<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L68 Veure codi del TemaController@nvots]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/nvots/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
Aquesta response retorna les dades en format '''JSON''', però podria tenir altres formats (XML, plain text):<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/nvots/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| nvots<br />
| integer<br />
| Total de vots per al tema<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema consultat<br />
|}<br />
<br />
Per exemple, per testejar-la:<br />
$ curl http://localhost:8000/api/nvots/1<br />
{"status":"OK","tema_id":"1","nvots":1}<br />
<br />
Per testejar l'exemple en producció, podeu provar (el -k és important perquè no demani els certificats HTTPS):<br />
$ curl https://jolgorio.tk/api/nvots/1 '''-k'''<br />
{"status":"OK","tema_id":"1","nvots":2}<br />
<br />
<br><br />
<br />
=== vota ===<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L112 Veure codi de TemaController@vota]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| vot<br />
| true / false<br />
| Estat actual del nostre vot de la nostra IP<br />
|-<br />
| nvots<br />
| integer<br />
| Total de vots per al tema<br />
|-<br />
| message<br />
| text<br />
| Missatge de text amb la descripció de l'error o acció<br />
|}<br />
<br />
<br><br />
<br />
=== fet ===<br />
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L86 Veure codi de TemaController@fet]<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Request<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| tema_id<br />
| integer<br />
| ID del tema del que volem saber el nº de vots que té<br />
|}<br />
<br />
{| class="wikitable"<br />
!colspan="3"|Response : JSON<br />
|-<br />
!colspan="3"|GET /api/vota/{tema_id}<br />
|-<br />
!Param<br />
!Values<br />
!Description<br />
|-<br />
| status<br />
| "OK" / "ERROR"<br />
| Estat intern de la consulta/acció<br />
|-<br />
| fet<br />
| true / false<br />
| Estat actual del tema (fet / no fet)<br />
|-<br />
| message<br />
| text<br />
| Missatge de text amb la descripció de l'error o acció<br />
|}<br />
<br />
<br></div>Enrichttps://cacauet.org/wiki/index.php?title=Laravel&diff=4228Laravel2021-02-28T18:33:41Z<p>Enric: /* Rols d'usuari */</p>
<hr />
<div><nowiki>#FpInfor #DawMp07 #DawMp07Uf2 #DawMp07Uf02 #DawMpDual</nowiki><br />
<br />
<br />
== Intro i referències ==<br />
Laravel és un framework web per a PHP que està agafant molta força.<br />
<br />
Documentació oficial: https://laravel.com/docs/<br />
<br />
Tutorials:<br />
* [https://ajgallego.gitbooks.io/laravel-5/content/index.html Principal tutorial per seguir el curs]: <pre>https://ajgallego.gitbooks.io/laravel-5/content/index.html</pre><br />
* Forms: https://selftaughtcoders.com/from-idea-to-launch/lesson-23/laravel-5-application-form-model-binding-laravelcollective-forms-html-library-bootstrap-framework/<br />
* Forms i validació: https://scotch.io/tutorials/simple-laravel-crud-with-resource-controllers<br />
* Apunts del Sergi Coll: https://seicoll.github.io/DAW-M07-UF2-Apunts/<br />
* https://styde.net/laravel-5/<br />
* Per passar del schema SQL (per ex. de MySQL Workbench) a Laravel migration: https://adolfocuadros.com/sql_to_laravel/<br />
<br />
<br />
Plugins:<br />
* CORS (Cross-Origin Resource Sharing): https://github.com/barryvdh/laravel-cors<br />
* CRUD & admin : Hi ha molts plugins per crear ''admin panels'' automàticament. Alguns son:<br />
** Voyager: https://voyager.devdojo.com/<br />
** Craftable: https://www.getcraftable.com/<br />
* https://iamacoder.com/post/5-must-have-laravel-5-packages/<br />
<br />
Temes a ampliar:<br />
* Forms: https://laravel.com/docs/4.2/html<br />
* Validació de forms: https://laravel.com/docs/5.5/validation<br />
* Autenticació: https://laravel.com/docs/5.5/authentication<br />
<br />
<br><br />
<br />
== Instal·lació i setup ==<br />
<br />
Prerequisits:<br />
* Laravel i PHP, és molt important tenir en compte les versions:<br />
** <strike>Laravel 5.3 : PHP >= 5.6.4<br />
** Laravel 5.5 : PHP == 7.0<br />
** Laravel 5.6 : PHP >= 7.1<br />
** Laravel 5.7 : PHP >= 7.1.3</strike><br />
** Laravel 6.x : PHP >= 7.2<br />
* Si utilitzes Ubuntu 14 o menor [https://www.digitalocean.com/community/tutorials/how-to-upgrade-to-php-7-on-ubuntu-14-04 actualitza la teva versió de PHP a la 7.0]<br />
* Calen els paquets següents: <pre>$ sudo apt-get install php-mbstring php-zip php-xml php-mysql</pre><br />
<br />
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...:<br />
# Instal·la el gestor de paquets per PHP Composer<br />
#* El més fàcil és fer: (però no ho farem pq volem la darrera versió)<pre>$ sudo apt install composer</pre><br />
#* Prova primer la instal·lació genèrica : [https://getcomposer.org/download/ Instal.la PHP Composer]<br />
#* També tens aquesta altra forma d' [https://getcomposer.org/doc/00-intro.md#installation-linux-unix-osx instal·lar Composer per GNU/Linux]. Descarrega composer-setup.php i instal·la'l així:<pre>$ php composer-setup.php --install-dir=~/bin --filename=composer</pre><br />
# Instal·la la darrera versió de Laravel<br />
#* https://laravel.com/docs/5.7/installation<br />
#* Bàsicament el què cal fer és aquesta comanda per instal·lar el binari ''laravel'':<pre>$ composer global require laravel/installer</pre><br />
#* Laravel s'instal·la a <code>$HOME/.config/composer</code> però per poder executar les properes comandes necessitarem tenir <code>$HOME/.config/composer/vendor/bin</code> al nostre $PATH. Inserta això al teu <code>$HOME/.profile</code>: <pre>PATH=$PATH:~/.config/composer/vendor/bin</pre><br />
#*: Fes logout/login del sistema per activar aquests canvis<br />
# Crea una app Laravel allà on et faci més ràbia: <pre>$ laravel new laravelapp1</pre><br />
#: o també: <pre>$ composer create-project --prefer-dist laravel/laravel laravelapp1</pre><br />
#: o si volem una versió específica de laravel: <pre>$ composer create-project --prefer-dist laravel/laravel=5.8.* laravelapp1</pre><br />
# Arrenca l'aplicació de prova: <pre>$ php artisan serve</pre><br />
# Comprova la app amb el navegador a<pre>http://localhost:8000</pre><br />
<br />
<br><br />
<br />
Si ja has completat la instal·lació, pots procedir a crear un altre projecte nou i realitzar el següent tutorial "tasklist":<br />
https://laravel.com/docs/5.2/quickstart<br />
<br />
<br><br />
<br />
== Incidències vàries ==<br />
Aquest és un bon tutorial:<br />
https://ajgallego.gitbooks.io/laravel-5/content/index.html<br />
<br />
Igualment, podríem trobar algunes incidències. Us dono pistes:<br />
<br />
=== Treballant amb GIT i clonant ===<br />
Al pujar el projecte a un repo GIT, i clonar-lo després caldrà:<br />
# Re-instal·lar les dependències:<pre>$ composer install</pre><br />
# Regenerar arxiu <code>.env</code> : com que depèn de cada entorn no es fica al projecte (es posa a <code>.gitignore</code>), però pots copiar i modificar de <code>.env.example</code><br />
# Error ''The only supported ciphers are AES-128-CBC and AES-256-CBC with the correct key lengths.'' Es soluciona amb :<pre>$ php artisan key:generate</pre><br />
<br />
=== Creant controllers amb CRUD complert ===<br />
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.<br />
# Ja no es pot fer amb <strike><code>Route::controller</code></strike> sinó amb:<pre>Route::resource("cosa","CosaController");</pre><br />
# Per exemple, per crear un controller per al model "Cosa" ho faríem amb -r (de resource): <pre>$ php artisan make:controller -r CosaController</pre><br />
<br />
=== Treballant amb SQLite ===<br />
Per configurar la BD amb SQLite cal crear el fitxer abans amb:<br />
$ touch db.sqlite<br />
<br />
Configurar la BD a .env:<br />
DB_CONNECTION=sqlite<br />
DB_DATABASE=/path/absolut/al/db.sqlite<br />
<br />
Instal·lar els binaris necessaris de SQLite i de PHP:<br />
$ sudo apt-get install sqlite php-sqlite3<br />
<br />
I crear la BD inicial amb:<br />
$ php artisan migrate<br />
<br />
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.<br />
<br />
=== Eliminant models o migracions ===<br />
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:<br />
$ composer dump-autoload<br />
...i es tornaran a generar els arxius d'autoload sense els arxius que volíem esborrar.<br />
<br />
=== Treballant amb proxies i composer ===<br />
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):<br />
$ composer update<br />
Loading composer repositories with package information<br />
Updating dependencies (including require-dev)<br />
(...demana user/password de packagist.org ...)<br />
<br />
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:<br />
$ ssh -L 3128:localhost:3128 jo@elmeuserver.com<br />
I un cop logats, aprofitem per instal·lar el squid:<br />
$ sudo apt install squid<br />
Hem de mantenir la shell oberta mentre vulguem que estigui activat el túnel (l'hem assignat a localhost:3128).<br />
<br />
Obrim una altra shell i anem al nostre projecte Laravel:<br />
$ export http_proxy=localhost:3128<br />
$ composer update<br />
<br />
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).<br />
<br />
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:<br />
$ ssh jo@elmeuserver.com<br />
$ sudo apt remove squid<br />
<br />
<br><br />
<br />
== Tutorials ==<br />
Després d'elaborar la documentació he trobat aquest tutorial bastant útil (només fins la v5.2):<br />
https://laravel.com/docs/5.2/quickstart<br />
<br />
Tutorial per a CRUD complert:<br />
https://www.itsolutionstuff.com/post/laravel-6-crud-application-tutorialexample.html<br />
<br />
== Resum per a fer un CRUD ==<br />
<br />
=== Setup projecte ===<br />
Crear projecte:<br />
$ laravel new proj1<br />
Crear DB (en aquest cas SQLite:<br />
$ touch db.sqlite<br />
Modifica .env per configurar la DB com sqlite:<br />
DB_CONNECTION=sqlite<br />
DB_DATABASE=/path/absolut/al/db.sqlite<br />
<br />
=== Model ===<br />
Crear taules i migracions:<br />
$ php artisan make:migration crea_taula_items --create=items<br />
Editar la migració per crear les taules adequades. Mira't les principals referències:<br />
* [https://laravel.com/docs/5.5/migrations#columns Tipus de columnes]<br />
* [https://laravel.com/docs/5.5/migrations#foreign-key-constraints Relacions i FKs]<br />
Realitzar la migració:<br />
$ php artisan migrate<br />
Crear models:<br />
$ php artisan make:model Item<br />
Ajusta el model perquè apunti al nom correcte de la taula:<br />
https://laravel.com/docs/5.5/eloquent#eloquent-model-conventions<br />
<br />
=== Controller i rutes ===<br />
Crear controllers amb els mètodes estàndard (index, create-store, show, edit-update, destroy):<br />
$ php artisan make:controller -r ItemController<br />
Crear rutes a <code>routes/web.php</code>:<br />
Route::resource("item","ItemController");<br />
Crear plantilles per als mètodes (l'exemple diu "tema" enlloc de "item"):<br />
$ php artisan route:list<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
| Domain | Method | URI | Name | Action | Middleware |<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
| | GET|HEAD | / | | Closure | web |<br />
| | GET|HEAD | api/user | | Closure | api,auth:api |<br />
| | GET|HEAD | tema | tema.index | App\Http\Controllers\TemaController@index | web |<br />
| | POST | tema | tema.store | App\Http\Controllers\TemaController@store | web |<br />
| | GET|HEAD | tema/create | tema.create | App\Http\Controllers\TemaController@create | web |<br />
| | GET|HEAD | tema/{tema} | tema.show | App\Http\Controllers\TemaController@show | web |<br />
| | PUT|PATCH | tema/{tema} | tema.update | App\Http\Controllers\TemaController@update | web |<br />
| | DELETE | tema/{tema} | tema.destroy | App\Http\Controllers\TemaController@destroy | web |<br />
| | GET|HEAD | tema/{tema}/edit | tema.edit | App\Http\Controllers\TemaController@edit | web |<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
<br />
Crear les views (plantilles blade) adequades per a tots els mètodes necessaris (els arxius van a <code>resources/views</code>). Pots veure [https://github.com/emieza/laravel-karaoke/tree/master/resources/views/llista aqui] alguns exemples.<br />
* '''index''' : llista tots els elements<br />
* '''show''' : mostra un element en concret, necessita que li passem un paràmetre per GET (id del element a mostrar)<br />
* '''create-store''' : "create és el form (no necessita codi), i "store" és el codi per insertar-ho a la BD (no necessita una plantilla)<br />
* '''edit-update''' : "edit" és el form, i "update" el codi per actualitzar la BD<br />
* '''destroy''' : elimina un element<br />
<br />
=== Codi del Controller i View ===<br />
* Crear views amb formularis d'entrada de dades: [https://github.com/emieza/laravel-karaoke/blob/master/resources/views/llista/crea.blade.php create.blade.php d'exemple]<br />
* Editar el codi del Controller per cridar pertinentment a les views: [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/LlistaController.php Controller d'exemple]<br />
<br />
=== Més docs ===<br />
Una bona referència de la doc oficial per fer un CRUD és aquesta:<br />
https://laravel.com/docs/5.2/quickstart<br />
En particular per veure com utilitzar les templates oficials amb bootstrap ;)<br />
<br />
<br><br />
<br />
== Projecte d'exemple ==<br />
Aquest és el projecte que he realitzat per entrenar-me, et pot servir d'exemple. El pots veure en producció aquí: https://jolgorio.tk<br />
https://github.com/emieza/laravel-karaoke<br />
<br />
Fes-li un cop d'ull al readme.md per veure com posar-lo en marxa.<br />
<br />
MOLT IMPORTANT PEL PROJECTE: Cal crear un README.md (com [https://github.com/emieza/laravel-karaoke/blob/master/readme.md per exemple aquest]). No acceptaré cap projecte sense README.md<br />
<br />
Per entrenar-vos amb el Markdown teniu aquest tester:<br />
http://dillinger.io/<br />
<br />
Anem per feina:<br />
# Taules: llistes, temes, vots<br />
# Rutes que vols implementar per al projecte. [https://github.com/emieza/laravel-karaoke/blob/master/routes/web.php En el meu cas, tinc]:<br />
#* /llista/crea (GET per formulari + POST per store)<br />
#* /llista (index de llistes)<br />
#* /llista/{id} (show)<br />
#* /llista/{id}/crea (GET + POST, per crear temes en les llistes)<br />
#* /vota/{idtema}<br />
# Codi:<br />
#* als Controllers pertinents. Mira't l'[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/LlistaController.php exemple de les llistes de karaoke].<br />
#* Plantilles: a resources/views/xxxx.blade.php . Mira't l'[https://github.com/emieza/laravel-karaoke/tree/master/resources/views/llista exemple un altre cop].<br />
<br />
<br><br />
<br />
== ORM : Models i relacions ==<br />
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.<br />
<br />
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. <br />
<br />
El què anem a explicar està documentat a l'apartat "Eloquent ORM" de Laravel:<br />
https://laravel.com/docs/5.7/eloquent-relationships<br />
https://laravel.com/docs/6.x/eloquent-relationships<br />
<br />
=== Accedint relacions 1-N de forma directa ===<br />
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í.<br />
<br />
L'objectiu serà poder accedir a l'objecte pare d'aquesta manera per mostrar el text del Post (pare).<br />
<syntaxhighlight lang="php"><br />
$comment = Comment::find(33);<br />
echo $comment->post->text;<br />
</syntaxhighlight><br />
<br />
Per aconseguir això, cal que indiquem la relació existent a les taules entre els models Post i Comment amb la relació <code>belongsTo</code>:<br />
<br />
<syntaxhighlight lang="php"><br />
<?php<br />
namespace App;<br />
use Illuminate\Database\Eloquent\Model;<br />
class Comment extends Model<br />
{<br />
/**<br />
* Accedeix al pare (Post)<br />
*/<br />
public function post()<br />
{<br />
return $this->belongsTo('App\Post','post_id');<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Accedint relacions 1-N de forma inversa ===<br />
El següent cas típic serà accedir des d'un objecte Post als diferents Comentaris, més o menys així:<br />
<br />
<syntaxhighlight lang="php"><br />
$comments = App\Post::find(1)->comments;<br />
foreach ($comments as $comment) {<br />
// ... el teu codi...<br />
echo $comment->text;<br />
}<br />
</syntaxhighlight><br />
El codi que veiem és per a un ''controller'', però es pot aplicar també als ''templates'', amb @foreach i similars.<br />
<br />
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<br />
<syntaxhighlight lang="php"><br />
<?php<br />
namespace App;<br />
use Illuminate\Database\Eloquent\Model;<br />
class Post extends Model<br />
{<br />
/**<br />
* Accedeix als comentaris relacionats amb el Post actual<br />
*/<br />
public function comments()<br />
{<br />
return $this->hasMany('App\Comment','<ref_remota>','<ref_local>');<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
On:<br />
* <ref_remota> és el camp de la taula de Comment que referencia el Post<br />
* <ref_local> és el camp de Post que fa de PK i on Comment apunta<br />
<br />
Per accedir al objecte relacionat "pare" caldrà fer una altra funció, en concret ''belongsTo''. Consulta la doc de les relacions 1-a-N (inversa).<br />
<br />
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:<br />
https://laravel.com/docs/5.5/eloquent-relationships#one-to-many<br />
<br />
=== Aniuant JSON en la API ===<br />
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:<br />
<br />
<syntaxhighlight lang="php"><br />
<?php<br />
Route::get("/comentaris", function() {<br />
$post = Post::with("comments")->get();<br />
return $post;<br />
});<br />
</syntaxhighlight><br />
<br />
...i ens retornarà les dades aniuades que volem! :)<br />
<br />
<br><br />
<br />
== Més coses ==<br />
Alguns temes que no hem aprofundit però que convé conèixer.<br />
<br />
=== Autenticació ===<br />
Senzill d'implementar i imprescindible. Laravel incorpora un ''scaffold'' per facilitar una funció tan estàndard.<br />
Amb una sola instrucció ens crea les rutes, vistes i els controllers típics (login, logout).<br />
<br />
==== Laravel 5.x ====<br />
[https://laravel.com/docs/5.5/authentication Autenticació en Laravel 5.x]:<br />
$ php artisan make:auth<br />
<br />
==== Laravel 6.x ====<br />
[https://laravel.com/docs/6.x/authentication Autenticació en Laravel 6.x]:<br />
$ composer require laravel/ui --dev<br />
$ php artisan ui vue --auth<br />
<br />
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:<br />
$ npm install && npm run dev<br />
<br />
També hi ha [https://laracasts.com/discuss/channels/laravel/laravel-60-appcss?page=1 solucions al problema carregant els CSS i JS del CDN] (només cal canviar un link en el ''head'' de <code>app.blade.php</code>.<br />
<br />
==== Laravel 8.x ====<br />
Ara el mòdul d'autenticació es diu [https://laravel.com/docs/8.x/starter-kits#laravel-breeze Laravel Breeze].<br />
<br />
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:<br />
* '''routes/web.php'''<br />
* '''resources/views/layouts/app.blade.php'''<br />
* resources/views/layouts/guest.blade.php<br />
* resources/views/layouts/navigation.blade.php<br />
* resources/views/auth/*<br />
* resources/views/components/*<br />
* resources/views/welcome.blade.php<br />
* resources/views/dashboard.blade.php<br />
<br />
Resumint, per instal·lar Breeze:<br />
$ composer require laravel/breeze --dev<br />
$ php artisan breeze:install<br />
$ npm install<br />
$ npm run dev<br />
<br />
==== Rols d'usuari ====<br />
En molts moments pot interessar tenir diversos rols d'usuari (admin, usuari, redactor, etc.).<br />
<br />
[https://medium.com/@otimfredrick/how-to-protect-admin-panel-route-in-laravel-70bb86168d87 Aquest post explica com utiltizar rols d'usuari] amb els sistemes bàsics d'autenticació de Laravel (Breeze, etc.).<br />
<br />
<br />
==== Desactivar registre d'usuaris ====<br />
Hi ha diverses maneres de desactivar el registre d'usuaris segons els mètodes d'autenticació triats (Breeze, JetStream o Fortify).<br />
<br />
Una manera senzilla d'aconseguir-ho és anar a les rutes de registre i comentar-les.<br />
<br />
=== Seeding ===<br />
Una part molt important és la de crear dades per farcir la base de dades inicialment i poder així testejar amb comoditat.<br />
<br />
https://laravel.com/docs/6.x/seeding<br />
<br />
En algun moment donat convé utilitzar un ''factory'' que ens permet crear elements en massa:<br />
<br />
https://laravel.com/docs/6.x/database-testing#writing-factories<br />
<br />
El ''factory'' sol utilitzar una llibreria <code>Faker</code> que ens va molt bé per crear noms i cognoms aleatoris, lorem ipsum, etc. que ens facilitarà la creació de dades de prova.<br />
<br />
https://github.com/fzaninotto/Faker<br />
<br />
=== Validacions ===<br />
Laravel ens ofereix un mecanisme de validació de formularis molt potent i efectiu.<br />
<br />
https://laravel.com/docs/5.5/validation<br />
<br />
=== Sessions ===<br />
D'entrada és molt útil per emetre missatges "flash", i informar l'usuari del processament intern.<br />
<br />
https://laravel.com/docs/5.5/session<br />
<br />
=== Arxius: filesystem vs BLOBs en BD ===<br />
Les imatges es poden guardar al sistema d'arxius o bé a la base de dades.<br />
* '''Filesystem''': En el propi tutorial hi ha una explicació de [https://ajgallego.gitbooks.io/laravel-5/content/capitulo_4_datos_de_entrada.html com guardar binaris amb el mètode clàssic del filesystem]<br />
* '''BLOBs en la BD''': Laravel ens permet crear models amb BLOBs i insertar les dades a la BD:<br />
** [https://www.daniweb.com/programming/web-development/threads/480731/how-to-inserting-files-on-mysql-using-laravel Insertant BLOBs amb Larvel]<br />
** Tingueu en compte, si ho feu així, de [https://stackoverflow.com/questions/8499633/how-to-display-base64-images-in-html com renderitzar continguts base64 (BLOBs) sobre un HTML]<br />
<br />
=== A solucionar ===<br />
Alguns temes a solucionar:<br />
* Quan utilitzem el scaffold d'autenticació, falla el logout. Això es deu a un canvi del mètode de GET a POST per motius de seguretat (amb POST, només podran fer logout des de la pròpia app Laravel ja que porta el csrf_token).<br />
*: https://laracasts.com/discuss/channels/laravel/laravel-53-logout-methodnotallowed<br />
<br />
<br><br />
<br />
=== Atacant 2 bases de dades simultàniament ===<br />
En alguns casos podem necessitar configurar 2 instàncies de bases de dades separades per optimitzar el rendiment. Aquest post ho explica molt bé:<br />
https://fideloper.com/laravel-multiple-database-connections<br />
<br />
Caldrà configurar el .env , config/database.php i especificar quina DB ataca en les migracions i en els models que creem.<br />
<br />
<br><br />
<br />
== Laravel i LDAP ==<br />
Aquest mòdul està pensat per a Active Directory, però [https://github.com/Adldap2/Adldap2-Laravel/issues/106 també funciona amb OpenLDAP si s'ajusta bé]:<br />
https://github.com/Adldap2/Adldap2-Laravel<br />
<br />
Primer cal configurar un servidor [[LDAP]].<br />
<br />
Després, tingues en compte que cal ajustar els següents paràmetres en el .env:<br />
ADLDAP_CONTROLLERS=localhost<br />
#ADLDAP_PORT=389<br />
ADLDAP_ADMIN_USERNAME="cn=admin,dc=cacauet,dc=org"<br />
ADLDAP_ADMIN_PASSWORD="enric123"<br />
ADLDAP_BASEDN="dc=cacauet,dc=org"<br />
<br />
Podem fer una autenticació seguint algun d'aquests exemples.<br />
<br />
Exemple 1: cercar un element del directori<br />
<syntaxhighlight lang="php"><br />
$user = Adldap::search()->where("mail","=","pepe@jolgorio.tk")->get();<br />
</syntaxhighlight><br />
<br />
Exemple 2: autenticar un usuari<br />
<syntaxhighlight lang="php"><br />
if( Adldap::auth()->attempt("cn=pepe,ou=usuaris,dc=cacauet,dc=org","pepe123")) {<br />
// autenticació exitosa<br />
return "Pepe OK!";<br />
}<br />
</syntaxhighlight><br />
<br />
<br><br />
<br />
== Laravel en producció ==<br />
Per posar en producció un projecte basat en Laravel cal tenir en compte:<br />
* '''IMPORTANT, SEGURETAT: Només cal publicar la carpeta <code>/public</code>''' . 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 .<br />
** Aquesta carpeta <code>/public</code> no figura inicialment quan creem o clonem un projecte (està a .gitignore), a l'igual que la carpeta <code>/vendor</code>, que es generen quan fem un <code>$ composer install</code>.<br />
** Reviseu la secció [[Laravel#Treballant_amb_GIT_i_clonant]] per fer el setup del projecte després de clonar.<br />
* '''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'').<br />
* 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:<br />
** db.sqlite (si s'escau)<br />
** carpeta <code>/storage</code><br />
** carpeta <code>/bootstrap/cache</code><br />
<br />
=== Desplegament en AWS amb Ubuntu i Apache ===<br />
Guia pel desplegament en Ubuntu amb Apache:<br />
* Accedir al nostre servidor via SSH<br />
* 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<pre>/var/www</pre><br />
* Per veure detalls reviseu la secció [[Laravel#Treballant_amb_GIT_i_clonant]]. Recordeu que això implica: <br />
*# composer install<br />
*# configurar arxiu .env<br />
*# generar clau<br />
* Es requereix el mòdul ''mod_rewrite'' d'Apache (o Nginx)<pre>$ sudo a2enmod rewrite</pre><br />
* Publicar la carpeta <code>/public</code> del projecte Laravel, d'alguna d'aquestes maneres:<br />
** Crear un VirtualHost i apuntar la ServerRoot del domini o subdomini a /var/www/<projecte>/public<br />
** Crear un link simbòlic de la carpeta pública d'Apache a la carpeta public del Laravel amb la comanda <pre>$ ln -s /var/www/<projecte>/public /var/www/html/lara1</pre><br />
* 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".<br />
* Ajusta els permisos de:<br />
** db.sqlite (si s'escau) i també de la carpeta que el conté (si no, no es podrà escriure-hi)<br />
** carpeta <code>/storage</code><br />
** carpeta <code>/bootstrap/cache</code><br />
* Cal activar els arxius <code>.htaccess</code> , afegint la directiva <code>AllowOverride all</code><br />
<br />
A l'arxiu de conf. del nostre VirtualHost (a <code>/etc/apache2/sites-available</code>):<br />
<Directory /var/www/><br />
AllowOverride All<br />
</Directory><br />
<br />
<br />
És important remarcar que per SEGURETAT no hem de mostrar mai els arxius interns de Laravel, només cal publicar el contingut de /public<br />
<br />
<br><br />
<br />
=== Heroku ===<br />
Abans de procedir amb aquesta part hauries de llegir i treballar aquesta altra: [[Heroku]] on treballem amb PHP simple.<br />
<br />
Pots posar en marxa un projecte Laravel a Heroku fàcilment seguint aquesta documentació. Segueix el tutorial per iniciar la app:<br />
https://devcenter.heroku.com/articles/getting-started-with-laravel<br />
<br />
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.<br />
<br />
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.<br />
<br />
En canvi, [https://devcenter.heroku.com/articles/heroku-postgresql el add-on de POSTGRESQL és gratuït i sense targeta de crèdit! :)] Som-hi, doncs!<br />
<br />
Primer de tot, creeu el projecte Laravel i inicialitzeu GIT en cas que no el tingueu penjat a Github o similars:<br />
$ git init<br />
<br />
Tb caldrà afegir un Procfile adequat per Laravel:<br />
$ echo "web: vendor/bin/heroku-php-apache2 public/" > Procfile<br />
<br />
Inicialitzem projecte Heroku:<br />
$ heroku create elmeuprojectedeguais<br />
<br />
Afegim els arxius al repo local:<br />
$ git add .<br />
$ git commit -am "primer commit"<br />
<br />
Afegim la BD PostgreSQL:<br />
$ heroku addons:create heroku-postgresql:hobby-dev<br />
<br />
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:<br />
$ heroku config -s | grep -i post<br />
<br />
Ens ho dona en la següent forma (exemple a continuació):<br />
DATABASE_URL='postgres://<usuari>:<password>@<maquina>:<port>/<bbdd>'<br />
DATABASE_URL='postgres://mxlsfebqyopadb:3e5af56b52cc06574645123ea9d9f7504564e207804dcc71a2db2848446ba064@ec2-156-73-167-43.compute-1.amazonaws.com:5432/d353ihheo564q7'<br />
<br />
Així, doncs, només caldrà ajustar les següents variables d'entorn que necessita el Laravel perquè això funcioni:<br />
DB_CONNECTION=pgsql<br />
DB_HOST=ec2-156...<br />
DB_PORT=5432<br />
DB_DATABASE=d353...<br />
DB_USERNAME=mxls...<br />
DB_PASSWORD=3e5a...<br />
<br />
Per fer-ho cal anar executant les següents ordres:<br />
$ heroku config:set DB_CONNECTION=pgsql<br />
$ ...etc...<br />
<br />
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:<br />
$ cp .env.example .env<br />
$ php artisan key:generate<br />
$ heroku config:set APP_KEY=base64:tX2ikx...<br />
<br />
En acabat, podem posar la app en producció:<br />
$ git add .<br />
$ git push heroku master<br />
<br />
I un cop acabats, migrem la nostra base de dades:<br />
$ heroku run php artisan migrate<br />
<br />
I veure la nostra flamant web en producció (a elmeuprojectedeguais.herokuapp.com):<br />
$ heroku open<br />
<br />
...et voilà!</div>Enrichttps://cacauet.org/wiki/index.php?title=Laravel&diff=4227Laravel2021-02-28T18:31:37Z<p>Enric: /* Laravel 8.x */</p>
<hr />
<div><nowiki>#FpInfor #DawMp07 #DawMp07Uf2 #DawMp07Uf02 #DawMpDual</nowiki><br />
<br />
<br />
== Intro i referències ==<br />
Laravel és un framework web per a PHP que està agafant molta força.<br />
<br />
Documentació oficial: https://laravel.com/docs/<br />
<br />
Tutorials:<br />
* [https://ajgallego.gitbooks.io/laravel-5/content/index.html Principal tutorial per seguir el curs]: <pre>https://ajgallego.gitbooks.io/laravel-5/content/index.html</pre><br />
* Forms: https://selftaughtcoders.com/from-idea-to-launch/lesson-23/laravel-5-application-form-model-binding-laravelcollective-forms-html-library-bootstrap-framework/<br />
* Forms i validació: https://scotch.io/tutorials/simple-laravel-crud-with-resource-controllers<br />
* Apunts del Sergi Coll: https://seicoll.github.io/DAW-M07-UF2-Apunts/<br />
* https://styde.net/laravel-5/<br />
* Per passar del schema SQL (per ex. de MySQL Workbench) a Laravel migration: https://adolfocuadros.com/sql_to_laravel/<br />
<br />
<br />
Plugins:<br />
* CORS (Cross-Origin Resource Sharing): https://github.com/barryvdh/laravel-cors<br />
* CRUD & admin : Hi ha molts plugins per crear ''admin panels'' automàticament. Alguns son:<br />
** Voyager: https://voyager.devdojo.com/<br />
** Craftable: https://www.getcraftable.com/<br />
* https://iamacoder.com/post/5-must-have-laravel-5-packages/<br />
<br />
Temes a ampliar:<br />
* Forms: https://laravel.com/docs/4.2/html<br />
* Validació de forms: https://laravel.com/docs/5.5/validation<br />
* Autenticació: https://laravel.com/docs/5.5/authentication<br />
<br />
<br><br />
<br />
== Instal·lació i setup ==<br />
<br />
Prerequisits:<br />
* Laravel i PHP, és molt important tenir en compte les versions:<br />
** <strike>Laravel 5.3 : PHP >= 5.6.4<br />
** Laravel 5.5 : PHP == 7.0<br />
** Laravel 5.6 : PHP >= 7.1<br />
** Laravel 5.7 : PHP >= 7.1.3</strike><br />
** Laravel 6.x : PHP >= 7.2<br />
* Si utilitzes Ubuntu 14 o menor [https://www.digitalocean.com/community/tutorials/how-to-upgrade-to-php-7-on-ubuntu-14-04 actualitza la teva versió de PHP a la 7.0]<br />
* Calen els paquets següents: <pre>$ sudo apt-get install php-mbstring php-zip php-xml php-mysql</pre><br />
<br />
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...:<br />
# Instal·la el gestor de paquets per PHP Composer<br />
#* El més fàcil és fer: (però no ho farem pq volem la darrera versió)<pre>$ sudo apt install composer</pre><br />
#* Prova primer la instal·lació genèrica : [https://getcomposer.org/download/ Instal.la PHP Composer]<br />
#* També tens aquesta altra forma d' [https://getcomposer.org/doc/00-intro.md#installation-linux-unix-osx instal·lar Composer per GNU/Linux]. Descarrega composer-setup.php i instal·la'l així:<pre>$ php composer-setup.php --install-dir=~/bin --filename=composer</pre><br />
# Instal·la la darrera versió de Laravel<br />
#* https://laravel.com/docs/5.7/installation<br />
#* Bàsicament el què cal fer és aquesta comanda per instal·lar el binari ''laravel'':<pre>$ composer global require laravel/installer</pre><br />
#* Laravel s'instal·la a <code>$HOME/.config/composer</code> però per poder executar les properes comandes necessitarem tenir <code>$HOME/.config/composer/vendor/bin</code> al nostre $PATH. Inserta això al teu <code>$HOME/.profile</code>: <pre>PATH=$PATH:~/.config/composer/vendor/bin</pre><br />
#*: Fes logout/login del sistema per activar aquests canvis<br />
# Crea una app Laravel allà on et faci més ràbia: <pre>$ laravel new laravelapp1</pre><br />
#: o també: <pre>$ composer create-project --prefer-dist laravel/laravel laravelapp1</pre><br />
#: o si volem una versió específica de laravel: <pre>$ composer create-project --prefer-dist laravel/laravel=5.8.* laravelapp1</pre><br />
# Arrenca l'aplicació de prova: <pre>$ php artisan serve</pre><br />
# Comprova la app amb el navegador a<pre>http://localhost:8000</pre><br />
<br />
<br><br />
<br />
Si ja has completat la instal·lació, pots procedir a crear un altre projecte nou i realitzar el següent tutorial "tasklist":<br />
https://laravel.com/docs/5.2/quickstart<br />
<br />
<br><br />
<br />
== Incidències vàries ==<br />
Aquest és un bon tutorial:<br />
https://ajgallego.gitbooks.io/laravel-5/content/index.html<br />
<br />
Igualment, podríem trobar algunes incidències. Us dono pistes:<br />
<br />
=== Treballant amb GIT i clonant ===<br />
Al pujar el projecte a un repo GIT, i clonar-lo després caldrà:<br />
# Re-instal·lar les dependències:<pre>$ composer install</pre><br />
# Regenerar arxiu <code>.env</code> : com que depèn de cada entorn no es fica al projecte (es posa a <code>.gitignore</code>), però pots copiar i modificar de <code>.env.example</code><br />
# Error ''The only supported ciphers are AES-128-CBC and AES-256-CBC with the correct key lengths.'' Es soluciona amb :<pre>$ php artisan key:generate</pre><br />
<br />
=== Creant controllers amb CRUD complert ===<br />
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.<br />
# Ja no es pot fer amb <strike><code>Route::controller</code></strike> sinó amb:<pre>Route::resource("cosa","CosaController");</pre><br />
# Per exemple, per crear un controller per al model "Cosa" ho faríem amb -r (de resource): <pre>$ php artisan make:controller -r CosaController</pre><br />
<br />
=== Treballant amb SQLite ===<br />
Per configurar la BD amb SQLite cal crear el fitxer abans amb:<br />
$ touch db.sqlite<br />
<br />
Configurar la BD a .env:<br />
DB_CONNECTION=sqlite<br />
DB_DATABASE=/path/absolut/al/db.sqlite<br />
<br />
Instal·lar els binaris necessaris de SQLite i de PHP:<br />
$ sudo apt-get install sqlite php-sqlite3<br />
<br />
I crear la BD inicial amb:<br />
$ php artisan migrate<br />
<br />
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.<br />
<br />
=== Eliminant models o migracions ===<br />
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:<br />
$ composer dump-autoload<br />
...i es tornaran a generar els arxius d'autoload sense els arxius que volíem esborrar.<br />
<br />
=== Treballant amb proxies i composer ===<br />
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):<br />
$ composer update<br />
Loading composer repositories with package information<br />
Updating dependencies (including require-dev)<br />
(...demana user/password de packagist.org ...)<br />
<br />
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:<br />
$ ssh -L 3128:localhost:3128 jo@elmeuserver.com<br />
I un cop logats, aprofitem per instal·lar el squid:<br />
$ sudo apt install squid<br />
Hem de mantenir la shell oberta mentre vulguem que estigui activat el túnel (l'hem assignat a localhost:3128).<br />
<br />
Obrim una altra shell i anem al nostre projecte Laravel:<br />
$ export http_proxy=localhost:3128<br />
$ composer update<br />
<br />
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).<br />
<br />
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:<br />
$ ssh jo@elmeuserver.com<br />
$ sudo apt remove squid<br />
<br />
<br><br />
<br />
== Tutorials ==<br />
Després d'elaborar la documentació he trobat aquest tutorial bastant útil (només fins la v5.2):<br />
https://laravel.com/docs/5.2/quickstart<br />
<br />
Tutorial per a CRUD complert:<br />
https://www.itsolutionstuff.com/post/laravel-6-crud-application-tutorialexample.html<br />
<br />
== Resum per a fer un CRUD ==<br />
<br />
=== Setup projecte ===<br />
Crear projecte:<br />
$ laravel new proj1<br />
Crear DB (en aquest cas SQLite:<br />
$ touch db.sqlite<br />
Modifica .env per configurar la DB com sqlite:<br />
DB_CONNECTION=sqlite<br />
DB_DATABASE=/path/absolut/al/db.sqlite<br />
<br />
=== Model ===<br />
Crear taules i migracions:<br />
$ php artisan make:migration crea_taula_items --create=items<br />
Editar la migració per crear les taules adequades. Mira't les principals referències:<br />
* [https://laravel.com/docs/5.5/migrations#columns Tipus de columnes]<br />
* [https://laravel.com/docs/5.5/migrations#foreign-key-constraints Relacions i FKs]<br />
Realitzar la migració:<br />
$ php artisan migrate<br />
Crear models:<br />
$ php artisan make:model Item<br />
Ajusta el model perquè apunti al nom correcte de la taula:<br />
https://laravel.com/docs/5.5/eloquent#eloquent-model-conventions<br />
<br />
=== Controller i rutes ===<br />
Crear controllers amb els mètodes estàndard (index, create-store, show, edit-update, destroy):<br />
$ php artisan make:controller -r ItemController<br />
Crear rutes a <code>routes/web.php</code>:<br />
Route::resource("item","ItemController");<br />
Crear plantilles per als mètodes (l'exemple diu "tema" enlloc de "item"):<br />
$ php artisan route:list<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
| Domain | Method | URI | Name | Action | Middleware |<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
| | GET|HEAD | / | | Closure | web |<br />
| | GET|HEAD | api/user | | Closure | api,auth:api |<br />
| | GET|HEAD | tema | tema.index | App\Http\Controllers\TemaController@index | web |<br />
| | POST | tema | tema.store | App\Http\Controllers\TemaController@store | web |<br />
| | GET|HEAD | tema/create | tema.create | App\Http\Controllers\TemaController@create | web |<br />
| | GET|HEAD | tema/{tema} | tema.show | App\Http\Controllers\TemaController@show | web |<br />
| | PUT|PATCH | tema/{tema} | tema.update | App\Http\Controllers\TemaController@update | web |<br />
| | DELETE | tema/{tema} | tema.destroy | App\Http\Controllers\TemaController@destroy | web |<br />
| | GET|HEAD | tema/{tema}/edit | tema.edit | App\Http\Controllers\TemaController@edit | web |<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
<br />
Crear les views (plantilles blade) adequades per a tots els mètodes necessaris (els arxius van a <code>resources/views</code>). Pots veure [https://github.com/emieza/laravel-karaoke/tree/master/resources/views/llista aqui] alguns exemples.<br />
* '''index''' : llista tots els elements<br />
* '''show''' : mostra un element en concret, necessita que li passem un paràmetre per GET (id del element a mostrar)<br />
* '''create-store''' : "create és el form (no necessita codi), i "store" és el codi per insertar-ho a la BD (no necessita una plantilla)<br />
* '''edit-update''' : "edit" és el form, i "update" el codi per actualitzar la BD<br />
* '''destroy''' : elimina un element<br />
<br />
=== Codi del Controller i View ===<br />
* Crear views amb formularis d'entrada de dades: [https://github.com/emieza/laravel-karaoke/blob/master/resources/views/llista/crea.blade.php create.blade.php d'exemple]<br />
* Editar el codi del Controller per cridar pertinentment a les views: [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/LlistaController.php Controller d'exemple]<br />
<br />
=== Més docs ===<br />
Una bona referència de la doc oficial per fer un CRUD és aquesta:<br />
https://laravel.com/docs/5.2/quickstart<br />
En particular per veure com utilitzar les templates oficials amb bootstrap ;)<br />
<br />
<br><br />
<br />
== Projecte d'exemple ==<br />
Aquest és el projecte que he realitzat per entrenar-me, et pot servir d'exemple. El pots veure en producció aquí: https://jolgorio.tk<br />
https://github.com/emieza/laravel-karaoke<br />
<br />
Fes-li un cop d'ull al readme.md per veure com posar-lo en marxa.<br />
<br />
MOLT IMPORTANT PEL PROJECTE: Cal crear un README.md (com [https://github.com/emieza/laravel-karaoke/blob/master/readme.md per exemple aquest]). No acceptaré cap projecte sense README.md<br />
<br />
Per entrenar-vos amb el Markdown teniu aquest tester:<br />
http://dillinger.io/<br />
<br />
Anem per feina:<br />
# Taules: llistes, temes, vots<br />
# Rutes que vols implementar per al projecte. [https://github.com/emieza/laravel-karaoke/blob/master/routes/web.php En el meu cas, tinc]:<br />
#* /llista/crea (GET per formulari + POST per store)<br />
#* /llista (index de llistes)<br />
#* /llista/{id} (show)<br />
#* /llista/{id}/crea (GET + POST, per crear temes en les llistes)<br />
#* /vota/{idtema}<br />
# Codi:<br />
#* als Controllers pertinents. Mira't l'[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/LlistaController.php exemple de les llistes de karaoke].<br />
#* Plantilles: a resources/views/xxxx.blade.php . Mira't l'[https://github.com/emieza/laravel-karaoke/tree/master/resources/views/llista exemple un altre cop].<br />
<br />
<br><br />
<br />
== ORM : Models i relacions ==<br />
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.<br />
<br />
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. <br />
<br />
El què anem a explicar està documentat a l'apartat "Eloquent ORM" de Laravel:<br />
https://laravel.com/docs/5.7/eloquent-relationships<br />
https://laravel.com/docs/6.x/eloquent-relationships<br />
<br />
=== Accedint relacions 1-N de forma directa ===<br />
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í.<br />
<br />
L'objectiu serà poder accedir a l'objecte pare d'aquesta manera per mostrar el text del Post (pare).<br />
<syntaxhighlight lang="php"><br />
$comment = Comment::find(33);<br />
echo $comment->post->text;<br />
</syntaxhighlight><br />
<br />
Per aconseguir això, cal que indiquem la relació existent a les taules entre els models Post i Comment amb la relació <code>belongsTo</code>:<br />
<br />
<syntaxhighlight lang="php"><br />
<?php<br />
namespace App;<br />
use Illuminate\Database\Eloquent\Model;<br />
class Comment extends Model<br />
{<br />
/**<br />
* Accedeix al pare (Post)<br />
*/<br />
public function post()<br />
{<br />
return $this->belongsTo('App\Post','post_id');<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Accedint relacions 1-N de forma inversa ===<br />
El següent cas típic serà accedir des d'un objecte Post als diferents Comentaris, més o menys així:<br />
<br />
<syntaxhighlight lang="php"><br />
$comments = App\Post::find(1)->comments;<br />
foreach ($comments as $comment) {<br />
// ... el teu codi...<br />
echo $comment->text;<br />
}<br />
</syntaxhighlight><br />
El codi que veiem és per a un ''controller'', però es pot aplicar també als ''templates'', amb @foreach i similars.<br />
<br />
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<br />
<syntaxhighlight lang="php"><br />
<?php<br />
namespace App;<br />
use Illuminate\Database\Eloquent\Model;<br />
class Post extends Model<br />
{<br />
/**<br />
* Accedeix als comentaris relacionats amb el Post actual<br />
*/<br />
public function comments()<br />
{<br />
return $this->hasMany('App\Comment','<ref_remota>','<ref_local>');<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
On:<br />
* <ref_remota> és el camp de la taula de Comment que referencia el Post<br />
* <ref_local> és el camp de Post que fa de PK i on Comment apunta<br />
<br />
Per accedir al objecte relacionat "pare" caldrà fer una altra funció, en concret ''belongsTo''. Consulta la doc de les relacions 1-a-N (inversa).<br />
<br />
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:<br />
https://laravel.com/docs/5.5/eloquent-relationships#one-to-many<br />
<br />
=== Aniuant JSON en la API ===<br />
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:<br />
<br />
<syntaxhighlight lang="php"><br />
<?php<br />
Route::get("/comentaris", function() {<br />
$post = Post::with("comments")->get();<br />
return $post;<br />
});<br />
</syntaxhighlight><br />
<br />
...i ens retornarà les dades aniuades que volem! :)<br />
<br />
<br><br />
<br />
== Més coses ==<br />
Alguns temes que no hem aprofundit però que convé conèixer.<br />
<br />
=== Autenticació ===<br />
Senzill d'implementar i imprescindible. Laravel incorpora un ''scaffold'' per facilitar una funció tan estàndard.<br />
Amb una sola instrucció ens crea les rutes, vistes i els controllers típics (login, logout).<br />
<br />
==== Laravel 5.x ====<br />
[https://laravel.com/docs/5.5/authentication Autenticació en Laravel 5.x]:<br />
$ php artisan make:auth<br />
<br />
==== Laravel 6.x ====<br />
[https://laravel.com/docs/6.x/authentication Autenticació en Laravel 6.x]:<br />
$ composer require laravel/ui --dev<br />
$ php artisan ui vue --auth<br />
<br />
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:<br />
$ npm install && npm run dev<br />
<br />
També hi ha [https://laracasts.com/discuss/channels/laravel/laravel-60-appcss?page=1 solucions al problema carregant els CSS i JS del CDN] (només cal canviar un link en el ''head'' de <code>app.blade.php</code>.<br />
<br />
==== Laravel 8.x ====<br />
Ara el mòdul d'autenticació es diu [https://laravel.com/docs/8.x/starter-kits#laravel-breeze Laravel Breeze].<br />
<br />
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:<br />
* '''routes/web.php'''<br />
* '''resources/views/layouts/app.blade.php'''<br />
* resources/views/layouts/guest.blade.php<br />
* resources/views/layouts/navigation.blade.php<br />
* resources/views/auth/*<br />
* resources/views/components/*<br />
* resources/views/welcome.blade.php<br />
* resources/views/dashboard.blade.php<br />
<br />
Resumint, per instal·lar Breeze:<br />
$ composer require laravel/breeze --dev<br />
$ php artisan breeze:install<br />
$ npm install<br />
$ npm run dev<br />
<br />
==== Rols d'usuari ====<br />
En molts moments pot interessar tenir diversos rols d'usuari (admin, usuari, redactor, etc.).<br />
<br />
[https://medium.com/@otimfredrick/how-to-protect-admin-panel-route-in-laravel-70bb86168d87 Aquest post explica com utiltizar rols d'usuari] amb els sistemes bàsics d'autenticació de Laravel (Breeze, etc.).<br />
<br />
=== Seeding ===<br />
Una part molt important és la de crear dades per farcir la base de dades inicialment i poder així testejar amb comoditat.<br />
<br />
https://laravel.com/docs/6.x/seeding<br />
<br />
En algun moment donat convé utilitzar un ''factory'' que ens permet crear elements en massa:<br />
<br />
https://laravel.com/docs/6.x/database-testing#writing-factories<br />
<br />
El ''factory'' sol utilitzar una llibreria <code>Faker</code> que ens va molt bé per crear noms i cognoms aleatoris, lorem ipsum, etc. que ens facilitarà la creació de dades de prova.<br />
<br />
https://github.com/fzaninotto/Faker<br />
<br />
=== Validacions ===<br />
Laravel ens ofereix un mecanisme de validació de formularis molt potent i efectiu.<br />
<br />
https://laravel.com/docs/5.5/validation<br />
<br />
=== Sessions ===<br />
D'entrada és molt útil per emetre missatges "flash", i informar l'usuari del processament intern.<br />
<br />
https://laravel.com/docs/5.5/session<br />
<br />
=== Arxius: filesystem vs BLOBs en BD ===<br />
Les imatges es poden guardar al sistema d'arxius o bé a la base de dades.<br />
* '''Filesystem''': En el propi tutorial hi ha una explicació de [https://ajgallego.gitbooks.io/laravel-5/content/capitulo_4_datos_de_entrada.html com guardar binaris amb el mètode clàssic del filesystem]<br />
* '''BLOBs en la BD''': Laravel ens permet crear models amb BLOBs i insertar les dades a la BD:<br />
** [https://www.daniweb.com/programming/web-development/threads/480731/how-to-inserting-files-on-mysql-using-laravel Insertant BLOBs amb Larvel]<br />
** Tingueu en compte, si ho feu així, de [https://stackoverflow.com/questions/8499633/how-to-display-base64-images-in-html com renderitzar continguts base64 (BLOBs) sobre un HTML]<br />
<br />
=== A solucionar ===<br />
Alguns temes a solucionar:<br />
* Quan utilitzem el scaffold d'autenticació, falla el logout. Això es deu a un canvi del mètode de GET a POST per motius de seguretat (amb POST, només podran fer logout des de la pròpia app Laravel ja que porta el csrf_token).<br />
*: https://laracasts.com/discuss/channels/laravel/laravel-53-logout-methodnotallowed<br />
<br />
<br><br />
<br />
=== Atacant 2 bases de dades simultàniament ===<br />
En alguns casos podem necessitar configurar 2 instàncies de bases de dades separades per optimitzar el rendiment. Aquest post ho explica molt bé:<br />
https://fideloper.com/laravel-multiple-database-connections<br />
<br />
Caldrà configurar el .env , config/database.php i especificar quina DB ataca en les migracions i en els models que creem.<br />
<br />
<br><br />
<br />
== Laravel i LDAP ==<br />
Aquest mòdul està pensat per a Active Directory, però [https://github.com/Adldap2/Adldap2-Laravel/issues/106 també funciona amb OpenLDAP si s'ajusta bé]:<br />
https://github.com/Adldap2/Adldap2-Laravel<br />
<br />
Primer cal configurar un servidor [[LDAP]].<br />
<br />
Després, tingues en compte que cal ajustar els següents paràmetres en el .env:<br />
ADLDAP_CONTROLLERS=localhost<br />
#ADLDAP_PORT=389<br />
ADLDAP_ADMIN_USERNAME="cn=admin,dc=cacauet,dc=org"<br />
ADLDAP_ADMIN_PASSWORD="enric123"<br />
ADLDAP_BASEDN="dc=cacauet,dc=org"<br />
<br />
Podem fer una autenticació seguint algun d'aquests exemples.<br />
<br />
Exemple 1: cercar un element del directori<br />
<syntaxhighlight lang="php"><br />
$user = Adldap::search()->where("mail","=","pepe@jolgorio.tk")->get();<br />
</syntaxhighlight><br />
<br />
Exemple 2: autenticar un usuari<br />
<syntaxhighlight lang="php"><br />
if( Adldap::auth()->attempt("cn=pepe,ou=usuaris,dc=cacauet,dc=org","pepe123")) {<br />
// autenticació exitosa<br />
return "Pepe OK!";<br />
}<br />
</syntaxhighlight><br />
<br />
<br><br />
<br />
== Laravel en producció ==<br />
Per posar en producció un projecte basat en Laravel cal tenir en compte:<br />
* '''IMPORTANT, SEGURETAT: Només cal publicar la carpeta <code>/public</code>''' . 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 .<br />
** Aquesta carpeta <code>/public</code> no figura inicialment quan creem o clonem un projecte (està a .gitignore), a l'igual que la carpeta <code>/vendor</code>, que es generen quan fem un <code>$ composer install</code>.<br />
** Reviseu la secció [[Laravel#Treballant_amb_GIT_i_clonant]] per fer el setup del projecte després de clonar.<br />
* '''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'').<br />
* 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:<br />
** db.sqlite (si s'escau)<br />
** carpeta <code>/storage</code><br />
** carpeta <code>/bootstrap/cache</code><br />
<br />
=== Desplegament en AWS amb Ubuntu i Apache ===<br />
Guia pel desplegament en Ubuntu amb Apache:<br />
* Accedir al nostre servidor via SSH<br />
* 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<pre>/var/www</pre><br />
* Per veure detalls reviseu la secció [[Laravel#Treballant_amb_GIT_i_clonant]]. Recordeu que això implica: <br />
*# composer install<br />
*# configurar arxiu .env<br />
*# generar clau<br />
* Es requereix el mòdul ''mod_rewrite'' d'Apache (o Nginx)<pre>$ sudo a2enmod rewrite</pre><br />
* Publicar la carpeta <code>/public</code> del projecte Laravel, d'alguna d'aquestes maneres:<br />
** Crear un VirtualHost i apuntar la ServerRoot del domini o subdomini a /var/www/<projecte>/public<br />
** Crear un link simbòlic de la carpeta pública d'Apache a la carpeta public del Laravel amb la comanda <pre>$ ln -s /var/www/<projecte>/public /var/www/html/lara1</pre><br />
* 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".<br />
* Ajusta els permisos de:<br />
** db.sqlite (si s'escau) i també de la carpeta que el conté (si no, no es podrà escriure-hi)<br />
** carpeta <code>/storage</code><br />
** carpeta <code>/bootstrap/cache</code><br />
* Cal activar els arxius <code>.htaccess</code> , afegint la directiva <code>AllowOverride all</code><br />
<br />
A l'arxiu de conf. del nostre VirtualHost (a <code>/etc/apache2/sites-available</code>):<br />
<Directory /var/www/><br />
AllowOverride All<br />
</Directory><br />
<br />
<br />
És important remarcar que per SEGURETAT no hem de mostrar mai els arxius interns de Laravel, només cal publicar el contingut de /public<br />
<br />
<br><br />
<br />
=== Heroku ===<br />
Abans de procedir amb aquesta part hauries de llegir i treballar aquesta altra: [[Heroku]] on treballem amb PHP simple.<br />
<br />
Pots posar en marxa un projecte Laravel a Heroku fàcilment seguint aquesta documentació. Segueix el tutorial per iniciar la app:<br />
https://devcenter.heroku.com/articles/getting-started-with-laravel<br />
<br />
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.<br />
<br />
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.<br />
<br />
En canvi, [https://devcenter.heroku.com/articles/heroku-postgresql el add-on de POSTGRESQL és gratuït i sense targeta de crèdit! :)] Som-hi, doncs!<br />
<br />
Primer de tot, creeu el projecte Laravel i inicialitzeu GIT en cas que no el tingueu penjat a Github o similars:<br />
$ git init<br />
<br />
Tb caldrà afegir un Procfile adequat per Laravel:<br />
$ echo "web: vendor/bin/heroku-php-apache2 public/" > Procfile<br />
<br />
Inicialitzem projecte Heroku:<br />
$ heroku create elmeuprojectedeguais<br />
<br />
Afegim els arxius al repo local:<br />
$ git add .<br />
$ git commit -am "primer commit"<br />
<br />
Afegim la BD PostgreSQL:<br />
$ heroku addons:create heroku-postgresql:hobby-dev<br />
<br />
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:<br />
$ heroku config -s | grep -i post<br />
<br />
Ens ho dona en la següent forma (exemple a continuació):<br />
DATABASE_URL='postgres://<usuari>:<password>@<maquina>:<port>/<bbdd>'<br />
DATABASE_URL='postgres://mxlsfebqyopadb:3e5af56b52cc06574645123ea9d9f7504564e207804dcc71a2db2848446ba064@ec2-156-73-167-43.compute-1.amazonaws.com:5432/d353ihheo564q7'<br />
<br />
Així, doncs, només caldrà ajustar les següents variables d'entorn que necessita el Laravel perquè això funcioni:<br />
DB_CONNECTION=pgsql<br />
DB_HOST=ec2-156...<br />
DB_PORT=5432<br />
DB_DATABASE=d353...<br />
DB_USERNAME=mxls...<br />
DB_PASSWORD=3e5a...<br />
<br />
Per fer-ho cal anar executant les següents ordres:<br />
$ heroku config:set DB_CONNECTION=pgsql<br />
$ ...etc...<br />
<br />
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:<br />
$ cp .env.example .env<br />
$ php artisan key:generate<br />
$ heroku config:set APP_KEY=base64:tX2ikx...<br />
<br />
En acabat, podem posar la app en producció:<br />
$ git add .<br />
$ git push heroku master<br />
<br />
I un cop acabats, migrem la nostra base de dades:<br />
$ heroku run php artisan migrate<br />
<br />
I veure la nostra flamant web en producció (a elmeuprojectedeguais.herokuapp.com):<br />
$ heroku open<br />
<br />
...et voilà!</div>Enrichttps://cacauet.org/wiki/index.php?title=Laravel&diff=4226Laravel2021-02-10T00:03:49Z<p>Enric: /* Laravel 8.x */</p>
<hr />
<div><nowiki>#FpInfor #DawMp07 #DawMp07Uf2 #DawMp07Uf02 #DawMpDual</nowiki><br />
<br />
<br />
== Intro i referències ==<br />
Laravel és un framework web per a PHP que està agafant molta força.<br />
<br />
Documentació oficial: https://laravel.com/docs/<br />
<br />
Tutorials:<br />
* [https://ajgallego.gitbooks.io/laravel-5/content/index.html Principal tutorial per seguir el curs]: <pre>https://ajgallego.gitbooks.io/laravel-5/content/index.html</pre><br />
* Forms: https://selftaughtcoders.com/from-idea-to-launch/lesson-23/laravel-5-application-form-model-binding-laravelcollective-forms-html-library-bootstrap-framework/<br />
* Forms i validació: https://scotch.io/tutorials/simple-laravel-crud-with-resource-controllers<br />
* Apunts del Sergi Coll: https://seicoll.github.io/DAW-M07-UF2-Apunts/<br />
* https://styde.net/laravel-5/<br />
* Per passar del schema SQL (per ex. de MySQL Workbench) a Laravel migration: https://adolfocuadros.com/sql_to_laravel/<br />
<br />
<br />
Plugins:<br />
* CORS (Cross-Origin Resource Sharing): https://github.com/barryvdh/laravel-cors<br />
* CRUD & admin : Hi ha molts plugins per crear ''admin panels'' automàticament. Alguns son:<br />
** Voyager: https://voyager.devdojo.com/<br />
** Craftable: https://www.getcraftable.com/<br />
* https://iamacoder.com/post/5-must-have-laravel-5-packages/<br />
<br />
Temes a ampliar:<br />
* Forms: https://laravel.com/docs/4.2/html<br />
* Validació de forms: https://laravel.com/docs/5.5/validation<br />
* Autenticació: https://laravel.com/docs/5.5/authentication<br />
<br />
<br><br />
<br />
== Instal·lació i setup ==<br />
<br />
Prerequisits:<br />
* Laravel i PHP, és molt important tenir en compte les versions:<br />
** <strike>Laravel 5.3 : PHP >= 5.6.4<br />
** Laravel 5.5 : PHP == 7.0<br />
** Laravel 5.6 : PHP >= 7.1<br />
** Laravel 5.7 : PHP >= 7.1.3</strike><br />
** Laravel 6.x : PHP >= 7.2<br />
* Si utilitzes Ubuntu 14 o menor [https://www.digitalocean.com/community/tutorials/how-to-upgrade-to-php-7-on-ubuntu-14-04 actualitza la teva versió de PHP a la 7.0]<br />
* Calen els paquets següents: <pre>$ sudo apt-get install php-mbstring php-zip php-xml php-mysql</pre><br />
<br />
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...:<br />
# Instal·la el gestor de paquets per PHP Composer<br />
#* El més fàcil és fer: (però no ho farem pq volem la darrera versió)<pre>$ sudo apt install composer</pre><br />
#* Prova primer la instal·lació genèrica : [https://getcomposer.org/download/ Instal.la PHP Composer]<br />
#* També tens aquesta altra forma d' [https://getcomposer.org/doc/00-intro.md#installation-linux-unix-osx instal·lar Composer per GNU/Linux]. Descarrega composer-setup.php i instal·la'l així:<pre>$ php composer-setup.php --install-dir=~/bin --filename=composer</pre><br />
# Instal·la la darrera versió de Laravel<br />
#* https://laravel.com/docs/5.7/installation<br />
#* Bàsicament el què cal fer és aquesta comanda per instal·lar el binari ''laravel'':<pre>$ composer global require laravel/installer</pre><br />
#* Laravel s'instal·la a <code>$HOME/.config/composer</code> però per poder executar les properes comandes necessitarem tenir <code>$HOME/.config/composer/vendor/bin</code> al nostre $PATH. Inserta això al teu <code>$HOME/.profile</code>: <pre>PATH=$PATH:~/.config/composer/vendor/bin</pre><br />
#*: Fes logout/login del sistema per activar aquests canvis<br />
# Crea una app Laravel allà on et faci més ràbia: <pre>$ laravel new laravelapp1</pre><br />
#: o també: <pre>$ composer create-project --prefer-dist laravel/laravel laravelapp1</pre><br />
#: o si volem una versió específica de laravel: <pre>$ composer create-project --prefer-dist laravel/laravel=5.8.* laravelapp1</pre><br />
# Arrenca l'aplicació de prova: <pre>$ php artisan serve</pre><br />
# Comprova la app amb el navegador a<pre>http://localhost:8000</pre><br />
<br />
<br><br />
<br />
Si ja has completat la instal·lació, pots procedir a crear un altre projecte nou i realitzar el següent tutorial "tasklist":<br />
https://laravel.com/docs/5.2/quickstart<br />
<br />
<br><br />
<br />
== Incidències vàries ==<br />
Aquest és un bon tutorial:<br />
https://ajgallego.gitbooks.io/laravel-5/content/index.html<br />
<br />
Igualment, podríem trobar algunes incidències. Us dono pistes:<br />
<br />
=== Treballant amb GIT i clonant ===<br />
Al pujar el projecte a un repo GIT, i clonar-lo després caldrà:<br />
# Re-instal·lar les dependències:<pre>$ composer install</pre><br />
# Regenerar arxiu <code>.env</code> : com que depèn de cada entorn no es fica al projecte (es posa a <code>.gitignore</code>), però pots copiar i modificar de <code>.env.example</code><br />
# Error ''The only supported ciphers are AES-128-CBC and AES-256-CBC with the correct key lengths.'' Es soluciona amb :<pre>$ php artisan key:generate</pre><br />
<br />
=== Creant controllers amb CRUD complert ===<br />
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.<br />
# Ja no es pot fer amb <strike><code>Route::controller</code></strike> sinó amb:<pre>Route::resource("cosa","CosaController");</pre><br />
# Per exemple, per crear un controller per al model "Cosa" ho faríem amb -r (de resource): <pre>$ php artisan make:controller -r CosaController</pre><br />
<br />
=== Treballant amb SQLite ===<br />
Per configurar la BD amb SQLite cal crear el fitxer abans amb:<br />
$ touch db.sqlite<br />
<br />
Configurar la BD a .env:<br />
DB_CONNECTION=sqlite<br />
DB_DATABASE=/path/absolut/al/db.sqlite<br />
<br />
Instal·lar els binaris necessaris de SQLite i de PHP:<br />
$ sudo apt-get install sqlite php-sqlite3<br />
<br />
I crear la BD inicial amb:<br />
$ php artisan migrate<br />
<br />
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.<br />
<br />
=== Eliminant models o migracions ===<br />
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:<br />
$ composer dump-autoload<br />
...i es tornaran a generar els arxius d'autoload sense els arxius que volíem esborrar.<br />
<br />
=== Treballant amb proxies i composer ===<br />
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):<br />
$ composer update<br />
Loading composer repositories with package information<br />
Updating dependencies (including require-dev)<br />
(...demana user/password de packagist.org ...)<br />
<br />
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:<br />
$ ssh -L 3128:localhost:3128 jo@elmeuserver.com<br />
I un cop logats, aprofitem per instal·lar el squid:<br />
$ sudo apt install squid<br />
Hem de mantenir la shell oberta mentre vulguem que estigui activat el túnel (l'hem assignat a localhost:3128).<br />
<br />
Obrim una altra shell i anem al nostre projecte Laravel:<br />
$ export http_proxy=localhost:3128<br />
$ composer update<br />
<br />
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).<br />
<br />
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:<br />
$ ssh jo@elmeuserver.com<br />
$ sudo apt remove squid<br />
<br />
<br><br />
<br />
== Tutorials ==<br />
Després d'elaborar la documentació he trobat aquest tutorial bastant útil (només fins la v5.2):<br />
https://laravel.com/docs/5.2/quickstart<br />
<br />
Tutorial per a CRUD complert:<br />
https://www.itsolutionstuff.com/post/laravel-6-crud-application-tutorialexample.html<br />
<br />
== Resum per a fer un CRUD ==<br />
<br />
=== Setup projecte ===<br />
Crear projecte:<br />
$ laravel new proj1<br />
Crear DB (en aquest cas SQLite:<br />
$ touch db.sqlite<br />
Modifica .env per configurar la DB com sqlite:<br />
DB_CONNECTION=sqlite<br />
DB_DATABASE=/path/absolut/al/db.sqlite<br />
<br />
=== Model ===<br />
Crear taules i migracions:<br />
$ php artisan make:migration crea_taula_items --create=items<br />
Editar la migració per crear les taules adequades. Mira't les principals referències:<br />
* [https://laravel.com/docs/5.5/migrations#columns Tipus de columnes]<br />
* [https://laravel.com/docs/5.5/migrations#foreign-key-constraints Relacions i FKs]<br />
Realitzar la migració:<br />
$ php artisan migrate<br />
Crear models:<br />
$ php artisan make:model Item<br />
Ajusta el model perquè apunti al nom correcte de la taula:<br />
https://laravel.com/docs/5.5/eloquent#eloquent-model-conventions<br />
<br />
=== Controller i rutes ===<br />
Crear controllers amb els mètodes estàndard (index, create-store, show, edit-update, destroy):<br />
$ php artisan make:controller -r ItemController<br />
Crear rutes a <code>routes/web.php</code>:<br />
Route::resource("item","ItemController");<br />
Crear plantilles per als mètodes (l'exemple diu "tema" enlloc de "item"):<br />
$ php artisan route:list<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
| Domain | Method | URI | Name | Action | Middleware |<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
| | GET|HEAD | / | | Closure | web |<br />
| | GET|HEAD | api/user | | Closure | api,auth:api |<br />
| | GET|HEAD | tema | tema.index | App\Http\Controllers\TemaController@index | web |<br />
| | POST | tema | tema.store | App\Http\Controllers\TemaController@store | web |<br />
| | GET|HEAD | tema/create | tema.create | App\Http\Controllers\TemaController@create | web |<br />
| | GET|HEAD | tema/{tema} | tema.show | App\Http\Controllers\TemaController@show | web |<br />
| | PUT|PATCH | tema/{tema} | tema.update | App\Http\Controllers\TemaController@update | web |<br />
| | DELETE | tema/{tema} | tema.destroy | App\Http\Controllers\TemaController@destroy | web |<br />
| | GET|HEAD | tema/{tema}/edit | tema.edit | App\Http\Controllers\TemaController@edit | web |<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
<br />
Crear les views (plantilles blade) adequades per a tots els mètodes necessaris (els arxius van a <code>resources/views</code>). Pots veure [https://github.com/emieza/laravel-karaoke/tree/master/resources/views/llista aqui] alguns exemples.<br />
* '''index''' : llista tots els elements<br />
* '''show''' : mostra un element en concret, necessita que li passem un paràmetre per GET (id del element a mostrar)<br />
* '''create-store''' : "create és el form (no necessita codi), i "store" és el codi per insertar-ho a la BD (no necessita una plantilla)<br />
* '''edit-update''' : "edit" és el form, i "update" el codi per actualitzar la BD<br />
* '''destroy''' : elimina un element<br />
<br />
=== Codi del Controller i View ===<br />
* Crear views amb formularis d'entrada de dades: [https://github.com/emieza/laravel-karaoke/blob/master/resources/views/llista/crea.blade.php create.blade.php d'exemple]<br />
* Editar el codi del Controller per cridar pertinentment a les views: [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/LlistaController.php Controller d'exemple]<br />
<br />
=== Més docs ===<br />
Una bona referència de la doc oficial per fer un CRUD és aquesta:<br />
https://laravel.com/docs/5.2/quickstart<br />
En particular per veure com utilitzar les templates oficials amb bootstrap ;)<br />
<br />
<br><br />
<br />
== Projecte d'exemple ==<br />
Aquest és el projecte que he realitzat per entrenar-me, et pot servir d'exemple. El pots veure en producció aquí: https://jolgorio.tk<br />
https://github.com/emieza/laravel-karaoke<br />
<br />
Fes-li un cop d'ull al readme.md per veure com posar-lo en marxa.<br />
<br />
MOLT IMPORTANT PEL PROJECTE: Cal crear un README.md (com [https://github.com/emieza/laravel-karaoke/blob/master/readme.md per exemple aquest]). No acceptaré cap projecte sense README.md<br />
<br />
Per entrenar-vos amb el Markdown teniu aquest tester:<br />
http://dillinger.io/<br />
<br />
Anem per feina:<br />
# Taules: llistes, temes, vots<br />
# Rutes que vols implementar per al projecte. [https://github.com/emieza/laravel-karaoke/blob/master/routes/web.php En el meu cas, tinc]:<br />
#* /llista/crea (GET per formulari + POST per store)<br />
#* /llista (index de llistes)<br />
#* /llista/{id} (show)<br />
#* /llista/{id}/crea (GET + POST, per crear temes en les llistes)<br />
#* /vota/{idtema}<br />
# Codi:<br />
#* als Controllers pertinents. Mira't l'[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/LlistaController.php exemple de les llistes de karaoke].<br />
#* Plantilles: a resources/views/xxxx.blade.php . Mira't l'[https://github.com/emieza/laravel-karaoke/tree/master/resources/views/llista exemple un altre cop].<br />
<br />
<br><br />
<br />
== ORM : Models i relacions ==<br />
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.<br />
<br />
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. <br />
<br />
El què anem a explicar està documentat a l'apartat "Eloquent ORM" de Laravel:<br />
https://laravel.com/docs/5.7/eloquent-relationships<br />
https://laravel.com/docs/6.x/eloquent-relationships<br />
<br />
=== Accedint relacions 1-N de forma directa ===<br />
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í.<br />
<br />
L'objectiu serà poder accedir a l'objecte pare d'aquesta manera per mostrar el text del Post (pare).<br />
<syntaxhighlight lang="php"><br />
$comment = Comment::find(33);<br />
echo $comment->post->text;<br />
</syntaxhighlight><br />
<br />
Per aconseguir això, cal que indiquem la relació existent a les taules entre els models Post i Comment amb la relació <code>belongsTo</code>:<br />
<br />
<syntaxhighlight lang="php"><br />
<?php<br />
namespace App;<br />
use Illuminate\Database\Eloquent\Model;<br />
class Comment extends Model<br />
{<br />
/**<br />
* Accedeix al pare (Post)<br />
*/<br />
public function post()<br />
{<br />
return $this->belongsTo('App\Post','post_id');<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Accedint relacions 1-N de forma inversa ===<br />
El següent cas típic serà accedir des d'un objecte Post als diferents Comentaris, més o menys així:<br />
<br />
<syntaxhighlight lang="php"><br />
$comments = App\Post::find(1)->comments;<br />
foreach ($comments as $comment) {<br />
// ... el teu codi...<br />
echo $comment->text;<br />
}<br />
</syntaxhighlight><br />
El codi que veiem és per a un ''controller'', però es pot aplicar també als ''templates'', amb @foreach i similars.<br />
<br />
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<br />
<syntaxhighlight lang="php"><br />
<?php<br />
namespace App;<br />
use Illuminate\Database\Eloquent\Model;<br />
class Post extends Model<br />
{<br />
/**<br />
* Accedeix als comentaris relacionats amb el Post actual<br />
*/<br />
public function comments()<br />
{<br />
return $this->hasMany('App\Comment','<ref_remota>','<ref_local>');<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
On:<br />
* <ref_remota> és el camp de la taula de Comment que referencia el Post<br />
* <ref_local> és el camp de Post que fa de PK i on Comment apunta<br />
<br />
Per accedir al objecte relacionat "pare" caldrà fer una altra funció, en concret ''belongsTo''. Consulta la doc de les relacions 1-a-N (inversa).<br />
<br />
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:<br />
https://laravel.com/docs/5.5/eloquent-relationships#one-to-many<br />
<br />
=== Aniuant JSON en la API ===<br />
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:<br />
<br />
<syntaxhighlight lang="php"><br />
<?php<br />
Route::get("/comentaris", function() {<br />
$post = Post::with("comments")->get();<br />
return $post;<br />
});<br />
</syntaxhighlight><br />
<br />
...i ens retornarà les dades aniuades que volem! :)<br />
<br />
<br><br />
<br />
== Més coses ==<br />
Alguns temes que no hem aprofundit però que convé conèixer.<br />
<br />
=== Autenticació ===<br />
Senzill d'implementar i imprescindible. Laravel incorpora un ''scaffold'' per facilitar una funció tan estàndard.<br />
Amb una sola instrucció ens crea les rutes, vistes i els controllers típics (login, logout).<br />
<br />
==== Laravel 5.x ====<br />
[https://laravel.com/docs/5.5/authentication Autenticació en Laravel 5.x]:<br />
$ php artisan make:auth<br />
<br />
==== Laravel 6.x ====<br />
[https://laravel.com/docs/6.x/authentication Autenticació en Laravel 6.x]:<br />
$ composer require laravel/ui --dev<br />
$ php artisan ui vue --auth<br />
<br />
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:<br />
$ npm install && npm run dev<br />
<br />
També hi ha [https://laracasts.com/discuss/channels/laravel/laravel-60-appcss?page=1 solucions al problema carregant els CSS i JS del CDN] (només cal canviar un link en el ''head'' de <code>app.blade.php</code>.<br />
<br />
==== Laravel 8.x ====<br />
Ara el mòdul d'autenticació es diu [https://laravel.com/docs/8.x/starter-kits#laravel-breeze Laravel Breeze].<br />
<br />
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:<br />
* '''routes/web.php'''<br />
* '''resources/views/layouts/app.blade.php'''<br />
* resources/views/layouts/guest.blade.php<br />
* resources/views/layouts/navigation.blade.php<br />
* resources/views/auth/*<br />
* resources/views/components/*<br />
* resources/views/welcome.blade.php<br />
* resources/views/dashboard.blade.php<br />
<br />
Resumint, per instal·lar Breeze:<br />
$ composer require laravel/breeze --dev<br />
$ php artisan breeze:install<br />
$ npm install<br />
$ npm run dev<br />
<br />
=== Seeding ===<br />
Una part molt important és la de crear dades per farcir la base de dades inicialment i poder així testejar amb comoditat.<br />
<br />
https://laravel.com/docs/6.x/seeding<br />
<br />
En algun moment donat convé utilitzar un ''factory'' que ens permet crear elements en massa:<br />
<br />
https://laravel.com/docs/6.x/database-testing#writing-factories<br />
<br />
El ''factory'' sol utilitzar una llibreria <code>Faker</code> que ens va molt bé per crear noms i cognoms aleatoris, lorem ipsum, etc. que ens facilitarà la creació de dades de prova.<br />
<br />
https://github.com/fzaninotto/Faker<br />
<br />
=== Validacions ===<br />
Laravel ens ofereix un mecanisme de validació de formularis molt potent i efectiu.<br />
<br />
https://laravel.com/docs/5.5/validation<br />
<br />
=== Sessions ===<br />
D'entrada és molt útil per emetre missatges "flash", i informar l'usuari del processament intern.<br />
<br />
https://laravel.com/docs/5.5/session<br />
<br />
=== Arxius: filesystem vs BLOBs en BD ===<br />
Les imatges es poden guardar al sistema d'arxius o bé a la base de dades.<br />
* '''Filesystem''': En el propi tutorial hi ha una explicació de [https://ajgallego.gitbooks.io/laravel-5/content/capitulo_4_datos_de_entrada.html com guardar binaris amb el mètode clàssic del filesystem]<br />
* '''BLOBs en la BD''': Laravel ens permet crear models amb BLOBs i insertar les dades a la BD:<br />
** [https://www.daniweb.com/programming/web-development/threads/480731/how-to-inserting-files-on-mysql-using-laravel Insertant BLOBs amb Larvel]<br />
** Tingueu en compte, si ho feu així, de [https://stackoverflow.com/questions/8499633/how-to-display-base64-images-in-html com renderitzar continguts base64 (BLOBs) sobre un HTML]<br />
<br />
=== A solucionar ===<br />
Alguns temes a solucionar:<br />
* Quan utilitzem el scaffold d'autenticació, falla el logout. Això es deu a un canvi del mètode de GET a POST per motius de seguretat (amb POST, només podran fer logout des de la pròpia app Laravel ja que porta el csrf_token).<br />
*: https://laracasts.com/discuss/channels/laravel/laravel-53-logout-methodnotallowed<br />
<br />
<br><br />
<br />
=== Atacant 2 bases de dades simultàniament ===<br />
En alguns casos podem necessitar configurar 2 instàncies de bases de dades separades per optimitzar el rendiment. Aquest post ho explica molt bé:<br />
https://fideloper.com/laravel-multiple-database-connections<br />
<br />
Caldrà configurar el .env , config/database.php i especificar quina DB ataca en les migracions i en els models que creem.<br />
<br />
<br><br />
<br />
== Laravel i LDAP ==<br />
Aquest mòdul està pensat per a Active Directory, però [https://github.com/Adldap2/Adldap2-Laravel/issues/106 també funciona amb OpenLDAP si s'ajusta bé]:<br />
https://github.com/Adldap2/Adldap2-Laravel<br />
<br />
Primer cal configurar un servidor [[LDAP]].<br />
<br />
Després, tingues en compte que cal ajustar els següents paràmetres en el .env:<br />
ADLDAP_CONTROLLERS=localhost<br />
#ADLDAP_PORT=389<br />
ADLDAP_ADMIN_USERNAME="cn=admin,dc=cacauet,dc=org"<br />
ADLDAP_ADMIN_PASSWORD="enric123"<br />
ADLDAP_BASEDN="dc=cacauet,dc=org"<br />
<br />
Podem fer una autenticació seguint algun d'aquests exemples.<br />
<br />
Exemple 1: cercar un element del directori<br />
<syntaxhighlight lang="php"><br />
$user = Adldap::search()->where("mail","=","pepe@jolgorio.tk")->get();<br />
</syntaxhighlight><br />
<br />
Exemple 2: autenticar un usuari<br />
<syntaxhighlight lang="php"><br />
if( Adldap::auth()->attempt("cn=pepe,ou=usuaris,dc=cacauet,dc=org","pepe123")) {<br />
// autenticació exitosa<br />
return "Pepe OK!";<br />
}<br />
</syntaxhighlight><br />
<br />
<br><br />
<br />
== Laravel en producció ==<br />
Per posar en producció un projecte basat en Laravel cal tenir en compte:<br />
* '''IMPORTANT, SEGURETAT: Només cal publicar la carpeta <code>/public</code>''' . 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 .<br />
** Aquesta carpeta <code>/public</code> no figura inicialment quan creem o clonem un projecte (està a .gitignore), a l'igual que la carpeta <code>/vendor</code>, que es generen quan fem un <code>$ composer install</code>.<br />
** Reviseu la secció [[Laravel#Treballant_amb_GIT_i_clonant]] per fer el setup del projecte després de clonar.<br />
* '''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'').<br />
* 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:<br />
** db.sqlite (si s'escau)<br />
** carpeta <code>/storage</code><br />
** carpeta <code>/bootstrap/cache</code><br />
<br />
=== Desplegament en AWS amb Ubuntu i Apache ===<br />
Guia pel desplegament en Ubuntu amb Apache:<br />
* Accedir al nostre servidor via SSH<br />
* 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<pre>/var/www</pre><br />
* Per veure detalls reviseu la secció [[Laravel#Treballant_amb_GIT_i_clonant]]. Recordeu que això implica: <br />
*# composer install<br />
*# configurar arxiu .env<br />
*# generar clau<br />
* Es requereix el mòdul ''mod_rewrite'' d'Apache (o Nginx)<pre>$ sudo a2enmod rewrite</pre><br />
* Publicar la carpeta <code>/public</code> del projecte Laravel, d'alguna d'aquestes maneres:<br />
** Crear un VirtualHost i apuntar la ServerRoot del domini o subdomini a /var/www/<projecte>/public<br />
** Crear un link simbòlic de la carpeta pública d'Apache a la carpeta public del Laravel amb la comanda <pre>$ ln -s /var/www/<projecte>/public /var/www/html/lara1</pre><br />
* 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".<br />
* Ajusta els permisos de:<br />
** db.sqlite (si s'escau) i també de la carpeta que el conté (si no, no es podrà escriure-hi)<br />
** carpeta <code>/storage</code><br />
** carpeta <code>/bootstrap/cache</code><br />
* Cal activar els arxius <code>.htaccess</code> , afegint la directiva <code>AllowOverride all</code><br />
<br />
A l'arxiu de conf. del nostre VirtualHost (a <code>/etc/apache2/sites-available</code>):<br />
<Directory /var/www/><br />
AllowOverride All<br />
</Directory><br />
<br />
<br />
És important remarcar que per SEGURETAT no hem de mostrar mai els arxius interns de Laravel, només cal publicar el contingut de /public<br />
<br />
<br><br />
<br />
=== Heroku ===<br />
Abans de procedir amb aquesta part hauries de llegir i treballar aquesta altra: [[Heroku]] on treballem amb PHP simple.<br />
<br />
Pots posar en marxa un projecte Laravel a Heroku fàcilment seguint aquesta documentació. Segueix el tutorial per iniciar la app:<br />
https://devcenter.heroku.com/articles/getting-started-with-laravel<br />
<br />
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.<br />
<br />
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.<br />
<br />
En canvi, [https://devcenter.heroku.com/articles/heroku-postgresql el add-on de POSTGRESQL és gratuït i sense targeta de crèdit! :)] Som-hi, doncs!<br />
<br />
Primer de tot, creeu el projecte Laravel i inicialitzeu GIT en cas que no el tingueu penjat a Github o similars:<br />
$ git init<br />
<br />
Tb caldrà afegir un Procfile adequat per Laravel:<br />
$ echo "web: vendor/bin/heroku-php-apache2 public/" > Procfile<br />
<br />
Inicialitzem projecte Heroku:<br />
$ heroku create elmeuprojectedeguais<br />
<br />
Afegim els arxius al repo local:<br />
$ git add .<br />
$ git commit -am "primer commit"<br />
<br />
Afegim la BD PostgreSQL:<br />
$ heroku addons:create heroku-postgresql:hobby-dev<br />
<br />
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:<br />
$ heroku config -s | grep -i post<br />
<br />
Ens ho dona en la següent forma (exemple a continuació):<br />
DATABASE_URL='postgres://<usuari>:<password>@<maquina>:<port>/<bbdd>'<br />
DATABASE_URL='postgres://mxlsfebqyopadb:3e5af56b52cc06574645123ea9d9f7504564e207804dcc71a2db2848446ba064@ec2-156-73-167-43.compute-1.amazonaws.com:5432/d353ihheo564q7'<br />
<br />
Així, doncs, només caldrà ajustar les següents variables d'entorn que necessita el Laravel perquè això funcioni:<br />
DB_CONNECTION=pgsql<br />
DB_HOST=ec2-156...<br />
DB_PORT=5432<br />
DB_DATABASE=d353...<br />
DB_USERNAME=mxls...<br />
DB_PASSWORD=3e5a...<br />
<br />
Per fer-ho cal anar executant les següents ordres:<br />
$ heroku config:set DB_CONNECTION=pgsql<br />
$ ...etc...<br />
<br />
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:<br />
$ cp .env.example .env<br />
$ php artisan key:generate<br />
$ heroku config:set APP_KEY=base64:tX2ikx...<br />
<br />
En acabat, podem posar la app en producció:<br />
$ git add .<br />
$ git push heroku master<br />
<br />
I un cop acabats, migrem la nostra base de dades:<br />
$ heroku run php artisan migrate<br />
<br />
I veure la nostra flamant web en producció (a elmeuprojectedeguais.herokuapp.com):<br />
$ heroku open<br />
<br />
...et voilà!</div>Enrichttps://cacauet.org/wiki/index.php?title=Laravel&diff=4225Laravel2021-02-10T00:00:27Z<p>Enric: /* Laravel 8.x */</p>
<hr />
<div><nowiki>#FpInfor #DawMp07 #DawMp07Uf2 #DawMp07Uf02 #DawMpDual</nowiki><br />
<br />
<br />
== Intro i referències ==<br />
Laravel és un framework web per a PHP que està agafant molta força.<br />
<br />
Documentació oficial: https://laravel.com/docs/<br />
<br />
Tutorials:<br />
* [https://ajgallego.gitbooks.io/laravel-5/content/index.html Principal tutorial per seguir el curs]: <pre>https://ajgallego.gitbooks.io/laravel-5/content/index.html</pre><br />
* Forms: https://selftaughtcoders.com/from-idea-to-launch/lesson-23/laravel-5-application-form-model-binding-laravelcollective-forms-html-library-bootstrap-framework/<br />
* Forms i validació: https://scotch.io/tutorials/simple-laravel-crud-with-resource-controllers<br />
* Apunts del Sergi Coll: https://seicoll.github.io/DAW-M07-UF2-Apunts/<br />
* https://styde.net/laravel-5/<br />
* Per passar del schema SQL (per ex. de MySQL Workbench) a Laravel migration: https://adolfocuadros.com/sql_to_laravel/<br />
<br />
<br />
Plugins:<br />
* CORS (Cross-Origin Resource Sharing): https://github.com/barryvdh/laravel-cors<br />
* CRUD & admin : Hi ha molts plugins per crear ''admin panels'' automàticament. Alguns son:<br />
** Voyager: https://voyager.devdojo.com/<br />
** Craftable: https://www.getcraftable.com/<br />
* https://iamacoder.com/post/5-must-have-laravel-5-packages/<br />
<br />
Temes a ampliar:<br />
* Forms: https://laravel.com/docs/4.2/html<br />
* Validació de forms: https://laravel.com/docs/5.5/validation<br />
* Autenticació: https://laravel.com/docs/5.5/authentication<br />
<br />
<br><br />
<br />
== Instal·lació i setup ==<br />
<br />
Prerequisits:<br />
* Laravel i PHP, és molt important tenir en compte les versions:<br />
** <strike>Laravel 5.3 : PHP >= 5.6.4<br />
** Laravel 5.5 : PHP == 7.0<br />
** Laravel 5.6 : PHP >= 7.1<br />
** Laravel 5.7 : PHP >= 7.1.3</strike><br />
** Laravel 6.x : PHP >= 7.2<br />
* Si utilitzes Ubuntu 14 o menor [https://www.digitalocean.com/community/tutorials/how-to-upgrade-to-php-7-on-ubuntu-14-04 actualitza la teva versió de PHP a la 7.0]<br />
* Calen els paquets següents: <pre>$ sudo apt-get install php-mbstring php-zip php-xml php-mysql</pre><br />
<br />
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...:<br />
# Instal·la el gestor de paquets per PHP Composer<br />
#* El més fàcil és fer: (però no ho farem pq volem la darrera versió)<pre>$ sudo apt install composer</pre><br />
#* Prova primer la instal·lació genèrica : [https://getcomposer.org/download/ Instal.la PHP Composer]<br />
#* També tens aquesta altra forma d' [https://getcomposer.org/doc/00-intro.md#installation-linux-unix-osx instal·lar Composer per GNU/Linux]. Descarrega composer-setup.php i instal·la'l així:<pre>$ php composer-setup.php --install-dir=~/bin --filename=composer</pre><br />
# Instal·la la darrera versió de Laravel<br />
#* https://laravel.com/docs/5.7/installation<br />
#* Bàsicament el què cal fer és aquesta comanda per instal·lar el binari ''laravel'':<pre>$ composer global require laravel/installer</pre><br />
#* Laravel s'instal·la a <code>$HOME/.config/composer</code> però per poder executar les properes comandes necessitarem tenir <code>$HOME/.config/composer/vendor/bin</code> al nostre $PATH. Inserta això al teu <code>$HOME/.profile</code>: <pre>PATH=$PATH:~/.config/composer/vendor/bin</pre><br />
#*: Fes logout/login del sistema per activar aquests canvis<br />
# Crea una app Laravel allà on et faci més ràbia: <pre>$ laravel new laravelapp1</pre><br />
#: o també: <pre>$ composer create-project --prefer-dist laravel/laravel laravelapp1</pre><br />
#: o si volem una versió específica de laravel: <pre>$ composer create-project --prefer-dist laravel/laravel=5.8.* laravelapp1</pre><br />
# Arrenca l'aplicació de prova: <pre>$ php artisan serve</pre><br />
# Comprova la app amb el navegador a<pre>http://localhost:8000</pre><br />
<br />
<br><br />
<br />
Si ja has completat la instal·lació, pots procedir a crear un altre projecte nou i realitzar el següent tutorial "tasklist":<br />
https://laravel.com/docs/5.2/quickstart<br />
<br />
<br><br />
<br />
== Incidències vàries ==<br />
Aquest és un bon tutorial:<br />
https://ajgallego.gitbooks.io/laravel-5/content/index.html<br />
<br />
Igualment, podríem trobar algunes incidències. Us dono pistes:<br />
<br />
=== Treballant amb GIT i clonant ===<br />
Al pujar el projecte a un repo GIT, i clonar-lo després caldrà:<br />
# Re-instal·lar les dependències:<pre>$ composer install</pre><br />
# Regenerar arxiu <code>.env</code> : com que depèn de cada entorn no es fica al projecte (es posa a <code>.gitignore</code>), però pots copiar i modificar de <code>.env.example</code><br />
# Error ''The only supported ciphers are AES-128-CBC and AES-256-CBC with the correct key lengths.'' Es soluciona amb :<pre>$ php artisan key:generate</pre><br />
<br />
=== Creant controllers amb CRUD complert ===<br />
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.<br />
# Ja no es pot fer amb <strike><code>Route::controller</code></strike> sinó amb:<pre>Route::resource("cosa","CosaController");</pre><br />
# Per exemple, per crear un controller per al model "Cosa" ho faríem amb -r (de resource): <pre>$ php artisan make:controller -r CosaController</pre><br />
<br />
=== Treballant amb SQLite ===<br />
Per configurar la BD amb SQLite cal crear el fitxer abans amb:<br />
$ touch db.sqlite<br />
<br />
Configurar la BD a .env:<br />
DB_CONNECTION=sqlite<br />
DB_DATABASE=/path/absolut/al/db.sqlite<br />
<br />
Instal·lar els binaris necessaris de SQLite i de PHP:<br />
$ sudo apt-get install sqlite php-sqlite3<br />
<br />
I crear la BD inicial amb:<br />
$ php artisan migrate<br />
<br />
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.<br />
<br />
=== Eliminant models o migracions ===<br />
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:<br />
$ composer dump-autoload<br />
...i es tornaran a generar els arxius d'autoload sense els arxius que volíem esborrar.<br />
<br />
=== Treballant amb proxies i composer ===<br />
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):<br />
$ composer update<br />
Loading composer repositories with package information<br />
Updating dependencies (including require-dev)<br />
(...demana user/password de packagist.org ...)<br />
<br />
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:<br />
$ ssh -L 3128:localhost:3128 jo@elmeuserver.com<br />
I un cop logats, aprofitem per instal·lar el squid:<br />
$ sudo apt install squid<br />
Hem de mantenir la shell oberta mentre vulguem que estigui activat el túnel (l'hem assignat a localhost:3128).<br />
<br />
Obrim una altra shell i anem al nostre projecte Laravel:<br />
$ export http_proxy=localhost:3128<br />
$ composer update<br />
<br />
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).<br />
<br />
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:<br />
$ ssh jo@elmeuserver.com<br />
$ sudo apt remove squid<br />
<br />
<br><br />
<br />
== Tutorials ==<br />
Després d'elaborar la documentació he trobat aquest tutorial bastant útil (només fins la v5.2):<br />
https://laravel.com/docs/5.2/quickstart<br />
<br />
Tutorial per a CRUD complert:<br />
https://www.itsolutionstuff.com/post/laravel-6-crud-application-tutorialexample.html<br />
<br />
== Resum per a fer un CRUD ==<br />
<br />
=== Setup projecte ===<br />
Crear projecte:<br />
$ laravel new proj1<br />
Crear DB (en aquest cas SQLite:<br />
$ touch db.sqlite<br />
Modifica .env per configurar la DB com sqlite:<br />
DB_CONNECTION=sqlite<br />
DB_DATABASE=/path/absolut/al/db.sqlite<br />
<br />
=== Model ===<br />
Crear taules i migracions:<br />
$ php artisan make:migration crea_taula_items --create=items<br />
Editar la migració per crear les taules adequades. Mira't les principals referències:<br />
* [https://laravel.com/docs/5.5/migrations#columns Tipus de columnes]<br />
* [https://laravel.com/docs/5.5/migrations#foreign-key-constraints Relacions i FKs]<br />
Realitzar la migració:<br />
$ php artisan migrate<br />
Crear models:<br />
$ php artisan make:model Item<br />
Ajusta el model perquè apunti al nom correcte de la taula:<br />
https://laravel.com/docs/5.5/eloquent#eloquent-model-conventions<br />
<br />
=== Controller i rutes ===<br />
Crear controllers amb els mètodes estàndard (index, create-store, show, edit-update, destroy):<br />
$ php artisan make:controller -r ItemController<br />
Crear rutes a <code>routes/web.php</code>:<br />
Route::resource("item","ItemController");<br />
Crear plantilles per als mètodes (l'exemple diu "tema" enlloc de "item"):<br />
$ php artisan route:list<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
| Domain | Method | URI | Name | Action | Middleware |<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
| | GET|HEAD | / | | Closure | web |<br />
| | GET|HEAD | api/user | | Closure | api,auth:api |<br />
| | GET|HEAD | tema | tema.index | App\Http\Controllers\TemaController@index | web |<br />
| | POST | tema | tema.store | App\Http\Controllers\TemaController@store | web |<br />
| | GET|HEAD | tema/create | tema.create | App\Http\Controllers\TemaController@create | web |<br />
| | GET|HEAD | tema/{tema} | tema.show | App\Http\Controllers\TemaController@show | web |<br />
| | PUT|PATCH | tema/{tema} | tema.update | App\Http\Controllers\TemaController@update | web |<br />
| | DELETE | tema/{tema} | tema.destroy | App\Http\Controllers\TemaController@destroy | web |<br />
| | GET|HEAD | tema/{tema}/edit | tema.edit | App\Http\Controllers\TemaController@edit | web |<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
<br />
Crear les views (plantilles blade) adequades per a tots els mètodes necessaris (els arxius van a <code>resources/views</code>). Pots veure [https://github.com/emieza/laravel-karaoke/tree/master/resources/views/llista aqui] alguns exemples.<br />
* '''index''' : llista tots els elements<br />
* '''show''' : mostra un element en concret, necessita que li passem un paràmetre per GET (id del element a mostrar)<br />
* '''create-store''' : "create és el form (no necessita codi), i "store" és el codi per insertar-ho a la BD (no necessita una plantilla)<br />
* '''edit-update''' : "edit" és el form, i "update" el codi per actualitzar la BD<br />
* '''destroy''' : elimina un element<br />
<br />
=== Codi del Controller i View ===<br />
* Crear views amb formularis d'entrada de dades: [https://github.com/emieza/laravel-karaoke/blob/master/resources/views/llista/crea.blade.php create.blade.php d'exemple]<br />
* Editar el codi del Controller per cridar pertinentment a les views: [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/LlistaController.php Controller d'exemple]<br />
<br />
=== Més docs ===<br />
Una bona referència de la doc oficial per fer un CRUD és aquesta:<br />
https://laravel.com/docs/5.2/quickstart<br />
En particular per veure com utilitzar les templates oficials amb bootstrap ;)<br />
<br />
<br><br />
<br />
== Projecte d'exemple ==<br />
Aquest és el projecte que he realitzat per entrenar-me, et pot servir d'exemple. El pots veure en producció aquí: https://jolgorio.tk<br />
https://github.com/emieza/laravel-karaoke<br />
<br />
Fes-li un cop d'ull al readme.md per veure com posar-lo en marxa.<br />
<br />
MOLT IMPORTANT PEL PROJECTE: Cal crear un README.md (com [https://github.com/emieza/laravel-karaoke/blob/master/readme.md per exemple aquest]). No acceptaré cap projecte sense README.md<br />
<br />
Per entrenar-vos amb el Markdown teniu aquest tester:<br />
http://dillinger.io/<br />
<br />
Anem per feina:<br />
# Taules: llistes, temes, vots<br />
# Rutes que vols implementar per al projecte. [https://github.com/emieza/laravel-karaoke/blob/master/routes/web.php En el meu cas, tinc]:<br />
#* /llista/crea (GET per formulari + POST per store)<br />
#* /llista (index de llistes)<br />
#* /llista/{id} (show)<br />
#* /llista/{id}/crea (GET + POST, per crear temes en les llistes)<br />
#* /vota/{idtema}<br />
# Codi:<br />
#* als Controllers pertinents. Mira't l'[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/LlistaController.php exemple de les llistes de karaoke].<br />
#* Plantilles: a resources/views/xxxx.blade.php . Mira't l'[https://github.com/emieza/laravel-karaoke/tree/master/resources/views/llista exemple un altre cop].<br />
<br />
<br><br />
<br />
== ORM : Models i relacions ==<br />
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.<br />
<br />
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. <br />
<br />
El què anem a explicar està documentat a l'apartat "Eloquent ORM" de Laravel:<br />
https://laravel.com/docs/5.7/eloquent-relationships<br />
https://laravel.com/docs/6.x/eloquent-relationships<br />
<br />
=== Accedint relacions 1-N de forma directa ===<br />
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í.<br />
<br />
L'objectiu serà poder accedir a l'objecte pare d'aquesta manera per mostrar el text del Post (pare).<br />
<syntaxhighlight lang="php"><br />
$comment = Comment::find(33);<br />
echo $comment->post->text;<br />
</syntaxhighlight><br />
<br />
Per aconseguir això, cal que indiquem la relació existent a les taules entre els models Post i Comment amb la relació <code>belongsTo</code>:<br />
<br />
<syntaxhighlight lang="php"><br />
<?php<br />
namespace App;<br />
use Illuminate\Database\Eloquent\Model;<br />
class Comment extends Model<br />
{<br />
/**<br />
* Accedeix al pare (Post)<br />
*/<br />
public function post()<br />
{<br />
return $this->belongsTo('App\Post','post_id');<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Accedint relacions 1-N de forma inversa ===<br />
El següent cas típic serà accedir des d'un objecte Post als diferents Comentaris, més o menys així:<br />
<br />
<syntaxhighlight lang="php"><br />
$comments = App\Post::find(1)->comments;<br />
foreach ($comments as $comment) {<br />
// ... el teu codi...<br />
echo $comment->text;<br />
}<br />
</syntaxhighlight><br />
El codi que veiem és per a un ''controller'', però es pot aplicar també als ''templates'', amb @foreach i similars.<br />
<br />
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<br />
<syntaxhighlight lang="php"><br />
<?php<br />
namespace App;<br />
use Illuminate\Database\Eloquent\Model;<br />
class Post extends Model<br />
{<br />
/**<br />
* Accedeix als comentaris relacionats amb el Post actual<br />
*/<br />
public function comments()<br />
{<br />
return $this->hasMany('App\Comment','<ref_remota>','<ref_local>');<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
On:<br />
* <ref_remota> és el camp de la taula de Comment que referencia el Post<br />
* <ref_local> és el camp de Post que fa de PK i on Comment apunta<br />
<br />
Per accedir al objecte relacionat "pare" caldrà fer una altra funció, en concret ''belongsTo''. Consulta la doc de les relacions 1-a-N (inversa).<br />
<br />
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:<br />
https://laravel.com/docs/5.5/eloquent-relationships#one-to-many<br />
<br />
=== Aniuant JSON en la API ===<br />
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:<br />
<br />
<syntaxhighlight lang="php"><br />
<?php<br />
Route::get("/comentaris", function() {<br />
$post = Post::with("comments")->get();<br />
return $post;<br />
});<br />
</syntaxhighlight><br />
<br />
...i ens retornarà les dades aniuades que volem! :)<br />
<br />
<br><br />
<br />
== Més coses ==<br />
Alguns temes que no hem aprofundit però que convé conèixer.<br />
<br />
=== Autenticació ===<br />
Senzill d'implementar i imprescindible. Laravel incorpora un ''scaffold'' per facilitar una funció tan estàndard.<br />
Amb una sola instrucció ens crea les rutes, vistes i els controllers típics (login, logout).<br />
<br />
==== Laravel 5.x ====<br />
[https://laravel.com/docs/5.5/authentication Autenticació en Laravel 5.x]:<br />
$ php artisan make:auth<br />
<br />
==== Laravel 6.x ====<br />
[https://laravel.com/docs/6.x/authentication Autenticació en Laravel 6.x]:<br />
$ composer require laravel/ui --dev<br />
$ php artisan ui vue --auth<br />
<br />
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:<br />
$ npm install && npm run dev<br />
<br />
També hi ha [https://laracasts.com/discuss/channels/laravel/laravel-60-appcss?page=1 solucions al problema carregant els CSS i JS del CDN] (només cal canviar un link en el ''head'' de <code>app.blade.php</code>.<br />
<br />
==== Laravel 8.x ====<br />
Ara el mòdul d'autenticació es diu [https://laravel.com/docs/8.x/starter-kits#laravel-breeze Laravel Breeze].<br />
<br />
ULL! Si instal·lem Laravel Breeze, aquest sobreescriurà arxius d'algunes ''views'' i ''routes''. En particular, abans d'instal·lar, feu un backup de:<br />
* '''resources/views/layouts/app.blade.php'''<br />
* resources/views/layouts/guest.blade.php<br />
* resources/views/layouts/navigation.blade.php<br />
* resources/views/auth/*<br />
* resources/views/components/*<br />
* resources/views/welcome.blade.php<br />
* resources/views/dashboard.blade.php<br />
* '''routes/web.php'''<br />
<br />
Resumint, per instal·lar Breeze:<br />
$ composer require laravel/breeze --dev<br />
$ php artisan breeze:install<br />
$ npm install<br />
$ npm run dev<br />
<br />
=== Seeding ===<br />
Una part molt important és la de crear dades per farcir la base de dades inicialment i poder així testejar amb comoditat.<br />
<br />
https://laravel.com/docs/6.x/seeding<br />
<br />
En algun moment donat convé utilitzar un ''factory'' que ens permet crear elements en massa:<br />
<br />
https://laravel.com/docs/6.x/database-testing#writing-factories<br />
<br />
El ''factory'' sol utilitzar una llibreria <code>Faker</code> que ens va molt bé per crear noms i cognoms aleatoris, lorem ipsum, etc. que ens facilitarà la creació de dades de prova.<br />
<br />
https://github.com/fzaninotto/Faker<br />
<br />
=== Validacions ===<br />
Laravel ens ofereix un mecanisme de validació de formularis molt potent i efectiu.<br />
<br />
https://laravel.com/docs/5.5/validation<br />
<br />
=== Sessions ===<br />
D'entrada és molt útil per emetre missatges "flash", i informar l'usuari del processament intern.<br />
<br />
https://laravel.com/docs/5.5/session<br />
<br />
=== Arxius: filesystem vs BLOBs en BD ===<br />
Les imatges es poden guardar al sistema d'arxius o bé a la base de dades.<br />
* '''Filesystem''': En el propi tutorial hi ha una explicació de [https://ajgallego.gitbooks.io/laravel-5/content/capitulo_4_datos_de_entrada.html com guardar binaris amb el mètode clàssic del filesystem]<br />
* '''BLOBs en la BD''': Laravel ens permet crear models amb BLOBs i insertar les dades a la BD:<br />
** [https://www.daniweb.com/programming/web-development/threads/480731/how-to-inserting-files-on-mysql-using-laravel Insertant BLOBs amb Larvel]<br />
** Tingueu en compte, si ho feu així, de [https://stackoverflow.com/questions/8499633/how-to-display-base64-images-in-html com renderitzar continguts base64 (BLOBs) sobre un HTML]<br />
<br />
=== A solucionar ===<br />
Alguns temes a solucionar:<br />
* Quan utilitzem el scaffold d'autenticació, falla el logout. Això es deu a un canvi del mètode de GET a POST per motius de seguretat (amb POST, només podran fer logout des de la pròpia app Laravel ja que porta el csrf_token).<br />
*: https://laracasts.com/discuss/channels/laravel/laravel-53-logout-methodnotallowed<br />
<br />
<br><br />
<br />
=== Atacant 2 bases de dades simultàniament ===<br />
En alguns casos podem necessitar configurar 2 instàncies de bases de dades separades per optimitzar el rendiment. Aquest post ho explica molt bé:<br />
https://fideloper.com/laravel-multiple-database-connections<br />
<br />
Caldrà configurar el .env , config/database.php i especificar quina DB ataca en les migracions i en els models que creem.<br />
<br />
<br><br />
<br />
== Laravel i LDAP ==<br />
Aquest mòdul està pensat per a Active Directory, però [https://github.com/Adldap2/Adldap2-Laravel/issues/106 també funciona amb OpenLDAP si s'ajusta bé]:<br />
https://github.com/Adldap2/Adldap2-Laravel<br />
<br />
Primer cal configurar un servidor [[LDAP]].<br />
<br />
Després, tingues en compte que cal ajustar els següents paràmetres en el .env:<br />
ADLDAP_CONTROLLERS=localhost<br />
#ADLDAP_PORT=389<br />
ADLDAP_ADMIN_USERNAME="cn=admin,dc=cacauet,dc=org"<br />
ADLDAP_ADMIN_PASSWORD="enric123"<br />
ADLDAP_BASEDN="dc=cacauet,dc=org"<br />
<br />
Podem fer una autenticació seguint algun d'aquests exemples.<br />
<br />
Exemple 1: cercar un element del directori<br />
<syntaxhighlight lang="php"><br />
$user = Adldap::search()->where("mail","=","pepe@jolgorio.tk")->get();<br />
</syntaxhighlight><br />
<br />
Exemple 2: autenticar un usuari<br />
<syntaxhighlight lang="php"><br />
if( Adldap::auth()->attempt("cn=pepe,ou=usuaris,dc=cacauet,dc=org","pepe123")) {<br />
// autenticació exitosa<br />
return "Pepe OK!";<br />
}<br />
</syntaxhighlight><br />
<br />
<br><br />
<br />
== Laravel en producció ==<br />
Per posar en producció un projecte basat en Laravel cal tenir en compte:<br />
* '''IMPORTANT, SEGURETAT: Només cal publicar la carpeta <code>/public</code>''' . 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 .<br />
** Aquesta carpeta <code>/public</code> no figura inicialment quan creem o clonem un projecte (està a .gitignore), a l'igual que la carpeta <code>/vendor</code>, que es generen quan fem un <code>$ composer install</code>.<br />
** Reviseu la secció [[Laravel#Treballant_amb_GIT_i_clonant]] per fer el setup del projecte després de clonar.<br />
* '''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'').<br />
* 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:<br />
** db.sqlite (si s'escau)<br />
** carpeta <code>/storage</code><br />
** carpeta <code>/bootstrap/cache</code><br />
<br />
=== Desplegament en AWS amb Ubuntu i Apache ===<br />
Guia pel desplegament en Ubuntu amb Apache:<br />
* Accedir al nostre servidor via SSH<br />
* 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<pre>/var/www</pre><br />
* Per veure detalls reviseu la secció [[Laravel#Treballant_amb_GIT_i_clonant]]. Recordeu que això implica: <br />
*# composer install<br />
*# configurar arxiu .env<br />
*# generar clau<br />
* Es requereix el mòdul ''mod_rewrite'' d'Apache (o Nginx)<pre>$ sudo a2enmod rewrite</pre><br />
* Publicar la carpeta <code>/public</code> del projecte Laravel, d'alguna d'aquestes maneres:<br />
** Crear un VirtualHost i apuntar la ServerRoot del domini o subdomini a /var/www/<projecte>/public<br />
** Crear un link simbòlic de la carpeta pública d'Apache a la carpeta public del Laravel amb la comanda <pre>$ ln -s /var/www/<projecte>/public /var/www/html/lara1</pre><br />
* 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".<br />
* Ajusta els permisos de:<br />
** db.sqlite (si s'escau) i també de la carpeta que el conté (si no, no es podrà escriure-hi)<br />
** carpeta <code>/storage</code><br />
** carpeta <code>/bootstrap/cache</code><br />
* Cal activar els arxius <code>.htaccess</code> , afegint la directiva <code>AllowOverride all</code><br />
<br />
A l'arxiu de conf. del nostre VirtualHost (a <code>/etc/apache2/sites-available</code>):<br />
<Directory /var/www/><br />
AllowOverride All<br />
</Directory><br />
<br />
<br />
És important remarcar que per SEGURETAT no hem de mostrar mai els arxius interns de Laravel, només cal publicar el contingut de /public<br />
<br />
<br><br />
<br />
=== Heroku ===<br />
Abans de procedir amb aquesta part hauries de llegir i treballar aquesta altra: [[Heroku]] on treballem amb PHP simple.<br />
<br />
Pots posar en marxa un projecte Laravel a Heroku fàcilment seguint aquesta documentació. Segueix el tutorial per iniciar la app:<br />
https://devcenter.heroku.com/articles/getting-started-with-laravel<br />
<br />
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.<br />
<br />
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.<br />
<br />
En canvi, [https://devcenter.heroku.com/articles/heroku-postgresql el add-on de POSTGRESQL és gratuït i sense targeta de crèdit! :)] Som-hi, doncs!<br />
<br />
Primer de tot, creeu el projecte Laravel i inicialitzeu GIT en cas que no el tingueu penjat a Github o similars:<br />
$ git init<br />
<br />
Tb caldrà afegir un Procfile adequat per Laravel:<br />
$ echo "web: vendor/bin/heroku-php-apache2 public/" > Procfile<br />
<br />
Inicialitzem projecte Heroku:<br />
$ heroku create elmeuprojectedeguais<br />
<br />
Afegim els arxius al repo local:<br />
$ git add .<br />
$ git commit -am "primer commit"<br />
<br />
Afegim la BD PostgreSQL:<br />
$ heroku addons:create heroku-postgresql:hobby-dev<br />
<br />
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:<br />
$ heroku config -s | grep -i post<br />
<br />
Ens ho dona en la següent forma (exemple a continuació):<br />
DATABASE_URL='postgres://<usuari>:<password>@<maquina>:<port>/<bbdd>'<br />
DATABASE_URL='postgres://mxlsfebqyopadb:3e5af56b52cc06574645123ea9d9f7504564e207804dcc71a2db2848446ba064@ec2-156-73-167-43.compute-1.amazonaws.com:5432/d353ihheo564q7'<br />
<br />
Així, doncs, només caldrà ajustar les següents variables d'entorn que necessita el Laravel perquè això funcioni:<br />
DB_CONNECTION=pgsql<br />
DB_HOST=ec2-156...<br />
DB_PORT=5432<br />
DB_DATABASE=d353...<br />
DB_USERNAME=mxls...<br />
DB_PASSWORD=3e5a...<br />
<br />
Per fer-ho cal anar executant les següents ordres:<br />
$ heroku config:set DB_CONNECTION=pgsql<br />
$ ...etc...<br />
<br />
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:<br />
$ cp .env.example .env<br />
$ php artisan key:generate<br />
$ heroku config:set APP_KEY=base64:tX2ikx...<br />
<br />
En acabat, podem posar la app en producció:<br />
$ git add .<br />
$ git push heroku master<br />
<br />
I un cop acabats, migrem la nostra base de dades:<br />
$ heroku run php artisan migrate<br />
<br />
I veure la nostra flamant web en producció (a elmeuprojectedeguais.herokuapp.com):<br />
$ heroku open<br />
<br />
...et voilà!</div>Enrichttps://cacauet.org/wiki/index.php?title=Laravel&diff=4224Laravel2021-02-09T23:56:33Z<p>Enric: /* Autenticació */</p>
<hr />
<div><nowiki>#FpInfor #DawMp07 #DawMp07Uf2 #DawMp07Uf02 #DawMpDual</nowiki><br />
<br />
<br />
== Intro i referències ==<br />
Laravel és un framework web per a PHP que està agafant molta força.<br />
<br />
Documentació oficial: https://laravel.com/docs/<br />
<br />
Tutorials:<br />
* [https://ajgallego.gitbooks.io/laravel-5/content/index.html Principal tutorial per seguir el curs]: <pre>https://ajgallego.gitbooks.io/laravel-5/content/index.html</pre><br />
* Forms: https://selftaughtcoders.com/from-idea-to-launch/lesson-23/laravel-5-application-form-model-binding-laravelcollective-forms-html-library-bootstrap-framework/<br />
* Forms i validació: https://scotch.io/tutorials/simple-laravel-crud-with-resource-controllers<br />
* Apunts del Sergi Coll: https://seicoll.github.io/DAW-M07-UF2-Apunts/<br />
* https://styde.net/laravel-5/<br />
* Per passar del schema SQL (per ex. de MySQL Workbench) a Laravel migration: https://adolfocuadros.com/sql_to_laravel/<br />
<br />
<br />
Plugins:<br />
* CORS (Cross-Origin Resource Sharing): https://github.com/barryvdh/laravel-cors<br />
* CRUD & admin : Hi ha molts plugins per crear ''admin panels'' automàticament. Alguns son:<br />
** Voyager: https://voyager.devdojo.com/<br />
** Craftable: https://www.getcraftable.com/<br />
* https://iamacoder.com/post/5-must-have-laravel-5-packages/<br />
<br />
Temes a ampliar:<br />
* Forms: https://laravel.com/docs/4.2/html<br />
* Validació de forms: https://laravel.com/docs/5.5/validation<br />
* Autenticació: https://laravel.com/docs/5.5/authentication<br />
<br />
<br><br />
<br />
== Instal·lació i setup ==<br />
<br />
Prerequisits:<br />
* Laravel i PHP, és molt important tenir en compte les versions:<br />
** <strike>Laravel 5.3 : PHP >= 5.6.4<br />
** Laravel 5.5 : PHP == 7.0<br />
** Laravel 5.6 : PHP >= 7.1<br />
** Laravel 5.7 : PHP >= 7.1.3</strike><br />
** Laravel 6.x : PHP >= 7.2<br />
* Si utilitzes Ubuntu 14 o menor [https://www.digitalocean.com/community/tutorials/how-to-upgrade-to-php-7-on-ubuntu-14-04 actualitza la teva versió de PHP a la 7.0]<br />
* Calen els paquets següents: <pre>$ sudo apt-get install php-mbstring php-zip php-xml php-mysql</pre><br />
<br />
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...:<br />
# Instal·la el gestor de paquets per PHP Composer<br />
#* El més fàcil és fer: (però no ho farem pq volem la darrera versió)<pre>$ sudo apt install composer</pre><br />
#* Prova primer la instal·lació genèrica : [https://getcomposer.org/download/ Instal.la PHP Composer]<br />
#* També tens aquesta altra forma d' [https://getcomposer.org/doc/00-intro.md#installation-linux-unix-osx instal·lar Composer per GNU/Linux]. Descarrega composer-setup.php i instal·la'l així:<pre>$ php composer-setup.php --install-dir=~/bin --filename=composer</pre><br />
# Instal·la la darrera versió de Laravel<br />
#* https://laravel.com/docs/5.7/installation<br />
#* Bàsicament el què cal fer és aquesta comanda per instal·lar el binari ''laravel'':<pre>$ composer global require laravel/installer</pre><br />
#* Laravel s'instal·la a <code>$HOME/.config/composer</code> però per poder executar les properes comandes necessitarem tenir <code>$HOME/.config/composer/vendor/bin</code> al nostre $PATH. Inserta això al teu <code>$HOME/.profile</code>: <pre>PATH=$PATH:~/.config/composer/vendor/bin</pre><br />
#*: Fes logout/login del sistema per activar aquests canvis<br />
# Crea una app Laravel allà on et faci més ràbia: <pre>$ laravel new laravelapp1</pre><br />
#: o també: <pre>$ composer create-project --prefer-dist laravel/laravel laravelapp1</pre><br />
#: o si volem una versió específica de laravel: <pre>$ composer create-project --prefer-dist laravel/laravel=5.8.* laravelapp1</pre><br />
# Arrenca l'aplicació de prova: <pre>$ php artisan serve</pre><br />
# Comprova la app amb el navegador a<pre>http://localhost:8000</pre><br />
<br />
<br><br />
<br />
Si ja has completat la instal·lació, pots procedir a crear un altre projecte nou i realitzar el següent tutorial "tasklist":<br />
https://laravel.com/docs/5.2/quickstart<br />
<br />
<br><br />
<br />
== Incidències vàries ==<br />
Aquest és un bon tutorial:<br />
https://ajgallego.gitbooks.io/laravel-5/content/index.html<br />
<br />
Igualment, podríem trobar algunes incidències. Us dono pistes:<br />
<br />
=== Treballant amb GIT i clonant ===<br />
Al pujar el projecte a un repo GIT, i clonar-lo després caldrà:<br />
# Re-instal·lar les dependències:<pre>$ composer install</pre><br />
# Regenerar arxiu <code>.env</code> : com que depèn de cada entorn no es fica al projecte (es posa a <code>.gitignore</code>), però pots copiar i modificar de <code>.env.example</code><br />
# Error ''The only supported ciphers are AES-128-CBC and AES-256-CBC with the correct key lengths.'' Es soluciona amb :<pre>$ php artisan key:generate</pre><br />
<br />
=== Creant controllers amb CRUD complert ===<br />
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.<br />
# Ja no es pot fer amb <strike><code>Route::controller</code></strike> sinó amb:<pre>Route::resource("cosa","CosaController");</pre><br />
# Per exemple, per crear un controller per al model "Cosa" ho faríem amb -r (de resource): <pre>$ php artisan make:controller -r CosaController</pre><br />
<br />
=== Treballant amb SQLite ===<br />
Per configurar la BD amb SQLite cal crear el fitxer abans amb:<br />
$ touch db.sqlite<br />
<br />
Configurar la BD a .env:<br />
DB_CONNECTION=sqlite<br />
DB_DATABASE=/path/absolut/al/db.sqlite<br />
<br />
Instal·lar els binaris necessaris de SQLite i de PHP:<br />
$ sudo apt-get install sqlite php-sqlite3<br />
<br />
I crear la BD inicial amb:<br />
$ php artisan migrate<br />
<br />
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.<br />
<br />
=== Eliminant models o migracions ===<br />
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:<br />
$ composer dump-autoload<br />
...i es tornaran a generar els arxius d'autoload sense els arxius que volíem esborrar.<br />
<br />
=== Treballant amb proxies i composer ===<br />
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):<br />
$ composer update<br />
Loading composer repositories with package information<br />
Updating dependencies (including require-dev)<br />
(...demana user/password de packagist.org ...)<br />
<br />
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:<br />
$ ssh -L 3128:localhost:3128 jo@elmeuserver.com<br />
I un cop logats, aprofitem per instal·lar el squid:<br />
$ sudo apt install squid<br />
Hem de mantenir la shell oberta mentre vulguem que estigui activat el túnel (l'hem assignat a localhost:3128).<br />
<br />
Obrim una altra shell i anem al nostre projecte Laravel:<br />
$ export http_proxy=localhost:3128<br />
$ composer update<br />
<br />
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).<br />
<br />
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:<br />
$ ssh jo@elmeuserver.com<br />
$ sudo apt remove squid<br />
<br />
<br><br />
<br />
== Tutorials ==<br />
Després d'elaborar la documentació he trobat aquest tutorial bastant útil (només fins la v5.2):<br />
https://laravel.com/docs/5.2/quickstart<br />
<br />
Tutorial per a CRUD complert:<br />
https://www.itsolutionstuff.com/post/laravel-6-crud-application-tutorialexample.html<br />
<br />
== Resum per a fer un CRUD ==<br />
<br />
=== Setup projecte ===<br />
Crear projecte:<br />
$ laravel new proj1<br />
Crear DB (en aquest cas SQLite:<br />
$ touch db.sqlite<br />
Modifica .env per configurar la DB com sqlite:<br />
DB_CONNECTION=sqlite<br />
DB_DATABASE=/path/absolut/al/db.sqlite<br />
<br />
=== Model ===<br />
Crear taules i migracions:<br />
$ php artisan make:migration crea_taula_items --create=items<br />
Editar la migració per crear les taules adequades. Mira't les principals referències:<br />
* [https://laravel.com/docs/5.5/migrations#columns Tipus de columnes]<br />
* [https://laravel.com/docs/5.5/migrations#foreign-key-constraints Relacions i FKs]<br />
Realitzar la migració:<br />
$ php artisan migrate<br />
Crear models:<br />
$ php artisan make:model Item<br />
Ajusta el model perquè apunti al nom correcte de la taula:<br />
https://laravel.com/docs/5.5/eloquent#eloquent-model-conventions<br />
<br />
=== Controller i rutes ===<br />
Crear controllers amb els mètodes estàndard (index, create-store, show, edit-update, destroy):<br />
$ php artisan make:controller -r ItemController<br />
Crear rutes a <code>routes/web.php</code>:<br />
Route::resource("item","ItemController");<br />
Crear plantilles per als mètodes (l'exemple diu "tema" enlloc de "item"):<br />
$ php artisan route:list<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
| Domain | Method | URI | Name | Action | Middleware |<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
| | GET|HEAD | / | | Closure | web |<br />
| | GET|HEAD | api/user | | Closure | api,auth:api |<br />
| | GET|HEAD | tema | tema.index | App\Http\Controllers\TemaController@index | web |<br />
| | POST | tema | tema.store | App\Http\Controllers\TemaController@store | web |<br />
| | GET|HEAD | tema/create | tema.create | App\Http\Controllers\TemaController@create | web |<br />
| | GET|HEAD | tema/{tema} | tema.show | App\Http\Controllers\TemaController@show | web |<br />
| | PUT|PATCH | tema/{tema} | tema.update | App\Http\Controllers\TemaController@update | web |<br />
| | DELETE | tema/{tema} | tema.destroy | App\Http\Controllers\TemaController@destroy | web |<br />
| | GET|HEAD | tema/{tema}/edit | tema.edit | App\Http\Controllers\TemaController@edit | web |<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
<br />
Crear les views (plantilles blade) adequades per a tots els mètodes necessaris (els arxius van a <code>resources/views</code>). Pots veure [https://github.com/emieza/laravel-karaoke/tree/master/resources/views/llista aqui] alguns exemples.<br />
* '''index''' : llista tots els elements<br />
* '''show''' : mostra un element en concret, necessita que li passem un paràmetre per GET (id del element a mostrar)<br />
* '''create-store''' : "create és el form (no necessita codi), i "store" és el codi per insertar-ho a la BD (no necessita una plantilla)<br />
* '''edit-update''' : "edit" és el form, i "update" el codi per actualitzar la BD<br />
* '''destroy''' : elimina un element<br />
<br />
=== Codi del Controller i View ===<br />
* Crear views amb formularis d'entrada de dades: [https://github.com/emieza/laravel-karaoke/blob/master/resources/views/llista/crea.blade.php create.blade.php d'exemple]<br />
* Editar el codi del Controller per cridar pertinentment a les views: [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/LlistaController.php Controller d'exemple]<br />
<br />
=== Més docs ===<br />
Una bona referència de la doc oficial per fer un CRUD és aquesta:<br />
https://laravel.com/docs/5.2/quickstart<br />
En particular per veure com utilitzar les templates oficials amb bootstrap ;)<br />
<br />
<br><br />
<br />
== Projecte d'exemple ==<br />
Aquest és el projecte que he realitzat per entrenar-me, et pot servir d'exemple. El pots veure en producció aquí: https://jolgorio.tk<br />
https://github.com/emieza/laravel-karaoke<br />
<br />
Fes-li un cop d'ull al readme.md per veure com posar-lo en marxa.<br />
<br />
MOLT IMPORTANT PEL PROJECTE: Cal crear un README.md (com [https://github.com/emieza/laravel-karaoke/blob/master/readme.md per exemple aquest]). No acceptaré cap projecte sense README.md<br />
<br />
Per entrenar-vos amb el Markdown teniu aquest tester:<br />
http://dillinger.io/<br />
<br />
Anem per feina:<br />
# Taules: llistes, temes, vots<br />
# Rutes que vols implementar per al projecte. [https://github.com/emieza/laravel-karaoke/blob/master/routes/web.php En el meu cas, tinc]:<br />
#* /llista/crea (GET per formulari + POST per store)<br />
#* /llista (index de llistes)<br />
#* /llista/{id} (show)<br />
#* /llista/{id}/crea (GET + POST, per crear temes en les llistes)<br />
#* /vota/{idtema}<br />
# Codi:<br />
#* als Controllers pertinents. Mira't l'[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/LlistaController.php exemple de les llistes de karaoke].<br />
#* Plantilles: a resources/views/xxxx.blade.php . Mira't l'[https://github.com/emieza/laravel-karaoke/tree/master/resources/views/llista exemple un altre cop].<br />
<br />
<br><br />
<br />
== ORM : Models i relacions ==<br />
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.<br />
<br />
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. <br />
<br />
El què anem a explicar està documentat a l'apartat "Eloquent ORM" de Laravel:<br />
https://laravel.com/docs/5.7/eloquent-relationships<br />
https://laravel.com/docs/6.x/eloquent-relationships<br />
<br />
=== Accedint relacions 1-N de forma directa ===<br />
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í.<br />
<br />
L'objectiu serà poder accedir a l'objecte pare d'aquesta manera per mostrar el text del Post (pare).<br />
<syntaxhighlight lang="php"><br />
$comment = Comment::find(33);<br />
echo $comment->post->text;<br />
</syntaxhighlight><br />
<br />
Per aconseguir això, cal que indiquem la relació existent a les taules entre els models Post i Comment amb la relació <code>belongsTo</code>:<br />
<br />
<syntaxhighlight lang="php"><br />
<?php<br />
namespace App;<br />
use Illuminate\Database\Eloquent\Model;<br />
class Comment extends Model<br />
{<br />
/**<br />
* Accedeix al pare (Post)<br />
*/<br />
public function post()<br />
{<br />
return $this->belongsTo('App\Post','post_id');<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Accedint relacions 1-N de forma inversa ===<br />
El següent cas típic serà accedir des d'un objecte Post als diferents Comentaris, més o menys així:<br />
<br />
<syntaxhighlight lang="php"><br />
$comments = App\Post::find(1)->comments;<br />
foreach ($comments as $comment) {<br />
// ... el teu codi...<br />
echo $comment->text;<br />
}<br />
</syntaxhighlight><br />
El codi que veiem és per a un ''controller'', però es pot aplicar també als ''templates'', amb @foreach i similars.<br />
<br />
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<br />
<syntaxhighlight lang="php"><br />
<?php<br />
namespace App;<br />
use Illuminate\Database\Eloquent\Model;<br />
class Post extends Model<br />
{<br />
/**<br />
* Accedeix als comentaris relacionats amb el Post actual<br />
*/<br />
public function comments()<br />
{<br />
return $this->hasMany('App\Comment','<ref_remota>','<ref_local>');<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
On:<br />
* <ref_remota> és el camp de la taula de Comment que referencia el Post<br />
* <ref_local> és el camp de Post que fa de PK i on Comment apunta<br />
<br />
Per accedir al objecte relacionat "pare" caldrà fer una altra funció, en concret ''belongsTo''. Consulta la doc de les relacions 1-a-N (inversa).<br />
<br />
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:<br />
https://laravel.com/docs/5.5/eloquent-relationships#one-to-many<br />
<br />
=== Aniuant JSON en la API ===<br />
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:<br />
<br />
<syntaxhighlight lang="php"><br />
<?php<br />
Route::get("/comentaris", function() {<br />
$post = Post::with("comments")->get();<br />
return $post;<br />
});<br />
</syntaxhighlight><br />
<br />
...i ens retornarà les dades aniuades que volem! :)<br />
<br />
<br><br />
<br />
== Més coses ==<br />
Alguns temes que no hem aprofundit però que convé conèixer.<br />
<br />
=== Autenticació ===<br />
Senzill d'implementar i imprescindible. Laravel incorpora un ''scaffold'' per facilitar una funció tan estàndard.<br />
Amb una sola instrucció ens crea les rutes, vistes i els controllers típics (login, logout).<br />
<br />
==== Laravel 5.x ====<br />
[https://laravel.com/docs/5.5/authentication Autenticació en Laravel 5.x]:<br />
$ php artisan make:auth<br />
<br />
==== Laravel 6.x ====<br />
[https://laravel.com/docs/6.x/authentication Autenticació en Laravel 6.x]:<br />
$ composer require laravel/ui --dev<br />
$ php artisan ui vue --auth<br />
<br />
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:<br />
$ npm install && npm run dev<br />
<br />
També hi ha [https://laracasts.com/discuss/channels/laravel/laravel-60-appcss?page=1 solucions al problema carregant els CSS i JS del CDN] (només cal canviar un link en el ''head'' de <code>app.blade.php</code>.<br />
<br />
==== Laravel 8.x ====<br />
Ara el mòdul d'autenticació es diu [https://laravel.com/docs/8.x/starter-kits#laravel-breeze Laravel Breeze].<br />
<br />
ULL! Si instal·lem Laravel Breeze, aquest sobreescriurà arxius d'algunes ''views'' i ''routes''. En particular, abans d'instal·lar, feu un backup de:<br />
* resources/views/layouts/app.blade.php<br />
* resources/views/layouts/guest.blade.php<br />
* resources/views/layouts/navigation.blade.php<br />
* resources/views/welcome.blade.php<br />
* resources/views/dashboard.blade.php<br />
* routes/web.php<br />
<br />
Resumint, per instal·lar Breeze:<br />
$ composer require laravel/breeze --dev<br />
$ php artisan breeze:install<br />
$ npm install<br />
$ npm run dev<br />
<br />
=== Seeding ===<br />
Una part molt important és la de crear dades per farcir la base de dades inicialment i poder així testejar amb comoditat.<br />
<br />
https://laravel.com/docs/6.x/seeding<br />
<br />
En algun moment donat convé utilitzar un ''factory'' que ens permet crear elements en massa:<br />
<br />
https://laravel.com/docs/6.x/database-testing#writing-factories<br />
<br />
El ''factory'' sol utilitzar una llibreria <code>Faker</code> que ens va molt bé per crear noms i cognoms aleatoris, lorem ipsum, etc. que ens facilitarà la creació de dades de prova.<br />
<br />
https://github.com/fzaninotto/Faker<br />
<br />
=== Validacions ===<br />
Laravel ens ofereix un mecanisme de validació de formularis molt potent i efectiu.<br />
<br />
https://laravel.com/docs/5.5/validation<br />
<br />
=== Sessions ===<br />
D'entrada és molt útil per emetre missatges "flash", i informar l'usuari del processament intern.<br />
<br />
https://laravel.com/docs/5.5/session<br />
<br />
=== Arxius: filesystem vs BLOBs en BD ===<br />
Les imatges es poden guardar al sistema d'arxius o bé a la base de dades.<br />
* '''Filesystem''': En el propi tutorial hi ha una explicació de [https://ajgallego.gitbooks.io/laravel-5/content/capitulo_4_datos_de_entrada.html com guardar binaris amb el mètode clàssic del filesystem]<br />
* '''BLOBs en la BD''': Laravel ens permet crear models amb BLOBs i insertar les dades a la BD:<br />
** [https://www.daniweb.com/programming/web-development/threads/480731/how-to-inserting-files-on-mysql-using-laravel Insertant BLOBs amb Larvel]<br />
** Tingueu en compte, si ho feu així, de [https://stackoverflow.com/questions/8499633/how-to-display-base64-images-in-html com renderitzar continguts base64 (BLOBs) sobre un HTML]<br />
<br />
=== A solucionar ===<br />
Alguns temes a solucionar:<br />
* Quan utilitzem el scaffold d'autenticació, falla el logout. Això es deu a un canvi del mètode de GET a POST per motius de seguretat (amb POST, només podran fer logout des de la pròpia app Laravel ja que porta el csrf_token).<br />
*: https://laracasts.com/discuss/channels/laravel/laravel-53-logout-methodnotallowed<br />
<br />
<br><br />
<br />
=== Atacant 2 bases de dades simultàniament ===<br />
En alguns casos podem necessitar configurar 2 instàncies de bases de dades separades per optimitzar el rendiment. Aquest post ho explica molt bé:<br />
https://fideloper.com/laravel-multiple-database-connections<br />
<br />
Caldrà configurar el .env , config/database.php i especificar quina DB ataca en les migracions i en els models que creem.<br />
<br />
<br><br />
<br />
== Laravel i LDAP ==<br />
Aquest mòdul està pensat per a Active Directory, però [https://github.com/Adldap2/Adldap2-Laravel/issues/106 també funciona amb OpenLDAP si s'ajusta bé]:<br />
https://github.com/Adldap2/Adldap2-Laravel<br />
<br />
Primer cal configurar un servidor [[LDAP]].<br />
<br />
Després, tingues en compte que cal ajustar els següents paràmetres en el .env:<br />
ADLDAP_CONTROLLERS=localhost<br />
#ADLDAP_PORT=389<br />
ADLDAP_ADMIN_USERNAME="cn=admin,dc=cacauet,dc=org"<br />
ADLDAP_ADMIN_PASSWORD="enric123"<br />
ADLDAP_BASEDN="dc=cacauet,dc=org"<br />
<br />
Podem fer una autenticació seguint algun d'aquests exemples.<br />
<br />
Exemple 1: cercar un element del directori<br />
<syntaxhighlight lang="php"><br />
$user = Adldap::search()->where("mail","=","pepe@jolgorio.tk")->get();<br />
</syntaxhighlight><br />
<br />
Exemple 2: autenticar un usuari<br />
<syntaxhighlight lang="php"><br />
if( Adldap::auth()->attempt("cn=pepe,ou=usuaris,dc=cacauet,dc=org","pepe123")) {<br />
// autenticació exitosa<br />
return "Pepe OK!";<br />
}<br />
</syntaxhighlight><br />
<br />
<br><br />
<br />
== Laravel en producció ==<br />
Per posar en producció un projecte basat en Laravel cal tenir en compte:<br />
* '''IMPORTANT, SEGURETAT: Només cal publicar la carpeta <code>/public</code>''' . 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 .<br />
** Aquesta carpeta <code>/public</code> no figura inicialment quan creem o clonem un projecte (està a .gitignore), a l'igual que la carpeta <code>/vendor</code>, que es generen quan fem un <code>$ composer install</code>.<br />
** Reviseu la secció [[Laravel#Treballant_amb_GIT_i_clonant]] per fer el setup del projecte després de clonar.<br />
* '''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'').<br />
* 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:<br />
** db.sqlite (si s'escau)<br />
** carpeta <code>/storage</code><br />
** carpeta <code>/bootstrap/cache</code><br />
<br />
=== Desplegament en AWS amb Ubuntu i Apache ===<br />
Guia pel desplegament en Ubuntu amb Apache:<br />
* Accedir al nostre servidor via SSH<br />
* 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<pre>/var/www</pre><br />
* Per veure detalls reviseu la secció [[Laravel#Treballant_amb_GIT_i_clonant]]. Recordeu que això implica: <br />
*# composer install<br />
*# configurar arxiu .env<br />
*# generar clau<br />
* Es requereix el mòdul ''mod_rewrite'' d'Apache (o Nginx)<pre>$ sudo a2enmod rewrite</pre><br />
* Publicar la carpeta <code>/public</code> del projecte Laravel, d'alguna d'aquestes maneres:<br />
** Crear un VirtualHost i apuntar la ServerRoot del domini o subdomini a /var/www/<projecte>/public<br />
** Crear un link simbòlic de la carpeta pública d'Apache a la carpeta public del Laravel amb la comanda <pre>$ ln -s /var/www/<projecte>/public /var/www/html/lara1</pre><br />
* 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".<br />
* Ajusta els permisos de:<br />
** db.sqlite (si s'escau) i també de la carpeta que el conté (si no, no es podrà escriure-hi)<br />
** carpeta <code>/storage</code><br />
** carpeta <code>/bootstrap/cache</code><br />
* Cal activar els arxius <code>.htaccess</code> , afegint la directiva <code>AllowOverride all</code><br />
<br />
A l'arxiu de conf. del nostre VirtualHost (a <code>/etc/apache2/sites-available</code>):<br />
<Directory /var/www/><br />
AllowOverride All<br />
</Directory><br />
<br />
<br />
És important remarcar que per SEGURETAT no hem de mostrar mai els arxius interns de Laravel, només cal publicar el contingut de /public<br />
<br />
<br><br />
<br />
=== Heroku ===<br />
Abans de procedir amb aquesta part hauries de llegir i treballar aquesta altra: [[Heroku]] on treballem amb PHP simple.<br />
<br />
Pots posar en marxa un projecte Laravel a Heroku fàcilment seguint aquesta documentació. Segueix el tutorial per iniciar la app:<br />
https://devcenter.heroku.com/articles/getting-started-with-laravel<br />
<br />
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.<br />
<br />
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.<br />
<br />
En canvi, [https://devcenter.heroku.com/articles/heroku-postgresql el add-on de POSTGRESQL és gratuït i sense targeta de crèdit! :)] Som-hi, doncs!<br />
<br />
Primer de tot, creeu el projecte Laravel i inicialitzeu GIT en cas que no el tingueu penjat a Github o similars:<br />
$ git init<br />
<br />
Tb caldrà afegir un Procfile adequat per Laravel:<br />
$ echo "web: vendor/bin/heroku-php-apache2 public/" > Procfile<br />
<br />
Inicialitzem projecte Heroku:<br />
$ heroku create elmeuprojectedeguais<br />
<br />
Afegim els arxius al repo local:<br />
$ git add .<br />
$ git commit -am "primer commit"<br />
<br />
Afegim la BD PostgreSQL:<br />
$ heroku addons:create heroku-postgresql:hobby-dev<br />
<br />
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:<br />
$ heroku config -s | grep -i post<br />
<br />
Ens ho dona en la següent forma (exemple a continuació):<br />
DATABASE_URL='postgres://<usuari>:<password>@<maquina>:<port>/<bbdd>'<br />
DATABASE_URL='postgres://mxlsfebqyopadb:3e5af56b52cc06574645123ea9d9f7504564e207804dcc71a2db2848446ba064@ec2-156-73-167-43.compute-1.amazonaws.com:5432/d353ihheo564q7'<br />
<br />
Així, doncs, només caldrà ajustar les següents variables d'entorn que necessita el Laravel perquè això funcioni:<br />
DB_CONNECTION=pgsql<br />
DB_HOST=ec2-156...<br />
DB_PORT=5432<br />
DB_DATABASE=d353...<br />
DB_USERNAME=mxls...<br />
DB_PASSWORD=3e5a...<br />
<br />
Per fer-ho cal anar executant les següents ordres:<br />
$ heroku config:set DB_CONNECTION=pgsql<br />
$ ...etc...<br />
<br />
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:<br />
$ cp .env.example .env<br />
$ php artisan key:generate<br />
$ heroku config:set APP_KEY=base64:tX2ikx...<br />
<br />
En acabat, podem posar la app en producció:<br />
$ git add .<br />
$ git push heroku master<br />
<br />
I un cop acabats, migrem la nostra base de dades:<br />
$ heroku run php artisan migrate<br />
<br />
I veure la nostra flamant web en producció (a elmeuprojectedeguais.herokuapp.com):<br />
$ heroku open<br />
<br />
...et voilà!</div>Enrichttps://cacauet.org/wiki/index.php?title=Programaci%C3%B3_web_entorn_servidor&diff=4223Programació web entorn servidor2021-02-02T09:56:50Z<p>Enric: /* UF3 Accés a dades */</p>
<hr />
<div><nowiki>#FpInfor #DawMp07<br />
#DawMp07Uf01 #DawMp07Uf02 #DawMp07Uf03 #DawMp07Uf04<br />
</nowiki><br />
<br />
<br />
En aquesta assignatura treballarem bàsicament amb PHP, que actualment és el llenguatge més estès per a la programació web.<br />
<br />
Recursos:<br />
* Quadern d'exercicis del Daniel Herrera (molt agraït):<pre>https://uf.ctrl-alt-d.net</pre><br />
* Al mateix cacauet.org també disposeu de recursos varis:<br />
*: [[Curs de PHP]]<br />
<br />
<br><br />
<br />
== UF1 Programació web entorn servidor ==<br />
Per configurar adequadament el Apache, reviseu [[Php.ini]]<br />
<br />
[https://uf.ctrl-alt-d.net/material/mostra/288/abc-index-dexercicis Índex d'exercicis]<br />
<br />
Temes a tractar amb PHP:<br />
* [[Web_technology_overview|Execució servidor vs client]]<br />
* Servidor web<br />
* Tipus primitius de dades<br />
* Arrays i arrays associatius (aka "diccionaris")<br />
* Control de flux<br />
* Funcions<br />
* Objectes<br />
* Arxius<br />
* [[PHP Forms|Formularis]]<br />
* GET vs POST<br />
* Cookies i [[PHP sessions]]<br />
<br />
Exemples:<br />
* [[Batalla naval en PHP]] (versions amb i sense sessions)<br />
<br />
Exercicis entregables:<br />
# [https://uf.ctrl-alt-d.net/material/mostra/294/calendari-en-php Calendari]<br />
# [https://uf.ctrl-alt-d.net/material/mostra/40/php-els-ingredients-de-la-pizza La pizza]<br />
# [https://uf.ctrl-alt-d.net/material/mostra/299/php-sudoku-amb-formularis-i-sessions Sudoku]<br />
# [https://uf.ctrl-alt-d.net/material/mostra/307/moviment-duna-peca-descacs-en-php Moure una peça d'escacs].<br />
<br />
<br><br />
<br />
== UF3 Accés a dades ==<br />
En aquesta UF estudiarem diversos mètodes d'accés a bases de dades, imprescindibles per poder realitzar pàgines web dinàmiques.<br />
<br />
Índex UF3 al quadern d'exercicis:<br />
https://github.com/ctrl-alt-d/FpUf/tree/main/DAW/DAW-MP07/DAW-MP07-UF3/tecniques-dacces-a-dades-metacontingut<br />
<br />
Començarem, però, per alguns exemples clàssics: [[Imatge:Filtre-continent.png|thumb|Llistat de països filtrats per continents.]]<br />
# [[PHP MySQL select]]: accedirem a una base de dades de la manera més clàssica i menys eficient, amb instruccions específiques per a un SGBD concret (MySQL). Òbviament, això no és gaire òptim però està bé conèixer els mecanismes bàsics.<br />
# '''PDO''' o PHP Data Objects<br />
#* Llegeix-te aquest [https://github.com/ctrl-alt-d/FpUf/tree/main/DAW/DAW-MP07/DAW-MP07-UF3/php-acces-a-dades-amb-pdo exercici d'accés a dades amb PDO].<br />
#*:Para atenció en com es fa el ''foreach'' enlloc del ''for'' habitual.<br />
#* Exercici: Utilitza la base de dades WORLD vista al primer tutorial.<br />
#** Fes un formulari amb un desplegable dels CONTINENTS.<br />
#** Llista els països amb un filtre per continent.<br />
#** Mostra la població de cada país i un total de tot el continent.<br />
<br />
<br><br />
<br />
El projecte d'aquest any: [https://wiket.esteveterradas.cat/index.php/Projecte_Vota_-_Especificacions Projecte VOTA!]<br />
<br />
[[Imatge:Vota4.jpg|450px]]<br />
<br />
<br><br />
<br />
== UF2 Programació de webs dinàmiques ==<br />
Prèviament hem après a programar ja en PHP i amb bases de dades, però hem aprés de forma un tant anàrquica, i hem vist en el transcurs dels projectes que tendim a fer "codi espagueti" i acabem repetint moltes parts del mateix de forma recorrent. En aquesta UF aprendrem a programar de forma més ordenada i aprendrem una sèrie d'eines imprescindibles per desenvolupar de forma segura i metòdica: els '''''frameworks'''''. En particular utilitzarem [[Laravel]] que és el ''framework'' per a PHP més famós actualment (a principis de 2018).<br />
<br />
Un framework es sol definir com:<br />
- un conjunt d'eines i llibreries<br />
- un conjunt de bones pràctiques per treballar amb aquestes eines<br />
<br />
Introducció i referències:<br />
* [[Desenvolupament d'aplicacions web amb frameworks]] una mica de teoria.<br />
* [[Laravel]]: instal·lació i primeres passes<br />
* Apunts del Sergi Coll: https://seicoll.github.io/DAW-M07-UF2-Apunts/<br />
* Tutorial de referència: https://ajgallego.gitbooks.io/laravel-5/content/index.html<br />
* [[Laravel#Quickstart_per_a_fer_un_CRUD|Xuleta de referència ràpida per a projectes amb Laravel]]<br />
<br />
Una de les característiques més incòmodes dels frameworks és que tenen una certa "corba d'aprenentatge", és a dir, que al principi costa una mica ficar-se. Un cop superat el segon projecte, tot resulta més fàcil i comprensible, i ajuda a programar amb ordre i de forma estandarditzada.<br />
<br />
Farem servir el tutorial de AJ Gallego per a endinsar-nos en el món de Laravel. Com que té la seva complicació i costa retenir cada pas que fem, dividirem el tutorial en diverses parts i repetirem el procediment realitzat en un altre projecte. Per senzillesa repetirem el projecte de la UF anterior però implementat ara amb el ''framework'', cosa que ens permetrà comparar el codi resultant dels dos projectes.<br />
<br />
El tutorial és aquest:<br />
https://ajgallego.gitbooks.io/laravel-5/content/index.html<br />
Com que algunes parts han quedat obsoletes, utilitza la [[Laravel|documentació de cacauet.org sobre Laravel]] per solventar els problemes. <br />
<br />
I les seves diverses parts son:<br />
# Instal·lació i eines Composer: [[Laravel#Instal.C2.B7lació_i_setup]]<br />
# Vistes i Controladors<br />
# Model i base de dades<br />
# Autenticació i autorització (middleware)<br />
<br />
Realitzarem totes aquestes passes primer amb el propi tutorial, i amb el projecte de la UF anterior (Vota2) de forma individual, per consolidar la comprensió de la mecànica del ''framework''.<br />
<br />
Al final de la UF realitzarem un projecte en grups. Aquest any serà el [https://wiket.esteveterradas.cat/index.php/Projecte_Xat_-_Especificacions projecte Xat per a un Ajuntament].<br />
<br />
Els lliuraments finalment seran:<br />
* Repositori del Github del tutorial (individual)<br />
* Repositori del Github del projecte Vota2 (individual)<br />
* Repositori del Github del projecte Xat (en grup)<br />
<br />
<br><br />
<br />
== UF4 Serveis web ==<br />
Els [https://ca.wikipedia.org/wiki/Servei_web serveis web], simplificant, és una manera de realitzar '''crides a funcions remotes''' mitjançant el protocol HTTP. És la forma més còmoda per al programador web d'anar a buscar dades a un servidor, ja sigui des d'un altre servidor o des d'un client.<br />
<br />
Al tractar-se, com hem dit, de "crides a funcions remotes", solem anomenar-los [https://ca.wikipedia.org/wiki/Interf%C3%ADcie_de_programaci%C3%B3_d'aplicacions API : Application Programming Interface].<br />
<br />
Articles de referència:<br />
* [[Serveis Web]]<br />
* [[Serveis web amb Laravel]]<br />
* Pràctica entregable: [[Serveis Web amb Opendata]]<br />
* Material addicional en Python: [[Web Services: exemple Escacs]]<br />
* [https://ajgallego.gitbooks.io/laravel-5/content/capitulo_5.html REST i CURL del tutorial de Laravel de AJ Gallego]<br />
<br />
<br></div>Enrichttps://cacauet.org/wiki/index.php?title=Laravel&diff=4222Laravel2021-02-01T17:44:56Z<p>Enric: /* Heroku */</p>
<hr />
<div><nowiki>#FpInfor #DawMp07 #DawMp07Uf2 #DawMp07Uf02 #DawMpDual</nowiki><br />
<br />
<br />
== Intro i referències ==<br />
Laravel és un framework web per a PHP que està agafant molta força.<br />
<br />
Documentació oficial: https://laravel.com/docs/<br />
<br />
Tutorials:<br />
* [https://ajgallego.gitbooks.io/laravel-5/content/index.html Principal tutorial per seguir el curs]: <pre>https://ajgallego.gitbooks.io/laravel-5/content/index.html</pre><br />
* Forms: https://selftaughtcoders.com/from-idea-to-launch/lesson-23/laravel-5-application-form-model-binding-laravelcollective-forms-html-library-bootstrap-framework/<br />
* Forms i validació: https://scotch.io/tutorials/simple-laravel-crud-with-resource-controllers<br />
* Apunts del Sergi Coll: https://seicoll.github.io/DAW-M07-UF2-Apunts/<br />
* https://styde.net/laravel-5/<br />
* Per passar del schema SQL (per ex. de MySQL Workbench) a Laravel migration: https://adolfocuadros.com/sql_to_laravel/<br />
<br />
<br />
Plugins:<br />
* CORS (Cross-Origin Resource Sharing): https://github.com/barryvdh/laravel-cors<br />
* CRUD & admin : Hi ha molts plugins per crear ''admin panels'' automàticament. Alguns son:<br />
** Voyager: https://voyager.devdojo.com/<br />
** Craftable: https://www.getcraftable.com/<br />
* https://iamacoder.com/post/5-must-have-laravel-5-packages/<br />
<br />
Temes a ampliar:<br />
* Forms: https://laravel.com/docs/4.2/html<br />
* Validació de forms: https://laravel.com/docs/5.5/validation<br />
* Autenticació: https://laravel.com/docs/5.5/authentication<br />
<br />
<br><br />
<br />
== Instal·lació i setup ==<br />
<br />
Prerequisits:<br />
* Laravel i PHP, és molt important tenir en compte les versions:<br />
** <strike>Laravel 5.3 : PHP >= 5.6.4<br />
** Laravel 5.5 : PHP == 7.0<br />
** Laravel 5.6 : PHP >= 7.1<br />
** Laravel 5.7 : PHP >= 7.1.3</strike><br />
** Laravel 6.x : PHP >= 7.2<br />
* Si utilitzes Ubuntu 14 o menor [https://www.digitalocean.com/community/tutorials/how-to-upgrade-to-php-7-on-ubuntu-14-04 actualitza la teva versió de PHP a la 7.0]<br />
* Calen els paquets següents: <pre>$ sudo apt-get install php-mbstring php-zip php-xml php-mysql</pre><br />
<br />
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...:<br />
# Instal·la el gestor de paquets per PHP Composer<br />
#* El més fàcil és fer: (però no ho farem pq volem la darrera versió)<pre>$ sudo apt install composer</pre><br />
#* Prova primer la instal·lació genèrica : [https://getcomposer.org/download/ Instal.la PHP Composer]<br />
#* També tens aquesta altra forma d' [https://getcomposer.org/doc/00-intro.md#installation-linux-unix-osx instal·lar Composer per GNU/Linux]. Descarrega composer-setup.php i instal·la'l així:<pre>$ php composer-setup.php --install-dir=~/bin --filename=composer</pre><br />
# Instal·la la darrera versió de Laravel<br />
#* https://laravel.com/docs/5.7/installation<br />
#* Bàsicament el què cal fer és aquesta comanda per instal·lar el binari ''laravel'':<pre>$ composer global require laravel/installer</pre><br />
#* Laravel s'instal·la a <code>$HOME/.config/composer</code> però per poder executar les properes comandes necessitarem tenir <code>$HOME/.config/composer/vendor/bin</code> al nostre $PATH. Inserta això al teu <code>$HOME/.profile</code>: <pre>PATH=$PATH:~/.config/composer/vendor/bin</pre><br />
#*: Fes logout/login del sistema per activar aquests canvis<br />
# Crea una app Laravel allà on et faci més ràbia: <pre>$ laravel new laravelapp1</pre><br />
#: o també: <pre>$ composer create-project --prefer-dist laravel/laravel laravelapp1</pre><br />
#: o si volem una versió específica de laravel: <pre>$ composer create-project --prefer-dist laravel/laravel=5.8.* laravelapp1</pre><br />
# Arrenca l'aplicació de prova: <pre>$ php artisan serve</pre><br />
# Comprova la app amb el navegador a<pre>http://localhost:8000</pre><br />
<br />
<br><br />
<br />
Si ja has completat la instal·lació, pots procedir a crear un altre projecte nou i realitzar el següent tutorial "tasklist":<br />
https://laravel.com/docs/5.2/quickstart<br />
<br />
<br><br />
<br />
== Incidències vàries ==<br />
Aquest és un bon tutorial:<br />
https://ajgallego.gitbooks.io/laravel-5/content/index.html<br />
<br />
Igualment, podríem trobar algunes incidències. Us dono pistes:<br />
<br />
=== Treballant amb GIT i clonant ===<br />
Al pujar el projecte a un repo GIT, i clonar-lo després caldrà:<br />
# Re-instal·lar les dependències:<pre>$ composer install</pre><br />
# Regenerar arxiu <code>.env</code> : com que depèn de cada entorn no es fica al projecte (es posa a <code>.gitignore</code>), però pots copiar i modificar de <code>.env.example</code><br />
# Error ''The only supported ciphers are AES-128-CBC and AES-256-CBC with the correct key lengths.'' Es soluciona amb :<pre>$ php artisan key:generate</pre><br />
<br />
=== Creant controllers amb CRUD complert ===<br />
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.<br />
# Ja no es pot fer amb <strike><code>Route::controller</code></strike> sinó amb:<pre>Route::resource("cosa","CosaController");</pre><br />
# Per exemple, per crear un controller per al model "Cosa" ho faríem amb -r (de resource): <pre>$ php artisan make:controller -r CosaController</pre><br />
<br />
=== Treballant amb SQLite ===<br />
Per configurar la BD amb SQLite cal crear el fitxer abans amb:<br />
$ touch db.sqlite<br />
<br />
Configurar la BD a .env:<br />
DB_CONNECTION=sqlite<br />
DB_DATABASE=/path/absolut/al/db.sqlite<br />
<br />
Instal·lar els binaris necessaris de SQLite i de PHP:<br />
$ sudo apt-get install sqlite php-sqlite3<br />
<br />
I crear la BD inicial amb:<br />
$ php artisan migrate<br />
<br />
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.<br />
<br />
=== Eliminant models o migracions ===<br />
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:<br />
$ composer dump-autoload<br />
...i es tornaran a generar els arxius d'autoload sense els arxius que volíem esborrar.<br />
<br />
=== Treballant amb proxies i composer ===<br />
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):<br />
$ composer update<br />
Loading composer repositories with package information<br />
Updating dependencies (including require-dev)<br />
(...demana user/password de packagist.org ...)<br />
<br />
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:<br />
$ ssh -L 3128:localhost:3128 jo@elmeuserver.com<br />
I un cop logats, aprofitem per instal·lar el squid:<br />
$ sudo apt install squid<br />
Hem de mantenir la shell oberta mentre vulguem que estigui activat el túnel (l'hem assignat a localhost:3128).<br />
<br />
Obrim una altra shell i anem al nostre projecte Laravel:<br />
$ export http_proxy=localhost:3128<br />
$ composer update<br />
<br />
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).<br />
<br />
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:<br />
$ ssh jo@elmeuserver.com<br />
$ sudo apt remove squid<br />
<br />
<br><br />
<br />
== Tutorials ==<br />
Després d'elaborar la documentació he trobat aquest tutorial bastant útil (només fins la v5.2):<br />
https://laravel.com/docs/5.2/quickstart<br />
<br />
Tutorial per a CRUD complert:<br />
https://www.itsolutionstuff.com/post/laravel-6-crud-application-tutorialexample.html<br />
<br />
== Resum per a fer un CRUD ==<br />
<br />
=== Setup projecte ===<br />
Crear projecte:<br />
$ laravel new proj1<br />
Crear DB (en aquest cas SQLite:<br />
$ touch db.sqlite<br />
Modifica .env per configurar la DB com sqlite:<br />
DB_CONNECTION=sqlite<br />
DB_DATABASE=/path/absolut/al/db.sqlite<br />
<br />
=== Model ===<br />
Crear taules i migracions:<br />
$ php artisan make:migration crea_taula_items --create=items<br />
Editar la migració per crear les taules adequades. Mira't les principals referències:<br />
* [https://laravel.com/docs/5.5/migrations#columns Tipus de columnes]<br />
* [https://laravel.com/docs/5.5/migrations#foreign-key-constraints Relacions i FKs]<br />
Realitzar la migració:<br />
$ php artisan migrate<br />
Crear models:<br />
$ php artisan make:model Item<br />
Ajusta el model perquè apunti al nom correcte de la taula:<br />
https://laravel.com/docs/5.5/eloquent#eloquent-model-conventions<br />
<br />
=== Controller i rutes ===<br />
Crear controllers amb els mètodes estàndard (index, create-store, show, edit-update, destroy):<br />
$ php artisan make:controller -r ItemController<br />
Crear rutes a <code>routes/web.php</code>:<br />
Route::resource("item","ItemController");<br />
Crear plantilles per als mètodes (l'exemple diu "tema" enlloc de "item"):<br />
$ php artisan route:list<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
| Domain | Method | URI | Name | Action | Middleware |<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
| | GET|HEAD | / | | Closure | web |<br />
| | GET|HEAD | api/user | | Closure | api,auth:api |<br />
| | GET|HEAD | tema | tema.index | App\Http\Controllers\TemaController@index | web |<br />
| | POST | tema | tema.store | App\Http\Controllers\TemaController@store | web |<br />
| | GET|HEAD | tema/create | tema.create | App\Http\Controllers\TemaController@create | web |<br />
| | GET|HEAD | tema/{tema} | tema.show | App\Http\Controllers\TemaController@show | web |<br />
| | PUT|PATCH | tema/{tema} | tema.update | App\Http\Controllers\TemaController@update | web |<br />
| | DELETE | tema/{tema} | tema.destroy | App\Http\Controllers\TemaController@destroy | web |<br />
| | GET|HEAD | tema/{tema}/edit | tema.edit | App\Http\Controllers\TemaController@edit | web |<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
<br />
Crear les views (plantilles blade) adequades per a tots els mètodes necessaris (els arxius van a <code>resources/views</code>). Pots veure [https://github.com/emieza/laravel-karaoke/tree/master/resources/views/llista aqui] alguns exemples.<br />
* '''index''' : llista tots els elements<br />
* '''show''' : mostra un element en concret, necessita que li passem un paràmetre per GET (id del element a mostrar)<br />
* '''create-store''' : "create és el form (no necessita codi), i "store" és el codi per insertar-ho a la BD (no necessita una plantilla)<br />
* '''edit-update''' : "edit" és el form, i "update" el codi per actualitzar la BD<br />
* '''destroy''' : elimina un element<br />
<br />
=== Codi del Controller i View ===<br />
* Crear views amb formularis d'entrada de dades: [https://github.com/emieza/laravel-karaoke/blob/master/resources/views/llista/crea.blade.php create.blade.php d'exemple]<br />
* Editar el codi del Controller per cridar pertinentment a les views: [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/LlistaController.php Controller d'exemple]<br />
<br />
=== Més docs ===<br />
Una bona referència de la doc oficial per fer un CRUD és aquesta:<br />
https://laravel.com/docs/5.2/quickstart<br />
En particular per veure com utilitzar les templates oficials amb bootstrap ;)<br />
<br />
<br><br />
<br />
== Projecte d'exemple ==<br />
Aquest és el projecte que he realitzat per entrenar-me, et pot servir d'exemple. El pots veure en producció aquí: https://jolgorio.tk<br />
https://github.com/emieza/laravel-karaoke<br />
<br />
Fes-li un cop d'ull al readme.md per veure com posar-lo en marxa.<br />
<br />
MOLT IMPORTANT PEL PROJECTE: Cal crear un README.md (com [https://github.com/emieza/laravel-karaoke/blob/master/readme.md per exemple aquest]). No acceptaré cap projecte sense README.md<br />
<br />
Per entrenar-vos amb el Markdown teniu aquest tester:<br />
http://dillinger.io/<br />
<br />
Anem per feina:<br />
# Taules: llistes, temes, vots<br />
# Rutes que vols implementar per al projecte. [https://github.com/emieza/laravel-karaoke/blob/master/routes/web.php En el meu cas, tinc]:<br />
#* /llista/crea (GET per formulari + POST per store)<br />
#* /llista (index de llistes)<br />
#* /llista/{id} (show)<br />
#* /llista/{id}/crea (GET + POST, per crear temes en les llistes)<br />
#* /vota/{idtema}<br />
# Codi:<br />
#* als Controllers pertinents. Mira't l'[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/LlistaController.php exemple de les llistes de karaoke].<br />
#* Plantilles: a resources/views/xxxx.blade.php . Mira't l'[https://github.com/emieza/laravel-karaoke/tree/master/resources/views/llista exemple un altre cop].<br />
<br />
<br><br />
<br />
== ORM : Models i relacions ==<br />
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.<br />
<br />
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. <br />
<br />
El què anem a explicar està documentat a l'apartat "Eloquent ORM" de Laravel:<br />
https://laravel.com/docs/5.7/eloquent-relationships<br />
https://laravel.com/docs/6.x/eloquent-relationships<br />
<br />
=== Accedint relacions 1-N de forma directa ===<br />
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í.<br />
<br />
L'objectiu serà poder accedir a l'objecte pare d'aquesta manera per mostrar el text del Post (pare).<br />
<syntaxhighlight lang="php"><br />
$comment = Comment::find(33);<br />
echo $comment->post->text;<br />
</syntaxhighlight><br />
<br />
Per aconseguir això, cal que indiquem la relació existent a les taules entre els models Post i Comment amb la relació <code>belongsTo</code>:<br />
<br />
<syntaxhighlight lang="php"><br />
<?php<br />
namespace App;<br />
use Illuminate\Database\Eloquent\Model;<br />
class Comment extends Model<br />
{<br />
/**<br />
* Accedeix al pare (Post)<br />
*/<br />
public function post()<br />
{<br />
return $this->belongsTo('App\Post','post_id');<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Accedint relacions 1-N de forma inversa ===<br />
El següent cas típic serà accedir des d'un objecte Post als diferents Comentaris, més o menys així:<br />
<br />
<syntaxhighlight lang="php"><br />
$comments = App\Post::find(1)->comments;<br />
foreach ($comments as $comment) {<br />
// ... el teu codi...<br />
echo $comment->text;<br />
}<br />
</syntaxhighlight><br />
El codi que veiem és per a un ''controller'', però es pot aplicar també als ''templates'', amb @foreach i similars.<br />
<br />
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<br />
<syntaxhighlight lang="php"><br />
<?php<br />
namespace App;<br />
use Illuminate\Database\Eloquent\Model;<br />
class Post extends Model<br />
{<br />
/**<br />
* Accedeix als comentaris relacionats amb el Post actual<br />
*/<br />
public function comments()<br />
{<br />
return $this->hasMany('App\Comment','<ref_remota>','<ref_local>');<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
On:<br />
* <ref_remota> és el camp de la taula de Comment que referencia el Post<br />
* <ref_local> és el camp de Post que fa de PK i on Comment apunta<br />
<br />
Per accedir al objecte relacionat "pare" caldrà fer una altra funció, en concret ''belongsTo''. Consulta la doc de les relacions 1-a-N (inversa).<br />
<br />
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:<br />
https://laravel.com/docs/5.5/eloquent-relationships#one-to-many<br />
<br />
=== Aniuant JSON en la API ===<br />
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:<br />
<br />
<syntaxhighlight lang="php"><br />
<?php<br />
Route::get("/comentaris", function() {<br />
$post = Post::with("comments")->get();<br />
return $post;<br />
});<br />
</syntaxhighlight><br />
<br />
...i ens retornarà les dades aniuades que volem! :)<br />
<br />
<br><br />
<br />
== Més coses ==<br />
Alguns temes que no hem aprofundit però que convé conèixer.<br />
<br />
=== Autenticació ===<br />
Senzill d'implementar i imprescindible. Laravel incorpora un ''scaffold'' per facilitar una funció tan estàndard.<br />
Amb una sola instrucció ens crea les rutes, vistes i els controllers típics (login, logout).<br />
<br />
[https://laravel.com/docs/5.5/authentication Autenticació en Laravel 5.x]:<br />
$ php artisan make:auth<br />
<br />
[https://laravel.com/docs/6.x/authentication Autenticació en Laravel 6.x]:<br />
$ composer require laravel/ui --dev<br />
$ php artisan ui vue --auth<br />
<br />
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:<br />
$ npm install && npm run dev<br />
<br />
També hi ha [https://laracasts.com/discuss/channels/laravel/laravel-60-appcss?page=1 solucions al problema carregant els CSS i JS del CDN] (només cal canviar un link en el ''head'' de <code>app.blade.php</code>.<br />
<br />
=== Seeding ===<br />
Una part molt important és la de crear dades per farcir la base de dades inicialment i poder així testejar amb comoditat.<br />
<br />
https://laravel.com/docs/6.x/seeding<br />
<br />
En algun moment donat convé utilitzar un ''factory'' que ens permet crear elements en massa:<br />
<br />
https://laravel.com/docs/6.x/database-testing#writing-factories<br />
<br />
El ''factory'' sol utilitzar una llibreria <code>Faker</code> que ens va molt bé per crear noms i cognoms aleatoris, lorem ipsum, etc. que ens facilitarà la creació de dades de prova.<br />
<br />
https://github.com/fzaninotto/Faker<br />
<br />
=== Validacions ===<br />
Laravel ens ofereix un mecanisme de validació de formularis molt potent i efectiu.<br />
<br />
https://laravel.com/docs/5.5/validation<br />
<br />
=== Sessions ===<br />
D'entrada és molt útil per emetre missatges "flash", i informar l'usuari del processament intern.<br />
<br />
https://laravel.com/docs/5.5/session<br />
<br />
=== Arxius: filesystem vs BLOBs en BD ===<br />
Les imatges es poden guardar al sistema d'arxius o bé a la base de dades.<br />
* '''Filesystem''': En el propi tutorial hi ha una explicació de [https://ajgallego.gitbooks.io/laravel-5/content/capitulo_4_datos_de_entrada.html com guardar binaris amb el mètode clàssic del filesystem]<br />
* '''BLOBs en la BD''': Laravel ens permet crear models amb BLOBs i insertar les dades a la BD:<br />
** [https://www.daniweb.com/programming/web-development/threads/480731/how-to-inserting-files-on-mysql-using-laravel Insertant BLOBs amb Larvel]<br />
** Tingueu en compte, si ho feu així, de [https://stackoverflow.com/questions/8499633/how-to-display-base64-images-in-html com renderitzar continguts base64 (BLOBs) sobre un HTML]<br />
<br />
=== A solucionar ===<br />
Alguns temes a solucionar:<br />
* Quan utilitzem el scaffold d'autenticació, falla el logout. Això es deu a un canvi del mètode de GET a POST per motius de seguretat (amb POST, només podran fer logout des de la pròpia app Laravel ja que porta el csrf_token).<br />
*: https://laracasts.com/discuss/channels/laravel/laravel-53-logout-methodnotallowed<br />
<br />
<br><br />
<br />
=== Atacant 2 bases de dades simultàniament ===<br />
En alguns casos podem necessitar configurar 2 instàncies de bases de dades separades per optimitzar el rendiment. Aquest post ho explica molt bé:<br />
https://fideloper.com/laravel-multiple-database-connections<br />
<br />
Caldrà configurar el .env , config/database.php i especificar quina DB ataca en les migracions i en els models que creem.<br />
<br />
<br><br />
<br />
== Laravel i LDAP ==<br />
Aquest mòdul està pensat per a Active Directory, però [https://github.com/Adldap2/Adldap2-Laravel/issues/106 també funciona amb OpenLDAP si s'ajusta bé]:<br />
https://github.com/Adldap2/Adldap2-Laravel<br />
<br />
Primer cal configurar un servidor [[LDAP]].<br />
<br />
Després, tingues en compte que cal ajustar els següents paràmetres en el .env:<br />
ADLDAP_CONTROLLERS=localhost<br />
#ADLDAP_PORT=389<br />
ADLDAP_ADMIN_USERNAME="cn=admin,dc=cacauet,dc=org"<br />
ADLDAP_ADMIN_PASSWORD="enric123"<br />
ADLDAP_BASEDN="dc=cacauet,dc=org"<br />
<br />
Podem fer una autenticació seguint algun d'aquests exemples.<br />
<br />
Exemple 1: cercar un element del directori<br />
<syntaxhighlight lang="php"><br />
$user = Adldap::search()->where("mail","=","pepe@jolgorio.tk")->get();<br />
</syntaxhighlight><br />
<br />
Exemple 2: autenticar un usuari<br />
<syntaxhighlight lang="php"><br />
if( Adldap::auth()->attempt("cn=pepe,ou=usuaris,dc=cacauet,dc=org","pepe123")) {<br />
// autenticació exitosa<br />
return "Pepe OK!";<br />
}<br />
</syntaxhighlight><br />
<br />
<br><br />
<br />
== Laravel en producció ==<br />
Per posar en producció un projecte basat en Laravel cal tenir en compte:<br />
* '''IMPORTANT, SEGURETAT: Només cal publicar la carpeta <code>/public</code>''' . 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 .<br />
** Aquesta carpeta <code>/public</code> no figura inicialment quan creem o clonem un projecte (està a .gitignore), a l'igual que la carpeta <code>/vendor</code>, que es generen quan fem un <code>$ composer install</code>.<br />
** Reviseu la secció [[Laravel#Treballant_amb_GIT_i_clonant]] per fer el setup del projecte després de clonar.<br />
* '''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'').<br />
* 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:<br />
** db.sqlite (si s'escau)<br />
** carpeta <code>/storage</code><br />
** carpeta <code>/bootstrap/cache</code><br />
<br />
=== Desplegament en AWS amb Ubuntu i Apache ===<br />
Guia pel desplegament en Ubuntu amb Apache:<br />
* Accedir al nostre servidor via SSH<br />
* 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<pre>/var/www</pre><br />
* Per veure detalls reviseu la secció [[Laravel#Treballant_amb_GIT_i_clonant]]. Recordeu que això implica: <br />
*# composer install<br />
*# configurar arxiu .env<br />
*# generar clau<br />
* Es requereix el mòdul ''mod_rewrite'' d'Apache (o Nginx)<pre>$ sudo a2enmod rewrite</pre><br />
* Publicar la carpeta <code>/public</code> del projecte Laravel, d'alguna d'aquestes maneres:<br />
** Crear un VirtualHost i apuntar la ServerRoot del domini o subdomini a /var/www/<projecte>/public<br />
** Crear un link simbòlic de la carpeta pública d'Apache a la carpeta public del Laravel amb la comanda <pre>$ ln -s /var/www/<projecte>/public /var/www/html/lara1</pre><br />
* 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".<br />
* Ajusta els permisos de:<br />
** db.sqlite (si s'escau) i també de la carpeta que el conté (si no, no es podrà escriure-hi)<br />
** carpeta <code>/storage</code><br />
** carpeta <code>/bootstrap/cache</code><br />
* Cal activar els arxius <code>.htaccess</code> , afegint la directiva <code>AllowOverride all</code><br />
<br />
A l'arxiu de conf. del nostre VirtualHost (a <code>/etc/apache2/sites-available</code>):<br />
<Directory /var/www/><br />
AllowOverride All<br />
</Directory><br />
<br />
<br />
És important remarcar que per SEGURETAT no hem de mostrar mai els arxius interns de Laravel, només cal publicar el contingut de /public<br />
<br />
<br><br />
<br />
=== Heroku ===<br />
Abans de procedir amb aquesta part hauries de llegir i treballar aquesta altra: [[Heroku]] on treballem amb PHP simple.<br />
<br />
Pots posar en marxa un projecte Laravel a Heroku fàcilment seguint aquesta documentació. Segueix el tutorial per iniciar la app:<br />
https://devcenter.heroku.com/articles/getting-started-with-laravel<br />
<br />
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.<br />
<br />
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.<br />
<br />
En canvi, [https://devcenter.heroku.com/articles/heroku-postgresql el add-on de POSTGRESQL és gratuït i sense targeta de crèdit! :)] Som-hi, doncs!<br />
<br />
Primer de tot, creeu el projecte Laravel i inicialitzeu GIT en cas que no el tingueu penjat a Github o similars:<br />
$ git init<br />
<br />
Tb caldrà afegir un Procfile adequat per Laravel:<br />
$ echo "web: vendor/bin/heroku-php-apache2 public/" > Procfile<br />
<br />
Inicialitzem projecte Heroku:<br />
$ heroku create elmeuprojectedeguais<br />
<br />
Afegim els arxius al repo local:<br />
$ git add .<br />
$ git commit -am "primer commit"<br />
<br />
Afegim la BD PostgreSQL:<br />
$ heroku addons:create heroku-postgresql:hobby-dev<br />
<br />
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:<br />
$ heroku config -s | grep -i post<br />
<br />
Ens ho dona en la següent forma (exemple a continuació):<br />
DATABASE_URL='postgres://<usuari>:<password>@<maquina>:<port>/<bbdd>'<br />
DATABASE_URL='postgres://mxlsfebqyopadb:3e5af56b52cc06574645123ea9d9f7504564e207804dcc71a2db2848446ba064@ec2-156-73-167-43.compute-1.amazonaws.com:5432/d353ihheo564q7'<br />
<br />
Així, doncs, només caldrà ajustar les següents variables d'entorn que necessita el Laravel perquè això funcioni:<br />
DB_CONNECTION=pgsql<br />
DB_HOST=ec2-156...<br />
DB_PORT=5432<br />
DB_DATABASE=d353...<br />
DB_USERNAME=mxls...<br />
DB_PASSWORD=3e5a...<br />
<br />
Per fer-ho cal anar executant les següents ordres:<br />
$ heroku config:set DB_CONNECTION=pgsql<br />
$ ...etc...<br />
<br />
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:<br />
$ cp .env.example .env<br />
$ php artisan key:generate<br />
$ heroku config:set APP_KEY=base64:tX2ikx...<br />
<br />
En acabat, podem posar la app en producció:<br />
$ git add .<br />
$ git push heroku master<br />
<br />
I un cop acabats, migrem la nostra base de dades:<br />
$ heroku run php artisan migrate<br />
<br />
I veure la nostra flamant web en producció (a elmeuprojectedeguais.herokuapp.com):<br />
$ heroku open<br />
<br />
...et voilà!</div>Enrichttps://cacauet.org/wiki/index.php?title=Laravel&diff=4221Laravel2021-02-01T17:43:02Z<p>Enric: /* Heroku */</p>
<hr />
<div><nowiki>#FpInfor #DawMp07 #DawMp07Uf2 #DawMp07Uf02 #DawMpDual</nowiki><br />
<br />
<br />
== Intro i referències ==<br />
Laravel és un framework web per a PHP que està agafant molta força.<br />
<br />
Documentació oficial: https://laravel.com/docs/<br />
<br />
Tutorials:<br />
* [https://ajgallego.gitbooks.io/laravel-5/content/index.html Principal tutorial per seguir el curs]: <pre>https://ajgallego.gitbooks.io/laravel-5/content/index.html</pre><br />
* Forms: https://selftaughtcoders.com/from-idea-to-launch/lesson-23/laravel-5-application-form-model-binding-laravelcollective-forms-html-library-bootstrap-framework/<br />
* Forms i validació: https://scotch.io/tutorials/simple-laravel-crud-with-resource-controllers<br />
* Apunts del Sergi Coll: https://seicoll.github.io/DAW-M07-UF2-Apunts/<br />
* https://styde.net/laravel-5/<br />
* Per passar del schema SQL (per ex. de MySQL Workbench) a Laravel migration: https://adolfocuadros.com/sql_to_laravel/<br />
<br />
<br />
Plugins:<br />
* CORS (Cross-Origin Resource Sharing): https://github.com/barryvdh/laravel-cors<br />
* CRUD & admin : Hi ha molts plugins per crear ''admin panels'' automàticament. Alguns son:<br />
** Voyager: https://voyager.devdojo.com/<br />
** Craftable: https://www.getcraftable.com/<br />
* https://iamacoder.com/post/5-must-have-laravel-5-packages/<br />
<br />
Temes a ampliar:<br />
* Forms: https://laravel.com/docs/4.2/html<br />
* Validació de forms: https://laravel.com/docs/5.5/validation<br />
* Autenticació: https://laravel.com/docs/5.5/authentication<br />
<br />
<br><br />
<br />
== Instal·lació i setup ==<br />
<br />
Prerequisits:<br />
* Laravel i PHP, és molt important tenir en compte les versions:<br />
** <strike>Laravel 5.3 : PHP >= 5.6.4<br />
** Laravel 5.5 : PHP == 7.0<br />
** Laravel 5.6 : PHP >= 7.1<br />
** Laravel 5.7 : PHP >= 7.1.3</strike><br />
** Laravel 6.x : PHP >= 7.2<br />
* Si utilitzes Ubuntu 14 o menor [https://www.digitalocean.com/community/tutorials/how-to-upgrade-to-php-7-on-ubuntu-14-04 actualitza la teva versió de PHP a la 7.0]<br />
* Calen els paquets següents: <pre>$ sudo apt-get install php-mbstring php-zip php-xml php-mysql</pre><br />
<br />
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...:<br />
# Instal·la el gestor de paquets per PHP Composer<br />
#* El més fàcil és fer: (però no ho farem pq volem la darrera versió)<pre>$ sudo apt install composer</pre><br />
#* Prova primer la instal·lació genèrica : [https://getcomposer.org/download/ Instal.la PHP Composer]<br />
#* També tens aquesta altra forma d' [https://getcomposer.org/doc/00-intro.md#installation-linux-unix-osx instal·lar Composer per GNU/Linux]. Descarrega composer-setup.php i instal·la'l així:<pre>$ php composer-setup.php --install-dir=~/bin --filename=composer</pre><br />
# Instal·la la darrera versió de Laravel<br />
#* https://laravel.com/docs/5.7/installation<br />
#* Bàsicament el què cal fer és aquesta comanda per instal·lar el binari ''laravel'':<pre>$ composer global require laravel/installer</pre><br />
#* Laravel s'instal·la a <code>$HOME/.config/composer</code> però per poder executar les properes comandes necessitarem tenir <code>$HOME/.config/composer/vendor/bin</code> al nostre $PATH. Inserta això al teu <code>$HOME/.profile</code>: <pre>PATH=$PATH:~/.config/composer/vendor/bin</pre><br />
#*: Fes logout/login del sistema per activar aquests canvis<br />
# Crea una app Laravel allà on et faci més ràbia: <pre>$ laravel new laravelapp1</pre><br />
#: o també: <pre>$ composer create-project --prefer-dist laravel/laravel laravelapp1</pre><br />
#: o si volem una versió específica de laravel: <pre>$ composer create-project --prefer-dist laravel/laravel=5.8.* laravelapp1</pre><br />
# Arrenca l'aplicació de prova: <pre>$ php artisan serve</pre><br />
# Comprova la app amb el navegador a<pre>http://localhost:8000</pre><br />
<br />
<br><br />
<br />
Si ja has completat la instal·lació, pots procedir a crear un altre projecte nou i realitzar el següent tutorial "tasklist":<br />
https://laravel.com/docs/5.2/quickstart<br />
<br />
<br><br />
<br />
== Incidències vàries ==<br />
Aquest és un bon tutorial:<br />
https://ajgallego.gitbooks.io/laravel-5/content/index.html<br />
<br />
Igualment, podríem trobar algunes incidències. Us dono pistes:<br />
<br />
=== Treballant amb GIT i clonant ===<br />
Al pujar el projecte a un repo GIT, i clonar-lo després caldrà:<br />
# Re-instal·lar les dependències:<pre>$ composer install</pre><br />
# Regenerar arxiu <code>.env</code> : com que depèn de cada entorn no es fica al projecte (es posa a <code>.gitignore</code>), però pots copiar i modificar de <code>.env.example</code><br />
# Error ''The only supported ciphers are AES-128-CBC and AES-256-CBC with the correct key lengths.'' Es soluciona amb :<pre>$ php artisan key:generate</pre><br />
<br />
=== Creant controllers amb CRUD complert ===<br />
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.<br />
# Ja no es pot fer amb <strike><code>Route::controller</code></strike> sinó amb:<pre>Route::resource("cosa","CosaController");</pre><br />
# Per exemple, per crear un controller per al model "Cosa" ho faríem amb -r (de resource): <pre>$ php artisan make:controller -r CosaController</pre><br />
<br />
=== Treballant amb SQLite ===<br />
Per configurar la BD amb SQLite cal crear el fitxer abans amb:<br />
$ touch db.sqlite<br />
<br />
Configurar la BD a .env:<br />
DB_CONNECTION=sqlite<br />
DB_DATABASE=/path/absolut/al/db.sqlite<br />
<br />
Instal·lar els binaris necessaris de SQLite i de PHP:<br />
$ sudo apt-get install sqlite php-sqlite3<br />
<br />
I crear la BD inicial amb:<br />
$ php artisan migrate<br />
<br />
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.<br />
<br />
=== Eliminant models o migracions ===<br />
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:<br />
$ composer dump-autoload<br />
...i es tornaran a generar els arxius d'autoload sense els arxius que volíem esborrar.<br />
<br />
=== Treballant amb proxies i composer ===<br />
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):<br />
$ composer update<br />
Loading composer repositories with package information<br />
Updating dependencies (including require-dev)<br />
(...demana user/password de packagist.org ...)<br />
<br />
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:<br />
$ ssh -L 3128:localhost:3128 jo@elmeuserver.com<br />
I un cop logats, aprofitem per instal·lar el squid:<br />
$ sudo apt install squid<br />
Hem de mantenir la shell oberta mentre vulguem que estigui activat el túnel (l'hem assignat a localhost:3128).<br />
<br />
Obrim una altra shell i anem al nostre projecte Laravel:<br />
$ export http_proxy=localhost:3128<br />
$ composer update<br />
<br />
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).<br />
<br />
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:<br />
$ ssh jo@elmeuserver.com<br />
$ sudo apt remove squid<br />
<br />
<br><br />
<br />
== Tutorials ==<br />
Després d'elaborar la documentació he trobat aquest tutorial bastant útil (només fins la v5.2):<br />
https://laravel.com/docs/5.2/quickstart<br />
<br />
Tutorial per a CRUD complert:<br />
https://www.itsolutionstuff.com/post/laravel-6-crud-application-tutorialexample.html<br />
<br />
== Resum per a fer un CRUD ==<br />
<br />
=== Setup projecte ===<br />
Crear projecte:<br />
$ laravel new proj1<br />
Crear DB (en aquest cas SQLite:<br />
$ touch db.sqlite<br />
Modifica .env per configurar la DB com sqlite:<br />
DB_CONNECTION=sqlite<br />
DB_DATABASE=/path/absolut/al/db.sqlite<br />
<br />
=== Model ===<br />
Crear taules i migracions:<br />
$ php artisan make:migration crea_taula_items --create=items<br />
Editar la migració per crear les taules adequades. Mira't les principals referències:<br />
* [https://laravel.com/docs/5.5/migrations#columns Tipus de columnes]<br />
* [https://laravel.com/docs/5.5/migrations#foreign-key-constraints Relacions i FKs]<br />
Realitzar la migració:<br />
$ php artisan migrate<br />
Crear models:<br />
$ php artisan make:model Item<br />
Ajusta el model perquè apunti al nom correcte de la taula:<br />
https://laravel.com/docs/5.5/eloquent#eloquent-model-conventions<br />
<br />
=== Controller i rutes ===<br />
Crear controllers amb els mètodes estàndard (index, create-store, show, edit-update, destroy):<br />
$ php artisan make:controller -r ItemController<br />
Crear rutes a <code>routes/web.php</code>:<br />
Route::resource("item","ItemController");<br />
Crear plantilles per als mètodes (l'exemple diu "tema" enlloc de "item"):<br />
$ php artisan route:list<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
| Domain | Method | URI | Name | Action | Middleware |<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
| | GET|HEAD | / | | Closure | web |<br />
| | GET|HEAD | api/user | | Closure | api,auth:api |<br />
| | GET|HEAD | tema | tema.index | App\Http\Controllers\TemaController@index | web |<br />
| | POST | tema | tema.store | App\Http\Controllers\TemaController@store | web |<br />
| | GET|HEAD | tema/create | tema.create | App\Http\Controllers\TemaController@create | web |<br />
| | GET|HEAD | tema/{tema} | tema.show | App\Http\Controllers\TemaController@show | web |<br />
| | PUT|PATCH | tema/{tema} | tema.update | App\Http\Controllers\TemaController@update | web |<br />
| | DELETE | tema/{tema} | tema.destroy | App\Http\Controllers\TemaController@destroy | web |<br />
| | GET|HEAD | tema/{tema}/edit | tema.edit | App\Http\Controllers\TemaController@edit | web |<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
<br />
Crear les views (plantilles blade) adequades per a tots els mètodes necessaris (els arxius van a <code>resources/views</code>). Pots veure [https://github.com/emieza/laravel-karaoke/tree/master/resources/views/llista aqui] alguns exemples.<br />
* '''index''' : llista tots els elements<br />
* '''show''' : mostra un element en concret, necessita que li passem un paràmetre per GET (id del element a mostrar)<br />
* '''create-store''' : "create és el form (no necessita codi), i "store" és el codi per insertar-ho a la BD (no necessita una plantilla)<br />
* '''edit-update''' : "edit" és el form, i "update" el codi per actualitzar la BD<br />
* '''destroy''' : elimina un element<br />
<br />
=== Codi del Controller i View ===<br />
* Crear views amb formularis d'entrada de dades: [https://github.com/emieza/laravel-karaoke/blob/master/resources/views/llista/crea.blade.php create.blade.php d'exemple]<br />
* Editar el codi del Controller per cridar pertinentment a les views: [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/LlistaController.php Controller d'exemple]<br />
<br />
=== Més docs ===<br />
Una bona referència de la doc oficial per fer un CRUD és aquesta:<br />
https://laravel.com/docs/5.2/quickstart<br />
En particular per veure com utilitzar les templates oficials amb bootstrap ;)<br />
<br />
<br><br />
<br />
== Projecte d'exemple ==<br />
Aquest és el projecte que he realitzat per entrenar-me, et pot servir d'exemple. El pots veure en producció aquí: https://jolgorio.tk<br />
https://github.com/emieza/laravel-karaoke<br />
<br />
Fes-li un cop d'ull al readme.md per veure com posar-lo en marxa.<br />
<br />
MOLT IMPORTANT PEL PROJECTE: Cal crear un README.md (com [https://github.com/emieza/laravel-karaoke/blob/master/readme.md per exemple aquest]). No acceptaré cap projecte sense README.md<br />
<br />
Per entrenar-vos amb el Markdown teniu aquest tester:<br />
http://dillinger.io/<br />
<br />
Anem per feina:<br />
# Taules: llistes, temes, vots<br />
# Rutes que vols implementar per al projecte. [https://github.com/emieza/laravel-karaoke/blob/master/routes/web.php En el meu cas, tinc]:<br />
#* /llista/crea (GET per formulari + POST per store)<br />
#* /llista (index de llistes)<br />
#* /llista/{id} (show)<br />
#* /llista/{id}/crea (GET + POST, per crear temes en les llistes)<br />
#* /vota/{idtema}<br />
# Codi:<br />
#* als Controllers pertinents. Mira't l'[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/LlistaController.php exemple de les llistes de karaoke].<br />
#* Plantilles: a resources/views/xxxx.blade.php . Mira't l'[https://github.com/emieza/laravel-karaoke/tree/master/resources/views/llista exemple un altre cop].<br />
<br />
<br><br />
<br />
== ORM : Models i relacions ==<br />
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.<br />
<br />
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. <br />
<br />
El què anem a explicar està documentat a l'apartat "Eloquent ORM" de Laravel:<br />
https://laravel.com/docs/5.7/eloquent-relationships<br />
https://laravel.com/docs/6.x/eloquent-relationships<br />
<br />
=== Accedint relacions 1-N de forma directa ===<br />
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í.<br />
<br />
L'objectiu serà poder accedir a l'objecte pare d'aquesta manera per mostrar el text del Post (pare).<br />
<syntaxhighlight lang="php"><br />
$comment = Comment::find(33);<br />
echo $comment->post->text;<br />
</syntaxhighlight><br />
<br />
Per aconseguir això, cal que indiquem la relació existent a les taules entre els models Post i Comment amb la relació <code>belongsTo</code>:<br />
<br />
<syntaxhighlight lang="php"><br />
<?php<br />
namespace App;<br />
use Illuminate\Database\Eloquent\Model;<br />
class Comment extends Model<br />
{<br />
/**<br />
* Accedeix al pare (Post)<br />
*/<br />
public function post()<br />
{<br />
return $this->belongsTo('App\Post','post_id');<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Accedint relacions 1-N de forma inversa ===<br />
El següent cas típic serà accedir des d'un objecte Post als diferents Comentaris, més o menys així:<br />
<br />
<syntaxhighlight lang="php"><br />
$comments = App\Post::find(1)->comments;<br />
foreach ($comments as $comment) {<br />
// ... el teu codi...<br />
echo $comment->text;<br />
}<br />
</syntaxhighlight><br />
El codi que veiem és per a un ''controller'', però es pot aplicar també als ''templates'', amb @foreach i similars.<br />
<br />
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<br />
<syntaxhighlight lang="php"><br />
<?php<br />
namespace App;<br />
use Illuminate\Database\Eloquent\Model;<br />
class Post extends Model<br />
{<br />
/**<br />
* Accedeix als comentaris relacionats amb el Post actual<br />
*/<br />
public function comments()<br />
{<br />
return $this->hasMany('App\Comment','<ref_remota>','<ref_local>');<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
On:<br />
* <ref_remota> és el camp de la taula de Comment que referencia el Post<br />
* <ref_local> és el camp de Post que fa de PK i on Comment apunta<br />
<br />
Per accedir al objecte relacionat "pare" caldrà fer una altra funció, en concret ''belongsTo''. Consulta la doc de les relacions 1-a-N (inversa).<br />
<br />
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:<br />
https://laravel.com/docs/5.5/eloquent-relationships#one-to-many<br />
<br />
=== Aniuant JSON en la API ===<br />
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:<br />
<br />
<syntaxhighlight lang="php"><br />
<?php<br />
Route::get("/comentaris", function() {<br />
$post = Post::with("comments")->get();<br />
return $post;<br />
});<br />
</syntaxhighlight><br />
<br />
...i ens retornarà les dades aniuades que volem! :)<br />
<br />
<br><br />
<br />
== Més coses ==<br />
Alguns temes que no hem aprofundit però que convé conèixer.<br />
<br />
=== Autenticació ===<br />
Senzill d'implementar i imprescindible. Laravel incorpora un ''scaffold'' per facilitar una funció tan estàndard.<br />
Amb una sola instrucció ens crea les rutes, vistes i els controllers típics (login, logout).<br />
<br />
[https://laravel.com/docs/5.5/authentication Autenticació en Laravel 5.x]:<br />
$ php artisan make:auth<br />
<br />
[https://laravel.com/docs/6.x/authentication Autenticació en Laravel 6.x]:<br />
$ composer require laravel/ui --dev<br />
$ php artisan ui vue --auth<br />
<br />
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:<br />
$ npm install && npm run dev<br />
<br />
També hi ha [https://laracasts.com/discuss/channels/laravel/laravel-60-appcss?page=1 solucions al problema carregant els CSS i JS del CDN] (només cal canviar un link en el ''head'' de <code>app.blade.php</code>.<br />
<br />
=== Seeding ===<br />
Una part molt important és la de crear dades per farcir la base de dades inicialment i poder així testejar amb comoditat.<br />
<br />
https://laravel.com/docs/6.x/seeding<br />
<br />
En algun moment donat convé utilitzar un ''factory'' que ens permet crear elements en massa:<br />
<br />
https://laravel.com/docs/6.x/database-testing#writing-factories<br />
<br />
El ''factory'' sol utilitzar una llibreria <code>Faker</code> que ens va molt bé per crear noms i cognoms aleatoris, lorem ipsum, etc. que ens facilitarà la creació de dades de prova.<br />
<br />
https://github.com/fzaninotto/Faker<br />
<br />
=== Validacions ===<br />
Laravel ens ofereix un mecanisme de validació de formularis molt potent i efectiu.<br />
<br />
https://laravel.com/docs/5.5/validation<br />
<br />
=== Sessions ===<br />
D'entrada és molt útil per emetre missatges "flash", i informar l'usuari del processament intern.<br />
<br />
https://laravel.com/docs/5.5/session<br />
<br />
=== Arxius: filesystem vs BLOBs en BD ===<br />
Les imatges es poden guardar al sistema d'arxius o bé a la base de dades.<br />
* '''Filesystem''': En el propi tutorial hi ha una explicació de [https://ajgallego.gitbooks.io/laravel-5/content/capitulo_4_datos_de_entrada.html com guardar binaris amb el mètode clàssic del filesystem]<br />
* '''BLOBs en la BD''': Laravel ens permet crear models amb BLOBs i insertar les dades a la BD:<br />
** [https://www.daniweb.com/programming/web-development/threads/480731/how-to-inserting-files-on-mysql-using-laravel Insertant BLOBs amb Larvel]<br />
** Tingueu en compte, si ho feu així, de [https://stackoverflow.com/questions/8499633/how-to-display-base64-images-in-html com renderitzar continguts base64 (BLOBs) sobre un HTML]<br />
<br />
=== A solucionar ===<br />
Alguns temes a solucionar:<br />
* Quan utilitzem el scaffold d'autenticació, falla el logout. Això es deu a un canvi del mètode de GET a POST per motius de seguretat (amb POST, només podran fer logout des de la pròpia app Laravel ja que porta el csrf_token).<br />
*: https://laracasts.com/discuss/channels/laravel/laravel-53-logout-methodnotallowed<br />
<br />
<br><br />
<br />
=== Atacant 2 bases de dades simultàniament ===<br />
En alguns casos podem necessitar configurar 2 instàncies de bases de dades separades per optimitzar el rendiment. Aquest post ho explica molt bé:<br />
https://fideloper.com/laravel-multiple-database-connections<br />
<br />
Caldrà configurar el .env , config/database.php i especificar quina DB ataca en les migracions i en els models que creem.<br />
<br />
<br><br />
<br />
== Laravel i LDAP ==<br />
Aquest mòdul està pensat per a Active Directory, però [https://github.com/Adldap2/Adldap2-Laravel/issues/106 també funciona amb OpenLDAP si s'ajusta bé]:<br />
https://github.com/Adldap2/Adldap2-Laravel<br />
<br />
Primer cal configurar un servidor [[LDAP]].<br />
<br />
Després, tingues en compte que cal ajustar els següents paràmetres en el .env:<br />
ADLDAP_CONTROLLERS=localhost<br />
#ADLDAP_PORT=389<br />
ADLDAP_ADMIN_USERNAME="cn=admin,dc=cacauet,dc=org"<br />
ADLDAP_ADMIN_PASSWORD="enric123"<br />
ADLDAP_BASEDN="dc=cacauet,dc=org"<br />
<br />
Podem fer una autenticació seguint algun d'aquests exemples.<br />
<br />
Exemple 1: cercar un element del directori<br />
<syntaxhighlight lang="php"><br />
$user = Adldap::search()->where("mail","=","pepe@jolgorio.tk")->get();<br />
</syntaxhighlight><br />
<br />
Exemple 2: autenticar un usuari<br />
<syntaxhighlight lang="php"><br />
if( Adldap::auth()->attempt("cn=pepe,ou=usuaris,dc=cacauet,dc=org","pepe123")) {<br />
// autenticació exitosa<br />
return "Pepe OK!";<br />
}<br />
</syntaxhighlight><br />
<br />
<br><br />
<br />
== Laravel en producció ==<br />
Per posar en producció un projecte basat en Laravel cal tenir en compte:<br />
* '''IMPORTANT, SEGURETAT: Només cal publicar la carpeta <code>/public</code>''' . 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 .<br />
** Aquesta carpeta <code>/public</code> no figura inicialment quan creem o clonem un projecte (està a .gitignore), a l'igual que la carpeta <code>/vendor</code>, que es generen quan fem un <code>$ composer install</code>.<br />
** Reviseu la secció [[Laravel#Treballant_amb_GIT_i_clonant]] per fer el setup del projecte després de clonar.<br />
* '''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'').<br />
* 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:<br />
** db.sqlite (si s'escau)<br />
** carpeta <code>/storage</code><br />
** carpeta <code>/bootstrap/cache</code><br />
<br />
=== Desplegament en AWS amb Ubuntu i Apache ===<br />
Guia pel desplegament en Ubuntu amb Apache:<br />
* Accedir al nostre servidor via SSH<br />
* 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<pre>/var/www</pre><br />
* Per veure detalls reviseu la secció [[Laravel#Treballant_amb_GIT_i_clonant]]. Recordeu que això implica: <br />
*# composer install<br />
*# configurar arxiu .env<br />
*# generar clau<br />
* Es requereix el mòdul ''mod_rewrite'' d'Apache (o Nginx)<pre>$ sudo a2enmod rewrite</pre><br />
* Publicar la carpeta <code>/public</code> del projecte Laravel, d'alguna d'aquestes maneres:<br />
** Crear un VirtualHost i apuntar la ServerRoot del domini o subdomini a /var/www/<projecte>/public<br />
** Crear un link simbòlic de la carpeta pública d'Apache a la carpeta public del Laravel amb la comanda <pre>$ ln -s /var/www/<projecte>/public /var/www/html/lara1</pre><br />
* 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".<br />
* Ajusta els permisos de:<br />
** db.sqlite (si s'escau) i també de la carpeta que el conté (si no, no es podrà escriure-hi)<br />
** carpeta <code>/storage</code><br />
** carpeta <code>/bootstrap/cache</code><br />
* Cal activar els arxius <code>.htaccess</code> , afegint la directiva <code>AllowOverride all</code><br />
<br />
A l'arxiu de conf. del nostre VirtualHost (a <code>/etc/apache2/sites-available</code>):<br />
<Directory /var/www/><br />
AllowOverride All<br />
</Directory><br />
<br />
<br />
És important remarcar que per SEGURETAT no hem de mostrar mai els arxius interns de Laravel, només cal publicar el contingut de /public<br />
<br />
<br><br />
<br />
=== Heroku ===<br />
Abans de procedir amb aquesta part hauries de llegir i treballar aquesta altra: [[Heroku]] on treballem amb PHP simple.<br />
<br />
Pots posar en marxa un projecte Laravel a Heroku fàcilment seguint aquesta documentació. Segueix el tutorial per iniciar la app:<br />
https://devcenter.heroku.com/articles/getting-started-with-laravel<br />
<br />
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.<br />
<br />
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.<br />
<br />
En canvi, [https://devcenter.heroku.com/articles/heroku-postgresql el add-on de POSTGRESQL és gratuït i sense targeta de crèdit! :)] Som-hi, doncs!<br />
<br />
Primer de tot, creeu el projecte Laravel i inicialitzeu GIT en cas que no el tingueu penjat a Github o similars:<br />
$ git init<br />
<br />
Tb caldrà afegir un Procfile adequat per Laravel:<br />
$ echo "web: vendor/bin/heroku-php-apache2 public/" > Procfile<br />
<br />
Inicialitzem projecte Heroku:<br />
$ heroku create elmeuprojectedeguais<br />
<br />
Afegim la BD PostgreSQL:<br />
$ heroku addons:create heroku-postgresql:hobby-dev<br />
<br />
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:<br />
$ heroku config -s | grep -i post<br />
<br />
Ens ho dona en la següent forma (exemple a continuació):<br />
DATABASE_URL='postgres://<usuari>:<password>@<maquina>:<port>/<bbdd>'<br />
DATABASE_URL='postgres://mxlsfebqyopadb:3e5af56b52cc06574645123ea9d9f7504564e207804dcc71a2db2848446ba064@ec2-156-73-167-43.compute-1.amazonaws.com:5432/d353ihheo564q7'<br />
<br />
Així, doncs, només caldrà ajustar les següents variables d'entorn que necessita el Laravel perquè això funcioni:<br />
DB_CONNECTION=pgsql<br />
DB_HOST=ec2-156...<br />
DB_PORT=5432<br />
DB_DATABASE=d353...<br />
DB_USERNAME=mxls...<br />
DB_PASSWORD=3e5a...<br />
<br />
Per fer-ho cal anar executant les següents ordres:<br />
$ heroku config:set DB_CONNECTION=pgsql<br />
$ ...etc...<br />
<br />
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:<br />
$ cp .env.example .env<br />
$ php artisan key:generate<br />
$ heroku config:set APP_KEY=base64:tX2ikx...<br />
<br />
En acabat, podem posar la app en producció:<br />
$ git add .<br />
$ git push heroku master<br />
<br />
I un cop acabats, migrem la nostra base de dades:<br />
$ heroku run php artisan migrate<br />
<br />
I veure la nostra flamant web en producció (a elmeuprojectedeguais.herokuapp.com):<br />
$ heroku open<br />
<br />
...et voilà!</div>Enrichttps://cacauet.org/wiki/index.php?title=Laravel&diff=4220Laravel2021-01-29T15:15:34Z<p>Enric: /* Heroku */</p>
<hr />
<div><nowiki>#FpInfor #DawMp07 #DawMp07Uf2 #DawMp07Uf02 #DawMpDual</nowiki><br />
<br />
<br />
== Intro i referències ==<br />
Laravel és un framework web per a PHP que està agafant molta força.<br />
<br />
Documentació oficial: https://laravel.com/docs/<br />
<br />
Tutorials:<br />
* [https://ajgallego.gitbooks.io/laravel-5/content/index.html Principal tutorial per seguir el curs]: <pre>https://ajgallego.gitbooks.io/laravel-5/content/index.html</pre><br />
* Forms: https://selftaughtcoders.com/from-idea-to-launch/lesson-23/laravel-5-application-form-model-binding-laravelcollective-forms-html-library-bootstrap-framework/<br />
* Forms i validació: https://scotch.io/tutorials/simple-laravel-crud-with-resource-controllers<br />
* Apunts del Sergi Coll: https://seicoll.github.io/DAW-M07-UF2-Apunts/<br />
* https://styde.net/laravel-5/<br />
* Per passar del schema SQL (per ex. de MySQL Workbench) a Laravel migration: https://adolfocuadros.com/sql_to_laravel/<br />
<br />
<br />
Plugins:<br />
* CORS (Cross-Origin Resource Sharing): https://github.com/barryvdh/laravel-cors<br />
* CRUD & admin : Hi ha molts plugins per crear ''admin panels'' automàticament. Alguns son:<br />
** Voyager: https://voyager.devdojo.com/<br />
** Craftable: https://www.getcraftable.com/<br />
* https://iamacoder.com/post/5-must-have-laravel-5-packages/<br />
<br />
Temes a ampliar:<br />
* Forms: https://laravel.com/docs/4.2/html<br />
* Validació de forms: https://laravel.com/docs/5.5/validation<br />
* Autenticació: https://laravel.com/docs/5.5/authentication<br />
<br />
<br><br />
<br />
== Instal·lació i setup ==<br />
<br />
Prerequisits:<br />
* Laravel i PHP, és molt important tenir en compte les versions:<br />
** <strike>Laravel 5.3 : PHP >= 5.6.4<br />
** Laravel 5.5 : PHP == 7.0<br />
** Laravel 5.6 : PHP >= 7.1<br />
** Laravel 5.7 : PHP >= 7.1.3</strike><br />
** Laravel 6.x : PHP >= 7.2<br />
* Si utilitzes Ubuntu 14 o menor [https://www.digitalocean.com/community/tutorials/how-to-upgrade-to-php-7-on-ubuntu-14-04 actualitza la teva versió de PHP a la 7.0]<br />
* Calen els paquets següents: <pre>$ sudo apt-get install php-mbstring php-zip php-xml php-mysql</pre><br />
<br />
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...:<br />
# Instal·la el gestor de paquets per PHP Composer<br />
#* El més fàcil és fer: (però no ho farem pq volem la darrera versió)<pre>$ sudo apt install composer</pre><br />
#* Prova primer la instal·lació genèrica : [https://getcomposer.org/download/ Instal.la PHP Composer]<br />
#* També tens aquesta altra forma d' [https://getcomposer.org/doc/00-intro.md#installation-linux-unix-osx instal·lar Composer per GNU/Linux]. Descarrega composer-setup.php i instal·la'l així:<pre>$ php composer-setup.php --install-dir=~/bin --filename=composer</pre><br />
# Instal·la la darrera versió de Laravel<br />
#* https://laravel.com/docs/5.7/installation<br />
#* Bàsicament el què cal fer és aquesta comanda per instal·lar el binari ''laravel'':<pre>$ composer global require laravel/installer</pre><br />
#* Laravel s'instal·la a <code>$HOME/.config/composer</code> però per poder executar les properes comandes necessitarem tenir <code>$HOME/.config/composer/vendor/bin</code> al nostre $PATH. Inserta això al teu <code>$HOME/.profile</code>: <pre>PATH=$PATH:~/.config/composer/vendor/bin</pre><br />
#*: Fes logout/login del sistema per activar aquests canvis<br />
# Crea una app Laravel allà on et faci més ràbia: <pre>$ laravel new laravelapp1</pre><br />
#: o també: <pre>$ composer create-project --prefer-dist laravel/laravel laravelapp1</pre><br />
#: o si volem una versió específica de laravel: <pre>$ composer create-project --prefer-dist laravel/laravel=5.8.* laravelapp1</pre><br />
# Arrenca l'aplicació de prova: <pre>$ php artisan serve</pre><br />
# Comprova la app amb el navegador a<pre>http://localhost:8000</pre><br />
<br />
<br><br />
<br />
Si ja has completat la instal·lació, pots procedir a crear un altre projecte nou i realitzar el següent tutorial "tasklist":<br />
https://laravel.com/docs/5.2/quickstart<br />
<br />
<br><br />
<br />
== Incidències vàries ==<br />
Aquest és un bon tutorial:<br />
https://ajgallego.gitbooks.io/laravel-5/content/index.html<br />
<br />
Igualment, podríem trobar algunes incidències. Us dono pistes:<br />
<br />
=== Treballant amb GIT i clonant ===<br />
Al pujar el projecte a un repo GIT, i clonar-lo després caldrà:<br />
# Re-instal·lar les dependències:<pre>$ composer install</pre><br />
# Regenerar arxiu <code>.env</code> : com que depèn de cada entorn no es fica al projecte (es posa a <code>.gitignore</code>), però pots copiar i modificar de <code>.env.example</code><br />
# Error ''The only supported ciphers are AES-128-CBC and AES-256-CBC with the correct key lengths.'' Es soluciona amb :<pre>$ php artisan key:generate</pre><br />
<br />
=== Creant controllers amb CRUD complert ===<br />
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.<br />
# Ja no es pot fer amb <strike><code>Route::controller</code></strike> sinó amb:<pre>Route::resource("cosa","CosaController");</pre><br />
# Per exemple, per crear un controller per al model "Cosa" ho faríem amb -r (de resource): <pre>$ php artisan make:controller -r CosaController</pre><br />
<br />
=== Treballant amb SQLite ===<br />
Per configurar la BD amb SQLite cal crear el fitxer abans amb:<br />
$ touch db.sqlite<br />
<br />
Configurar la BD a .env:<br />
DB_CONNECTION=sqlite<br />
DB_DATABASE=/path/absolut/al/db.sqlite<br />
<br />
Instal·lar els binaris necessaris de SQLite i de PHP:<br />
$ sudo apt-get install sqlite php-sqlite3<br />
<br />
I crear la BD inicial amb:<br />
$ php artisan migrate<br />
<br />
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.<br />
<br />
=== Eliminant models o migracions ===<br />
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:<br />
$ composer dump-autoload<br />
...i es tornaran a generar els arxius d'autoload sense els arxius que volíem esborrar.<br />
<br />
=== Treballant amb proxies i composer ===<br />
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):<br />
$ composer update<br />
Loading composer repositories with package information<br />
Updating dependencies (including require-dev)<br />
(...demana user/password de packagist.org ...)<br />
<br />
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:<br />
$ ssh -L 3128:localhost:3128 jo@elmeuserver.com<br />
I un cop logats, aprofitem per instal·lar el squid:<br />
$ sudo apt install squid<br />
Hem de mantenir la shell oberta mentre vulguem que estigui activat el túnel (l'hem assignat a localhost:3128).<br />
<br />
Obrim una altra shell i anem al nostre projecte Laravel:<br />
$ export http_proxy=localhost:3128<br />
$ composer update<br />
<br />
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).<br />
<br />
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:<br />
$ ssh jo@elmeuserver.com<br />
$ sudo apt remove squid<br />
<br />
<br><br />
<br />
== Tutorials ==<br />
Després d'elaborar la documentació he trobat aquest tutorial bastant útil (només fins la v5.2):<br />
https://laravel.com/docs/5.2/quickstart<br />
<br />
Tutorial per a CRUD complert:<br />
https://www.itsolutionstuff.com/post/laravel-6-crud-application-tutorialexample.html<br />
<br />
== Resum per a fer un CRUD ==<br />
<br />
=== Setup projecte ===<br />
Crear projecte:<br />
$ laravel new proj1<br />
Crear DB (en aquest cas SQLite:<br />
$ touch db.sqlite<br />
Modifica .env per configurar la DB com sqlite:<br />
DB_CONNECTION=sqlite<br />
DB_DATABASE=/path/absolut/al/db.sqlite<br />
<br />
=== Model ===<br />
Crear taules i migracions:<br />
$ php artisan make:migration crea_taula_items --create=items<br />
Editar la migració per crear les taules adequades. Mira't les principals referències:<br />
* [https://laravel.com/docs/5.5/migrations#columns Tipus de columnes]<br />
* [https://laravel.com/docs/5.5/migrations#foreign-key-constraints Relacions i FKs]<br />
Realitzar la migració:<br />
$ php artisan migrate<br />
Crear models:<br />
$ php artisan make:model Item<br />
Ajusta el model perquè apunti al nom correcte de la taula:<br />
https://laravel.com/docs/5.5/eloquent#eloquent-model-conventions<br />
<br />
=== Controller i rutes ===<br />
Crear controllers amb els mètodes estàndard (index, create-store, show, edit-update, destroy):<br />
$ php artisan make:controller -r ItemController<br />
Crear rutes a <code>routes/web.php</code>:<br />
Route::resource("item","ItemController");<br />
Crear plantilles per als mètodes (l'exemple diu "tema" enlloc de "item"):<br />
$ php artisan route:list<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
| Domain | Method | URI | Name | Action | Middleware |<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
| | GET|HEAD | / | | Closure | web |<br />
| | GET|HEAD | api/user | | Closure | api,auth:api |<br />
| | GET|HEAD | tema | tema.index | App\Http\Controllers\TemaController@index | web |<br />
| | POST | tema | tema.store | App\Http\Controllers\TemaController@store | web |<br />
| | GET|HEAD | tema/create | tema.create | App\Http\Controllers\TemaController@create | web |<br />
| | GET|HEAD | tema/{tema} | tema.show | App\Http\Controllers\TemaController@show | web |<br />
| | PUT|PATCH | tema/{tema} | tema.update | App\Http\Controllers\TemaController@update | web |<br />
| | DELETE | tema/{tema} | tema.destroy | App\Http\Controllers\TemaController@destroy | web |<br />
| | GET|HEAD | tema/{tema}/edit | tema.edit | App\Http\Controllers\TemaController@edit | web |<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
<br />
Crear les views (plantilles blade) adequades per a tots els mètodes necessaris (els arxius van a <code>resources/views</code>). Pots veure [https://github.com/emieza/laravel-karaoke/tree/master/resources/views/llista aqui] alguns exemples.<br />
* '''index''' : llista tots els elements<br />
* '''show''' : mostra un element en concret, necessita que li passem un paràmetre per GET (id del element a mostrar)<br />
* '''create-store''' : "create és el form (no necessita codi), i "store" és el codi per insertar-ho a la BD (no necessita una plantilla)<br />
* '''edit-update''' : "edit" és el form, i "update" el codi per actualitzar la BD<br />
* '''destroy''' : elimina un element<br />
<br />
=== Codi del Controller i View ===<br />
* Crear views amb formularis d'entrada de dades: [https://github.com/emieza/laravel-karaoke/blob/master/resources/views/llista/crea.blade.php create.blade.php d'exemple]<br />
* Editar el codi del Controller per cridar pertinentment a les views: [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/LlistaController.php Controller d'exemple]<br />
<br />
=== Més docs ===<br />
Una bona referència de la doc oficial per fer un CRUD és aquesta:<br />
https://laravel.com/docs/5.2/quickstart<br />
En particular per veure com utilitzar les templates oficials amb bootstrap ;)<br />
<br />
<br><br />
<br />
== Projecte d'exemple ==<br />
Aquest és el projecte que he realitzat per entrenar-me, et pot servir d'exemple. El pots veure en producció aquí: https://jolgorio.tk<br />
https://github.com/emieza/laravel-karaoke<br />
<br />
Fes-li un cop d'ull al readme.md per veure com posar-lo en marxa.<br />
<br />
MOLT IMPORTANT PEL PROJECTE: Cal crear un README.md (com [https://github.com/emieza/laravel-karaoke/blob/master/readme.md per exemple aquest]). No acceptaré cap projecte sense README.md<br />
<br />
Per entrenar-vos amb el Markdown teniu aquest tester:<br />
http://dillinger.io/<br />
<br />
Anem per feina:<br />
# Taules: llistes, temes, vots<br />
# Rutes que vols implementar per al projecte. [https://github.com/emieza/laravel-karaoke/blob/master/routes/web.php En el meu cas, tinc]:<br />
#* /llista/crea (GET per formulari + POST per store)<br />
#* /llista (index de llistes)<br />
#* /llista/{id} (show)<br />
#* /llista/{id}/crea (GET + POST, per crear temes en les llistes)<br />
#* /vota/{idtema}<br />
# Codi:<br />
#* als Controllers pertinents. Mira't l'[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/LlistaController.php exemple de les llistes de karaoke].<br />
#* Plantilles: a resources/views/xxxx.blade.php . Mira't l'[https://github.com/emieza/laravel-karaoke/tree/master/resources/views/llista exemple un altre cop].<br />
<br />
<br><br />
<br />
== ORM : Models i relacions ==<br />
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.<br />
<br />
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. <br />
<br />
El què anem a explicar està documentat a l'apartat "Eloquent ORM" de Laravel:<br />
https://laravel.com/docs/5.7/eloquent-relationships<br />
https://laravel.com/docs/6.x/eloquent-relationships<br />
<br />
=== Accedint relacions 1-N de forma directa ===<br />
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í.<br />
<br />
L'objectiu serà poder accedir a l'objecte pare d'aquesta manera per mostrar el text del Post (pare).<br />
<syntaxhighlight lang="php"><br />
$comment = Comment::find(33);<br />
echo $comment->post->text;<br />
</syntaxhighlight><br />
<br />
Per aconseguir això, cal que indiquem la relació existent a les taules entre els models Post i Comment amb la relació <code>belongsTo</code>:<br />
<br />
<syntaxhighlight lang="php"><br />
<?php<br />
namespace App;<br />
use Illuminate\Database\Eloquent\Model;<br />
class Comment extends Model<br />
{<br />
/**<br />
* Accedeix al pare (Post)<br />
*/<br />
public function post()<br />
{<br />
return $this->belongsTo('App\Post','post_id');<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Accedint relacions 1-N de forma inversa ===<br />
El següent cas típic serà accedir des d'un objecte Post als diferents Comentaris, més o menys així:<br />
<br />
<syntaxhighlight lang="php"><br />
$comments = App\Post::find(1)->comments;<br />
foreach ($comments as $comment) {<br />
// ... el teu codi...<br />
echo $comment->text;<br />
}<br />
</syntaxhighlight><br />
El codi que veiem és per a un ''controller'', però es pot aplicar també als ''templates'', amb @foreach i similars.<br />
<br />
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<br />
<syntaxhighlight lang="php"><br />
<?php<br />
namespace App;<br />
use Illuminate\Database\Eloquent\Model;<br />
class Post extends Model<br />
{<br />
/**<br />
* Accedeix als comentaris relacionats amb el Post actual<br />
*/<br />
public function comments()<br />
{<br />
return $this->hasMany('App\Comment','<ref_remota>','<ref_local>');<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
On:<br />
* <ref_remota> és el camp de la taula de Comment que referencia el Post<br />
* <ref_local> és el camp de Post que fa de PK i on Comment apunta<br />
<br />
Per accedir al objecte relacionat "pare" caldrà fer una altra funció, en concret ''belongsTo''. Consulta la doc de les relacions 1-a-N (inversa).<br />
<br />
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:<br />
https://laravel.com/docs/5.5/eloquent-relationships#one-to-many<br />
<br />
=== Aniuant JSON en la API ===<br />
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:<br />
<br />
<syntaxhighlight lang="php"><br />
<?php<br />
Route::get("/comentaris", function() {<br />
$post = Post::with("comments")->get();<br />
return $post;<br />
});<br />
</syntaxhighlight><br />
<br />
...i ens retornarà les dades aniuades que volem! :)<br />
<br />
<br><br />
<br />
== Més coses ==<br />
Alguns temes que no hem aprofundit però que convé conèixer.<br />
<br />
=== Autenticació ===<br />
Senzill d'implementar i imprescindible. Laravel incorpora un ''scaffold'' per facilitar una funció tan estàndard.<br />
Amb una sola instrucció ens crea les rutes, vistes i els controllers típics (login, logout).<br />
<br />
[https://laravel.com/docs/5.5/authentication Autenticació en Laravel 5.x]:<br />
$ php artisan make:auth<br />
<br />
[https://laravel.com/docs/6.x/authentication Autenticació en Laravel 6.x]:<br />
$ composer require laravel/ui --dev<br />
$ php artisan ui vue --auth<br />
<br />
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:<br />
$ npm install && npm run dev<br />
<br />
També hi ha [https://laracasts.com/discuss/channels/laravel/laravel-60-appcss?page=1 solucions al problema carregant els CSS i JS del CDN] (només cal canviar un link en el ''head'' de <code>app.blade.php</code>.<br />
<br />
=== Seeding ===<br />
Una part molt important és la de crear dades per farcir la base de dades inicialment i poder així testejar amb comoditat.<br />
<br />
https://laravel.com/docs/6.x/seeding<br />
<br />
En algun moment donat convé utilitzar un ''factory'' que ens permet crear elements en massa:<br />
<br />
https://laravel.com/docs/6.x/database-testing#writing-factories<br />
<br />
El ''factory'' sol utilitzar una llibreria <code>Faker</code> que ens va molt bé per crear noms i cognoms aleatoris, lorem ipsum, etc. que ens facilitarà la creació de dades de prova.<br />
<br />
https://github.com/fzaninotto/Faker<br />
<br />
=== Validacions ===<br />
Laravel ens ofereix un mecanisme de validació de formularis molt potent i efectiu.<br />
<br />
https://laravel.com/docs/5.5/validation<br />
<br />
=== Sessions ===<br />
D'entrada és molt útil per emetre missatges "flash", i informar l'usuari del processament intern.<br />
<br />
https://laravel.com/docs/5.5/session<br />
<br />
=== Arxius: filesystem vs BLOBs en BD ===<br />
Les imatges es poden guardar al sistema d'arxius o bé a la base de dades.<br />
* '''Filesystem''': En el propi tutorial hi ha una explicació de [https://ajgallego.gitbooks.io/laravel-5/content/capitulo_4_datos_de_entrada.html com guardar binaris amb el mètode clàssic del filesystem]<br />
* '''BLOBs en la BD''': Laravel ens permet crear models amb BLOBs i insertar les dades a la BD:<br />
** [https://www.daniweb.com/programming/web-development/threads/480731/how-to-inserting-files-on-mysql-using-laravel Insertant BLOBs amb Larvel]<br />
** Tingueu en compte, si ho feu així, de [https://stackoverflow.com/questions/8499633/how-to-display-base64-images-in-html com renderitzar continguts base64 (BLOBs) sobre un HTML]<br />
<br />
=== A solucionar ===<br />
Alguns temes a solucionar:<br />
* Quan utilitzem el scaffold d'autenticació, falla el logout. Això es deu a un canvi del mètode de GET a POST per motius de seguretat (amb POST, només podran fer logout des de la pròpia app Laravel ja que porta el csrf_token).<br />
*: https://laracasts.com/discuss/channels/laravel/laravel-53-logout-methodnotallowed<br />
<br />
<br><br />
<br />
=== Atacant 2 bases de dades simultàniament ===<br />
En alguns casos podem necessitar configurar 2 instàncies de bases de dades separades per optimitzar el rendiment. Aquest post ho explica molt bé:<br />
https://fideloper.com/laravel-multiple-database-connections<br />
<br />
Caldrà configurar el .env , config/database.php i especificar quina DB ataca en les migracions i en els models que creem.<br />
<br />
<br><br />
<br />
== Laravel i LDAP ==<br />
Aquest mòdul està pensat per a Active Directory, però [https://github.com/Adldap2/Adldap2-Laravel/issues/106 també funciona amb OpenLDAP si s'ajusta bé]:<br />
https://github.com/Adldap2/Adldap2-Laravel<br />
<br />
Primer cal configurar un servidor [[LDAP]].<br />
<br />
Després, tingues en compte que cal ajustar els següents paràmetres en el .env:<br />
ADLDAP_CONTROLLERS=localhost<br />
#ADLDAP_PORT=389<br />
ADLDAP_ADMIN_USERNAME="cn=admin,dc=cacauet,dc=org"<br />
ADLDAP_ADMIN_PASSWORD="enric123"<br />
ADLDAP_BASEDN="dc=cacauet,dc=org"<br />
<br />
Podem fer una autenticació seguint algun d'aquests exemples.<br />
<br />
Exemple 1: cercar un element del directori<br />
<syntaxhighlight lang="php"><br />
$user = Adldap::search()->where("mail","=","pepe@jolgorio.tk")->get();<br />
</syntaxhighlight><br />
<br />
Exemple 2: autenticar un usuari<br />
<syntaxhighlight lang="php"><br />
if( Adldap::auth()->attempt("cn=pepe,ou=usuaris,dc=cacauet,dc=org","pepe123")) {<br />
// autenticació exitosa<br />
return "Pepe OK!";<br />
}<br />
</syntaxhighlight><br />
<br />
<br><br />
<br />
== Laravel en producció ==<br />
Per posar en producció un projecte basat en Laravel cal tenir en compte:<br />
* '''IMPORTANT, SEGURETAT: Només cal publicar la carpeta <code>/public</code>''' . 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 .<br />
** Aquesta carpeta <code>/public</code> no figura inicialment quan creem o clonem un projecte (està a .gitignore), a l'igual que la carpeta <code>/vendor</code>, que es generen quan fem un <code>$ composer install</code>.<br />
** Reviseu la secció [[Laravel#Treballant_amb_GIT_i_clonant]] per fer el setup del projecte després de clonar.<br />
* '''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'').<br />
* 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:<br />
** db.sqlite (si s'escau)<br />
** carpeta <code>/storage</code><br />
** carpeta <code>/bootstrap/cache</code><br />
<br />
=== Desplegament en AWS amb Ubuntu i Apache ===<br />
Guia pel desplegament en Ubuntu amb Apache:<br />
* Accedir al nostre servidor via SSH<br />
* 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<pre>/var/www</pre><br />
* Per veure detalls reviseu la secció [[Laravel#Treballant_amb_GIT_i_clonant]]. Recordeu que això implica: <br />
*# composer install<br />
*# configurar arxiu .env<br />
*# generar clau<br />
* Es requereix el mòdul ''mod_rewrite'' d'Apache (o Nginx)<pre>$ sudo a2enmod rewrite</pre><br />
* Publicar la carpeta <code>/public</code> del projecte Laravel, d'alguna d'aquestes maneres:<br />
** Crear un VirtualHost i apuntar la ServerRoot del domini o subdomini a /var/www/<projecte>/public<br />
** Crear un link simbòlic de la carpeta pública d'Apache a la carpeta public del Laravel amb la comanda <pre>$ ln -s /var/www/<projecte>/public /var/www/html/lara1</pre><br />
* 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".<br />
* Ajusta els permisos de:<br />
** db.sqlite (si s'escau) i també de la carpeta que el conté (si no, no es podrà escriure-hi)<br />
** carpeta <code>/storage</code><br />
** carpeta <code>/bootstrap/cache</code><br />
* Cal activar els arxius <code>.htaccess</code> , afegint la directiva <code>AllowOverride all</code><br />
<br />
A l'arxiu de conf. del nostre VirtualHost (a <code>/etc/apache2/sites-available</code>):<br />
<Directory /var/www/><br />
AllowOverride All<br />
</Directory><br />
<br />
<br />
És important remarcar que per SEGURETAT no hem de mostrar mai els arxius interns de Laravel, només cal publicar el contingut de /public<br />
<br />
<br><br />
<br />
=== Heroku ===<br />
Abans de procedir amb aquesta part hauries de llegir i treballar aquesta altra: [[Heroku]] on treballem amb PHP simple.<br />
<br />
Pots posar en marxa un projecte Laravel a Heroku fàcilment seguint aquesta documentació. Segueix el tutorial per iniciar la app:<br />
https://devcenter.heroku.com/articles/getting-started-with-laravel<br />
<br />
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.<br />
<br />
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.<br />
<br />
En canvi, [https://devcenter.heroku.com/articles/heroku-postgresql el add-on de POSTGRESQL és gratuït i sense targeta de crèdit! :)] Som-hi, doncs!<br />
<br />
Primer de tot, creeu el projecte Laravel i inicialitzeu GIT en cas que no el tingueu penjat a Github o similars:<br />
$ git init<br />
<br />
Inicialitzem projecte Heroku:<br />
$ heroku create elmeuprojectedeguais<br />
<br />
Afegim la BD PostgreSQL:<br />
$ heroku addons:create heroku-postgresql:hobby-dev<br />
<br />
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:<br />
$ heroku config -s | grep -i post<br />
<br />
Ens ho dona en la següent forma (exemple a continuació):<br />
DATABASE_URL='postgres://<usuari>:<password>@<maquina>:<port>/<bbdd>'<br />
DATABASE_URL='postgres://mxlsfebqyopadb:3e5af56b52cc06574645123ea9d9f7504564e207804dcc71a2db2848446ba064@ec2-156-73-167-43.compute-1.amazonaws.com:5432/d353ihheo564q7'<br />
<br />
Així, doncs, només caldrà ajustar les següents variables d'entorn que necessita el Laravel perquè això funcioni:<br />
DB_CONNECTION=pgsql<br />
DB_HOST=ec2-156...<br />
DB_PORT=5432<br />
DB_DATABASE=d353...<br />
DB_USERNAME=mxls...<br />
DB_PASSWORD=3e5a...<br />
<br />
Per fer-ho cal anar executant les següents ordres:<br />
$ heroku config:set DB_CONNECTION=pgsql<br />
$ ...etc...<br />
<br />
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:<br />
$ cp .env.example .env<br />
$ php artisan key:generate<br />
$ heroku config:set APP_KEY=base64:tX2ikx...<br />
<br />
En acabat, podem posar la app en producció:<br />
$ git add .<br />
$ git push heroku master<br />
<br />
I un cop acabats, migrem la nostra base de dades:<br />
$ heroku run php artisan migrate<br />
<br />
I veure la nostra flamant web en producció (a elmeuprojectedeguais.herokuapp.com):<br />
$ heroku open<br />
<br />
...et voilà!</div>Enrichttps://cacauet.org/wiki/index.php?title=Laravel&diff=4219Laravel2021-01-29T15:06:43Z<p>Enric: /* Heroku */</p>
<hr />
<div><nowiki>#FpInfor #DawMp07 #DawMp07Uf2 #DawMp07Uf02 #DawMpDual</nowiki><br />
<br />
<br />
== Intro i referències ==<br />
Laravel és un framework web per a PHP que està agafant molta força.<br />
<br />
Documentació oficial: https://laravel.com/docs/<br />
<br />
Tutorials:<br />
* [https://ajgallego.gitbooks.io/laravel-5/content/index.html Principal tutorial per seguir el curs]: <pre>https://ajgallego.gitbooks.io/laravel-5/content/index.html</pre><br />
* Forms: https://selftaughtcoders.com/from-idea-to-launch/lesson-23/laravel-5-application-form-model-binding-laravelcollective-forms-html-library-bootstrap-framework/<br />
* Forms i validació: https://scotch.io/tutorials/simple-laravel-crud-with-resource-controllers<br />
* Apunts del Sergi Coll: https://seicoll.github.io/DAW-M07-UF2-Apunts/<br />
* https://styde.net/laravel-5/<br />
* Per passar del schema SQL (per ex. de MySQL Workbench) a Laravel migration: https://adolfocuadros.com/sql_to_laravel/<br />
<br />
<br />
Plugins:<br />
* CORS (Cross-Origin Resource Sharing): https://github.com/barryvdh/laravel-cors<br />
* CRUD & admin : Hi ha molts plugins per crear ''admin panels'' automàticament. Alguns son:<br />
** Voyager: https://voyager.devdojo.com/<br />
** Craftable: https://www.getcraftable.com/<br />
* https://iamacoder.com/post/5-must-have-laravel-5-packages/<br />
<br />
Temes a ampliar:<br />
* Forms: https://laravel.com/docs/4.2/html<br />
* Validació de forms: https://laravel.com/docs/5.5/validation<br />
* Autenticació: https://laravel.com/docs/5.5/authentication<br />
<br />
<br><br />
<br />
== Instal·lació i setup ==<br />
<br />
Prerequisits:<br />
* Laravel i PHP, és molt important tenir en compte les versions:<br />
** <strike>Laravel 5.3 : PHP >= 5.6.4<br />
** Laravel 5.5 : PHP == 7.0<br />
** Laravel 5.6 : PHP >= 7.1<br />
** Laravel 5.7 : PHP >= 7.1.3</strike><br />
** Laravel 6.x : PHP >= 7.2<br />
* Si utilitzes Ubuntu 14 o menor [https://www.digitalocean.com/community/tutorials/how-to-upgrade-to-php-7-on-ubuntu-14-04 actualitza la teva versió de PHP a la 7.0]<br />
* Calen els paquets següents: <pre>$ sudo apt-get install php-mbstring php-zip php-xml php-mysql</pre><br />
<br />
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...:<br />
# Instal·la el gestor de paquets per PHP Composer<br />
#* El més fàcil és fer: (però no ho farem pq volem la darrera versió)<pre>$ sudo apt install composer</pre><br />
#* Prova primer la instal·lació genèrica : [https://getcomposer.org/download/ Instal.la PHP Composer]<br />
#* També tens aquesta altra forma d' [https://getcomposer.org/doc/00-intro.md#installation-linux-unix-osx instal·lar Composer per GNU/Linux]. Descarrega composer-setup.php i instal·la'l així:<pre>$ php composer-setup.php --install-dir=~/bin --filename=composer</pre><br />
# Instal·la la darrera versió de Laravel<br />
#* https://laravel.com/docs/5.7/installation<br />
#* Bàsicament el què cal fer és aquesta comanda per instal·lar el binari ''laravel'':<pre>$ composer global require laravel/installer</pre><br />
#* Laravel s'instal·la a <code>$HOME/.config/composer</code> però per poder executar les properes comandes necessitarem tenir <code>$HOME/.config/composer/vendor/bin</code> al nostre $PATH. Inserta això al teu <code>$HOME/.profile</code>: <pre>PATH=$PATH:~/.config/composer/vendor/bin</pre><br />
#*: Fes logout/login del sistema per activar aquests canvis<br />
# Crea una app Laravel allà on et faci més ràbia: <pre>$ laravel new laravelapp1</pre><br />
#: o també: <pre>$ composer create-project --prefer-dist laravel/laravel laravelapp1</pre><br />
#: o si volem una versió específica de laravel: <pre>$ composer create-project --prefer-dist laravel/laravel=5.8.* laravelapp1</pre><br />
# Arrenca l'aplicació de prova: <pre>$ php artisan serve</pre><br />
# Comprova la app amb el navegador a<pre>http://localhost:8000</pre><br />
<br />
<br><br />
<br />
Si ja has completat la instal·lació, pots procedir a crear un altre projecte nou i realitzar el següent tutorial "tasklist":<br />
https://laravel.com/docs/5.2/quickstart<br />
<br />
<br><br />
<br />
== Incidències vàries ==<br />
Aquest és un bon tutorial:<br />
https://ajgallego.gitbooks.io/laravel-5/content/index.html<br />
<br />
Igualment, podríem trobar algunes incidències. Us dono pistes:<br />
<br />
=== Treballant amb GIT i clonant ===<br />
Al pujar el projecte a un repo GIT, i clonar-lo després caldrà:<br />
# Re-instal·lar les dependències:<pre>$ composer install</pre><br />
# Regenerar arxiu <code>.env</code> : com que depèn de cada entorn no es fica al projecte (es posa a <code>.gitignore</code>), però pots copiar i modificar de <code>.env.example</code><br />
# Error ''The only supported ciphers are AES-128-CBC and AES-256-CBC with the correct key lengths.'' Es soluciona amb :<pre>$ php artisan key:generate</pre><br />
<br />
=== Creant controllers amb CRUD complert ===<br />
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.<br />
# Ja no es pot fer amb <strike><code>Route::controller</code></strike> sinó amb:<pre>Route::resource("cosa","CosaController");</pre><br />
# Per exemple, per crear un controller per al model "Cosa" ho faríem amb -r (de resource): <pre>$ php artisan make:controller -r CosaController</pre><br />
<br />
=== Treballant amb SQLite ===<br />
Per configurar la BD amb SQLite cal crear el fitxer abans amb:<br />
$ touch db.sqlite<br />
<br />
Configurar la BD a .env:<br />
DB_CONNECTION=sqlite<br />
DB_DATABASE=/path/absolut/al/db.sqlite<br />
<br />
Instal·lar els binaris necessaris de SQLite i de PHP:<br />
$ sudo apt-get install sqlite php-sqlite3<br />
<br />
I crear la BD inicial amb:<br />
$ php artisan migrate<br />
<br />
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.<br />
<br />
=== Eliminant models o migracions ===<br />
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:<br />
$ composer dump-autoload<br />
...i es tornaran a generar els arxius d'autoload sense els arxius que volíem esborrar.<br />
<br />
=== Treballant amb proxies i composer ===<br />
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):<br />
$ composer update<br />
Loading composer repositories with package information<br />
Updating dependencies (including require-dev)<br />
(...demana user/password de packagist.org ...)<br />
<br />
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:<br />
$ ssh -L 3128:localhost:3128 jo@elmeuserver.com<br />
I un cop logats, aprofitem per instal·lar el squid:<br />
$ sudo apt install squid<br />
Hem de mantenir la shell oberta mentre vulguem que estigui activat el túnel (l'hem assignat a localhost:3128).<br />
<br />
Obrim una altra shell i anem al nostre projecte Laravel:<br />
$ export http_proxy=localhost:3128<br />
$ composer update<br />
<br />
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).<br />
<br />
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:<br />
$ ssh jo@elmeuserver.com<br />
$ sudo apt remove squid<br />
<br />
<br><br />
<br />
== Tutorials ==<br />
Després d'elaborar la documentació he trobat aquest tutorial bastant útil (només fins la v5.2):<br />
https://laravel.com/docs/5.2/quickstart<br />
<br />
Tutorial per a CRUD complert:<br />
https://www.itsolutionstuff.com/post/laravel-6-crud-application-tutorialexample.html<br />
<br />
== Resum per a fer un CRUD ==<br />
<br />
=== Setup projecte ===<br />
Crear projecte:<br />
$ laravel new proj1<br />
Crear DB (en aquest cas SQLite:<br />
$ touch db.sqlite<br />
Modifica .env per configurar la DB com sqlite:<br />
DB_CONNECTION=sqlite<br />
DB_DATABASE=/path/absolut/al/db.sqlite<br />
<br />
=== Model ===<br />
Crear taules i migracions:<br />
$ php artisan make:migration crea_taula_items --create=items<br />
Editar la migració per crear les taules adequades. Mira't les principals referències:<br />
* [https://laravel.com/docs/5.5/migrations#columns Tipus de columnes]<br />
* [https://laravel.com/docs/5.5/migrations#foreign-key-constraints Relacions i FKs]<br />
Realitzar la migració:<br />
$ php artisan migrate<br />
Crear models:<br />
$ php artisan make:model Item<br />
Ajusta el model perquè apunti al nom correcte de la taula:<br />
https://laravel.com/docs/5.5/eloquent#eloquent-model-conventions<br />
<br />
=== Controller i rutes ===<br />
Crear controllers amb els mètodes estàndard (index, create-store, show, edit-update, destroy):<br />
$ php artisan make:controller -r ItemController<br />
Crear rutes a <code>routes/web.php</code>:<br />
Route::resource("item","ItemController");<br />
Crear plantilles per als mètodes (l'exemple diu "tema" enlloc de "item"):<br />
$ php artisan route:list<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
| Domain | Method | URI | Name | Action | Middleware |<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
| | GET|HEAD | / | | Closure | web |<br />
| | GET|HEAD | api/user | | Closure | api,auth:api |<br />
| | GET|HEAD | tema | tema.index | App\Http\Controllers\TemaController@index | web |<br />
| | POST | tema | tema.store | App\Http\Controllers\TemaController@store | web |<br />
| | GET|HEAD | tema/create | tema.create | App\Http\Controllers\TemaController@create | web |<br />
| | GET|HEAD | tema/{tema} | tema.show | App\Http\Controllers\TemaController@show | web |<br />
| | PUT|PATCH | tema/{tema} | tema.update | App\Http\Controllers\TemaController@update | web |<br />
| | DELETE | tema/{tema} | tema.destroy | App\Http\Controllers\TemaController@destroy | web |<br />
| | GET|HEAD | tema/{tema}/edit | tema.edit | App\Http\Controllers\TemaController@edit | web |<br />
+--------+-----------+-----------------------+----------------+-----------------------------------------------+--------------+<br />
<br />
Crear les views (plantilles blade) adequades per a tots els mètodes necessaris (els arxius van a <code>resources/views</code>). Pots veure [https://github.com/emieza/laravel-karaoke/tree/master/resources/views/llista aqui] alguns exemples.<br />
* '''index''' : llista tots els elements<br />
* '''show''' : mostra un element en concret, necessita que li passem un paràmetre per GET (id del element a mostrar)<br />
* '''create-store''' : "create és el form (no necessita codi), i "store" és el codi per insertar-ho a la BD (no necessita una plantilla)<br />
* '''edit-update''' : "edit" és el form, i "update" el codi per actualitzar la BD<br />
* '''destroy''' : elimina un element<br />
<br />
=== Codi del Controller i View ===<br />
* Crear views amb formularis d'entrada de dades: [https://github.com/emieza/laravel-karaoke/blob/master/resources/views/llista/crea.blade.php create.blade.php d'exemple]<br />
* Editar el codi del Controller per cridar pertinentment a les views: [https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/LlistaController.php Controller d'exemple]<br />
<br />
=== Més docs ===<br />
Una bona referència de la doc oficial per fer un CRUD és aquesta:<br />
https://laravel.com/docs/5.2/quickstart<br />
En particular per veure com utilitzar les templates oficials amb bootstrap ;)<br />
<br />
<br><br />
<br />
== Projecte d'exemple ==<br />
Aquest és el projecte que he realitzat per entrenar-me, et pot servir d'exemple. El pots veure en producció aquí: https://jolgorio.tk<br />
https://github.com/emieza/laravel-karaoke<br />
<br />
Fes-li un cop d'ull al readme.md per veure com posar-lo en marxa.<br />
<br />
MOLT IMPORTANT PEL PROJECTE: Cal crear un README.md (com [https://github.com/emieza/laravel-karaoke/blob/master/readme.md per exemple aquest]). No acceptaré cap projecte sense README.md<br />
<br />
Per entrenar-vos amb el Markdown teniu aquest tester:<br />
http://dillinger.io/<br />
<br />
Anem per feina:<br />
# Taules: llistes, temes, vots<br />
# Rutes que vols implementar per al projecte. [https://github.com/emieza/laravel-karaoke/blob/master/routes/web.php En el meu cas, tinc]:<br />
#* /llista/crea (GET per formulari + POST per store)<br />
#* /llista (index de llistes)<br />
#* /llista/{id} (show)<br />
#* /llista/{id}/crea (GET + POST, per crear temes en les llistes)<br />
#* /vota/{idtema}<br />
# Codi:<br />
#* als Controllers pertinents. Mira't l'[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/LlistaController.php exemple de les llistes de karaoke].<br />
#* Plantilles: a resources/views/xxxx.blade.php . Mira't l'[https://github.com/emieza/laravel-karaoke/tree/master/resources/views/llista exemple un altre cop].<br />
<br />
<br><br />
<br />
== ORM : Models i relacions ==<br />
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.<br />
<br />
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. <br />
<br />
El què anem a explicar està documentat a l'apartat "Eloquent ORM" de Laravel:<br />
https://laravel.com/docs/5.7/eloquent-relationships<br />
https://laravel.com/docs/6.x/eloquent-relationships<br />
<br />
=== Accedint relacions 1-N de forma directa ===<br />
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í.<br />
<br />
L'objectiu serà poder accedir a l'objecte pare d'aquesta manera per mostrar el text del Post (pare).<br />
<syntaxhighlight lang="php"><br />
$comment = Comment::find(33);<br />
echo $comment->post->text;<br />
</syntaxhighlight><br />
<br />
Per aconseguir això, cal que indiquem la relació existent a les taules entre els models Post i Comment amb la relació <code>belongsTo</code>:<br />
<br />
<syntaxhighlight lang="php"><br />
<?php<br />
namespace App;<br />
use Illuminate\Database\Eloquent\Model;<br />
class Comment extends Model<br />
{<br />
/**<br />
* Accedeix al pare (Post)<br />
*/<br />
public function post()<br />
{<br />
return $this->belongsTo('App\Post','post_id');<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=== Accedint relacions 1-N de forma inversa ===<br />
El següent cas típic serà accedir des d'un objecte Post als diferents Comentaris, més o menys així:<br />
<br />
<syntaxhighlight lang="php"><br />
$comments = App\Post::find(1)->comments;<br />
foreach ($comments as $comment) {<br />
// ... el teu codi...<br />
echo $comment->text;<br />
}<br />
</syntaxhighlight><br />
El codi que veiem és per a un ''controller'', però es pot aplicar també als ''templates'', amb @foreach i similars.<br />
<br />
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<br />
<syntaxhighlight lang="php"><br />
<?php<br />
namespace App;<br />
use Illuminate\Database\Eloquent\Model;<br />
class Post extends Model<br />
{<br />
/**<br />
* Accedeix als comentaris relacionats amb el Post actual<br />
*/<br />
public function comments()<br />
{<br />
return $this->hasMany('App\Comment','<ref_remota>','<ref_local>');<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
On:<br />
* <ref_remota> és el camp de la taula de Comment que referencia el Post<br />
* <ref_local> és el camp de Post que fa de PK i on Comment apunta<br />
<br />
Per accedir al objecte relacionat "pare" caldrà fer una altra funció, en concret ''belongsTo''. Consulta la doc de les relacions 1-a-N (inversa).<br />
<br />
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:<br />
https://laravel.com/docs/5.5/eloquent-relationships#one-to-many<br />
<br />
=== Aniuant JSON en la API ===<br />
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:<br />
<br />
<syntaxhighlight lang="php"><br />
<?php<br />
Route::get("/comentaris", function() {<br />
$post = Post::with("comments")->get();<br />
return $post;<br />
});<br />
</syntaxhighlight><br />
<br />
...i ens retornarà les dades aniuades que volem! :)<br />
<br />
<br><br />
<br />
== Més coses ==<br />
Alguns temes que no hem aprofundit però que convé conèixer.<br />
<br />
=== Autenticació ===<br />
Senzill d'implementar i imprescindible. Laravel incorpora un ''scaffold'' per facilitar una funció tan estàndard.<br />
Amb una sola instrucció ens crea les rutes, vistes i els controllers típics (login, logout).<br />
<br />
[https://laravel.com/docs/5.5/authentication Autenticació en Laravel 5.x]:<br />
$ php artisan make:auth<br />
<br />
[https://laravel.com/docs/6.x/authentication Autenticació en Laravel 6.x]:<br />
$ composer require laravel/ui --dev<br />
$ php artisan ui vue --auth<br />
<br />
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:<br />
$ npm install && npm run dev<br />
<br />
També hi ha [https://laracasts.com/discuss/channels/laravel/laravel-60-appcss?page=1 solucions al problema carregant els CSS i JS del CDN] (només cal canviar un link en el ''head'' de <code>app.blade.php</code>.<br />
<br />
=== Seeding ===<br />
Una part molt important és la de crear dades per farcir la base de dades inicialment i poder així testejar amb comoditat.<br />
<br />
https://laravel.com/docs/6.x/seeding<br />
<br />
En algun moment donat convé utilitzar un ''factory'' que ens permet crear elements en massa:<br />
<br />
https://laravel.com/docs/6.x/database-testing#writing-factories<br />
<br />
El ''factory'' sol utilitzar una llibreria <code>Faker</code> que ens va molt bé per crear noms i cognoms aleatoris, lorem ipsum, etc. que ens facilitarà la creació de dades de prova.<br />
<br />
https://github.com/fzaninotto/Faker<br />
<br />
=== Validacions ===<br />
Laravel ens ofereix un mecanisme de validació de formularis molt potent i efectiu.<br />
<br />
https://laravel.com/docs/5.5/validation<br />
<br />
=== Sessions ===<br />
D'entrada és molt útil per emetre missatges "flash", i informar l'usuari del processament intern.<br />
<br />
https://laravel.com/docs/5.5/session<br />
<br />
=== Arxius: filesystem vs BLOBs en BD ===<br />
Les imatges es poden guardar al sistema d'arxius o bé a la base de dades.<br />
* '''Filesystem''': En el propi tutorial hi ha una explicació de [https://ajgallego.gitbooks.io/laravel-5/content/capitulo_4_datos_de_entrada.html com guardar binaris amb el mètode clàssic del filesystem]<br />
* '''BLOBs en la BD''': Laravel ens permet crear models amb BLOBs i insertar les dades a la BD:<br />
** [https://www.daniweb.com/programming/web-development/threads/480731/how-to-inserting-files-on-mysql-using-laravel Insertant BLOBs amb Larvel]<br />
** Tingueu en compte, si ho feu així, de [https://stackoverflow.com/questions/8499633/how-to-display-base64-images-in-html com renderitzar continguts base64 (BLOBs) sobre un HTML]<br />
<br />
=== A solucionar ===<br />
Alguns temes a solucionar:<br />
* Quan utilitzem el scaffold d'autenticació, falla el logout. Això es deu a un canvi del mètode de GET a POST per motius de seguretat (amb POST, només podran fer logout des de la pròpia app Laravel ja que porta el csrf_token).<br />
*: https://laracasts.com/discuss/channels/laravel/laravel-53-logout-methodnotallowed<br />
<br />
<br><br />
<br />
=== Atacant 2 bases de dades simultàniament ===<br />
En alguns casos podem necessitar configurar 2 instàncies de bases de dades separades per optimitzar el rendiment. Aquest post ho explica molt bé:<br />
https://fideloper.com/laravel-multiple-database-connections<br />
<br />
Caldrà configurar el .env , config/database.php i especificar quina DB ataca en les migracions i en els models que creem.<br />
<br />
<br><br />
<br />
== Laravel i LDAP ==<br />
Aquest mòdul està pensat per a Active Directory, però [https://github.com/Adldap2/Adldap2-Laravel/issues/106 també funciona amb OpenLDAP si s'ajusta bé]:<br />
https://github.com/Adldap2/Adldap2-Laravel<br />
<br />
Primer cal configurar un servidor [[LDAP]].<br />
<br />
Després, tingues en compte que cal ajustar els següents paràmetres en el .env:<br />
ADLDAP_CONTROLLERS=localhost<br />
#ADLDAP_PORT=389<br />
ADLDAP_ADMIN_USERNAME="cn=admin,dc=cacauet,dc=org"<br />
ADLDAP_ADMIN_PASSWORD="enric123"<br />
ADLDAP_BASEDN="dc=cacauet,dc=org"<br />
<br />
Podem fer una autenticació seguint algun d'aquests exemples.<br />
<br />
Exemple 1: cercar un element del directori<br />
<syntaxhighlight lang="php"><br />
$user = Adldap::search()->where("mail","=","pepe@jolgorio.tk")->get();<br />
</syntaxhighlight><br />
<br />
Exemple 2: autenticar un usuari<br />
<syntaxhighlight lang="php"><br />
if( Adldap::auth()->attempt("cn=pepe,ou=usuaris,dc=cacauet,dc=org","pepe123")) {<br />
// autenticació exitosa<br />
return "Pepe OK!";<br />
}<br />
</syntaxhighlight><br />
<br />
<br><br />
<br />
== Laravel en producció ==<br />
Per posar en producció un projecte basat en Laravel cal tenir en compte:<br />
* '''IMPORTANT, SEGURETAT: Només cal publicar la carpeta <code>/public</code>''' . 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 .<br />
** Aquesta carpeta <code>/public</code> no figura inicialment quan creem o clonem un projecte (està a .gitignore), a l'igual que la carpeta <code>/vendor</code>, que es generen quan fem un <code>$ composer install</code>.<br />
** Reviseu la secció [[Laravel#Treballant_amb_GIT_i_clonant]] per fer el setup del projecte després de clonar.<br />
* '''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'').<br />
* 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:<br />
** db.sqlite (si s'escau)<br />
** carpeta <code>/storage</code><br />
** carpeta <code>/bootstrap/cache</code><br />
<br />
=== Desplegament en AWS amb Ubuntu i Apache ===<br />
Guia pel desplegament en Ubuntu amb Apache:<br />
* Accedir al nostre servidor via SSH<br />
* 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<pre>/var/www</pre><br />
* Per veure detalls reviseu la secció [[Laravel#Treballant_amb_GIT_i_clonant]]. Recordeu que això implica: <br />
*# composer install<br />
*# configurar arxiu .env<br />
*# generar clau<br />
* Es requereix el mòdul ''mod_rewrite'' d'Apache (o Nginx)<pre>$ sudo a2enmod rewrite</pre><br />
* Publicar la carpeta <code>/public</code> del projecte Laravel, d'alguna d'aquestes maneres:<br />
** Crear un VirtualHost i apuntar la ServerRoot del domini o subdomini a /var/www/<projecte>/public<br />
** Crear un link simbòlic de la carpeta pública d'Apache a la carpeta public del Laravel amb la comanda <pre>$ ln -s /var/www/<projecte>/public /var/www/html/lara1</pre><br />
* 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".<br />
* Ajusta els permisos de:<br />
** db.sqlite (si s'escau) i també de la carpeta que el conté (si no, no es podrà escriure-hi)<br />
** carpeta <code>/storage</code><br />
** carpeta <code>/bootstrap/cache</code><br />
* Cal activar els arxius <code>.htaccess</code> , afegint la directiva <code>AllowOverride all</code><br />
<br />
A l'arxiu de conf. del nostre VirtualHost (a <code>/etc/apache2/sites-available</code>):<br />
<Directory /var/www/><br />
AllowOverride All<br />
</Directory><br />
<br />
<br />
És important remarcar que per SEGURETAT no hem de mostrar mai els arxius interns de Laravel, només cal publicar el contingut de /public<br />
<br />
<br><br />
<br />
=== Heroku ===<br />
Abans de procedir amb aquesta part hauries de llegir i treballar aquesta altra: [[Heroku]] on treballem amb PHP simple.<br />
<br />
Pots posar en marxa un projecte Laravel a Heroku fàcilment seguint aquesta documentació. Segueix el tutorial per iniciar la app:<br />
https://devcenter.heroku.com/articles/getting-started-with-laravel<br />
<br />
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.<br />
<br />
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.<br />
<br />
En canvi, [https://devcenter.heroku.com/articles/heroku-postgresql el add-on de POSTGRESQL és gratuït i sense targeta de crèdit! :)] Som-hi, doncs!<br />
<br />
Primer de tot, creeu el projecte Laravel i inicialitzeu GIT en cas que no el tingueu penjat a Github o similars:<br />
$ git init<br />
<br />
Inicialitzem projecte Heroku:<br />
$ heroku create elmeuprojectedeguais<br />
<br />
Afegim la BD PostgreSQL:<br />
$ heroku addons:create heroku-postgresql:hobby-dev<br />
<br />
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:<br />
$ heroku config -s | grep -i post<br />
<br />
Ens ho dona en la següent forma (exemple a continuació):<br />
DATABASE_URL='postgres://<usuari>:<password>@<maquina>:<port>/<bbdd>'<br />
DATABASE_URL='postgres://mxlsfebqyopadb:3e5af56b52cc06574645123ea9d9f7504564e207804dcc71a2db2848446ba064@ec2-156-73-167-43.compute-1.amazonaws.com:5432/d353ihheo564q7'<br />
<br />
Així, doncs, només caldrà ajustar les següents variables d'entorn que necessita el Laravel perquè això funcioni:<br />
DB_CONNECTION=pgsql<br />
DB_HOST=ec2-156...<br />
DB_PORT=5432<br />
DB_DATABASE=d353...<br />
DB_USERNAME=mxls...<br />
DB_PASSWORD=3e5a...<br />
<br />
Per fer-ho cal anar executant les següents ordres:<br />
$ heroku config:set DB_CONNECTION=pgsql<br />
$ ...etc...<br />
<br />
I també carregueu una APP_KEY. La podeu generar amb <br />
APP_KEY=...<br />
<br />
En acabat, podem posar la app en producció:<br />
$ git add .<br />
$ git push heroku master<br />
<br />
I un cop acabats, migrem la nostra base de dades:<br />
$ heroku run php artisan migrate<br />
<br />
...et voilà!</div>Enrichttps://cacauet.org/wiki/index.php?title=Heroku&diff=4218Heroku2021-01-25T13:36:40Z<p>Enric: /* Per desenvolupar en local */</p>
<hr />
<div><br />
<br />
== Introducció ==<br />
Heroku és una PaaS (Platform as a Service) que ens permet fer desplegaments sense necessitat de tenir un servidor.<br />
<br />
[[Desplegament_d%27aplicacions_web#UF2:_Servidors_d.27aplicacions_web|Servidors d'aplicacions web]]<br />
<br />
<br><br />
<br />
== Primeres passes ==<br />
Inicia't amb aquest tutorial per PHP simple:<br />
https://devcenter.heroku.com/articles/getting-started-with-php#introduction<br />
<br />
Quan hagis acabat, tindràs en marxa una web d'exemple. Fes un cop d'ull al Procfile, veuràs que la carpeta web/ és on s'inicia la nostra aplicació web.<br />
<br />
Substitueix els continguts de la carpeta web/ per un index.php senzill per començar a fer la nostra app.<br />
<br />
<br><br />
<br />
== Plugins i bases de dades ==<br />
Un cop hem estat capaços de crear una web, crearem una base de dades. Aparentment podem crear una MySQL gratuita, però ens demana la targeta de crèdit. En canvi, amb PostgreSQL no ens en demana.<br />
<br />
Teniu la [https://devcenter.heroku.com/articles/heroku-postgresql Documentació oficial de PostgreSQL per a Heroku] on explica com posar a punt la BD.<br />
<br />
Crearem una base de dades PostgreSQL als Add-ons (via web o via comandes CLI). Podràs veure les credencials de la BBDD per utilitzar-ho en el PDO després.<br />
<br />
Crea una pàgina PHP d'una TASKLIST amb PostgreSQL. Ha de quedar més o menys com aquesta:<br />
https://floating-beyond-40727.herokuapp.com<br />
<br />
Post utilitzar aquest exemple de PDO:<br />
https://uf.ctrl-alt-d.net/material/mostra/50/php-acces-a-dades-amb-pdo<br />
<br />
Caldrà que creis la taula, un formulari per entrar les tasks, i visualitzar-les.<br />
<br />
=== Accedint a la shell del PostgreSQL ===<br />
Normalment, i si no tenim algun proxy o tallafocs intermig, ens podem connectar des de la shell LOCAL amb:<br />
$ heroku pg:psql<br />
<br />
Però si tenim algun d'aquests casos de proxy/tallafocs, podem fer un hack:<br />
# Ens loguem a la web de Heroku<br />
# Entrem a la nostra aplicació -> More... -> Run console<br />
# Executem "bash"<br />
# Dintre de la consola web, executem: <pre>$ psql $DATABASE_URL</pre><br />
#: Podria ser que enlloc de $DATABASE_URL la variable fos $HEROKU_POSTGRESQL_WHITE_URL<br />
#: Per examinar totes les variables d'entorn pots executar "env" a la shell<br />
<br />
=== Carregar un BD sobre Postgre a Heroku ===<br />
Podeu [http://pgfoundry.org/projects/dbsamples/ descarregar BBDD d'exemple aquí]. Per exemple, la típica world.sql que també te MySQL.<br />
<br />
Per carregar la vostra BD sobre Heroku només cal fer:<br />
$ heroku pg:psql < lamevaBD.sql<br />
<br />
<br><br />
<br />
== Per desenvolupar en local ==<br />
Per treballar més àgilment convé treballar en local. Només desplegarem el projecte a Heroku quan el tinguem més o menys funcional.<br />
<br />
En principi hauria de funciona el següent per treballar en local (per un projecte en PHP):<br />
<br />
$ cd my-heroku-project<br />
$ composer install<br />
$ heroku local<br />
<br />
Si és amb NodeJS:<br />
$ cd my-heroky-project<br />
$ npm install<br />
$ npm start<br />
<br />
Però sempre hi ha mes coses que controlar:<br />
<br />
# Haurieu de tenir instal·lat ja PostgreSQL a la màquina local, si heu arribat aquí. En cas contrari, l'instal·leu amb APT.<br />
# Mireu-vos l'article [[PostgreSQL]] per iniciar-vos a com utilitzar aquesta BDD en local. Caldrà crear una BD i usuari/contrasenya per poder accedir-hi. El nom d'usuari ha de ser el mateix que el del sistema operatiu.<br />
#: Es recomana (per simplificar): crear un usuari amb el mateix nom del del SO, i crear una BBDD amb el mateix nom de l'usuari.<br />
# Canvieu la contrasenya de l'usuari de Postgre amb:<pre>postgre=>ALTER USER enric PASSWORD 'enric123';</pre><br />
# Si el vostre projecte és PHP pur, hauríem de posar-lo a la carpeta <code>/var/www/html</code> per publicar-ho a l'Apache. Però tenim maneres alternatives per publicar-ho. En concret, aquesta, dins la pròpia carpeta del projecte:<pre>php -S localhost:8080 -t ./ index.php</pre><br />
# Visiteu amb el navegador per visualitzar:<pre>http://localhost:8080</pre><br />
# Les instruccions de connexió a BD amb PHP no us funcionaran. Caldrà que construïu la variable $DATABASE_URL adequadament abans d'executar la comanda de PHP:<pre>$ export DATABASE_URL=postgres://enric:enric123@localhost:5432/enric</pre><br />
<br />
<br />
<br><br />
<br />
== Heroku amb frameworks ==<br />
* [[Laravel#Heroku]]<br />
* [[Django_en_producci%C3%B3#Django_en_producci.C3.B3_amb_Heroku|Django amb Heroku]]</div>Enrichttps://cacauet.org/wiki/index.php?title=Heroku&diff=4217Heroku2021-01-25T13:30:10Z<p>Enric: /* Per desenvolupar en local */</p>
<hr />
<div><br />
<br />
== Introducció ==<br />
Heroku és una PaaS (Platform as a Service) que ens permet fer desplegaments sense necessitat de tenir un servidor.<br />
<br />
[[Desplegament_d%27aplicacions_web#UF2:_Servidors_d.27aplicacions_web|Servidors d'aplicacions web]]<br />
<br />
<br><br />
<br />
== Primeres passes ==<br />
Inicia't amb aquest tutorial per PHP simple:<br />
https://devcenter.heroku.com/articles/getting-started-with-php#introduction<br />
<br />
Quan hagis acabat, tindràs en marxa una web d'exemple. Fes un cop d'ull al Procfile, veuràs que la carpeta web/ és on s'inicia la nostra aplicació web.<br />
<br />
Substitueix els continguts de la carpeta web/ per un index.php senzill per començar a fer la nostra app.<br />
<br />
<br><br />
<br />
== Plugins i bases de dades ==<br />
Un cop hem estat capaços de crear una web, crearem una base de dades. Aparentment podem crear una MySQL gratuita, però ens demana la targeta de crèdit. En canvi, amb PostgreSQL no ens en demana.<br />
<br />
Teniu la [https://devcenter.heroku.com/articles/heroku-postgresql Documentació oficial de PostgreSQL per a Heroku] on explica com posar a punt la BD.<br />
<br />
Crearem una base de dades PostgreSQL als Add-ons (via web o via comandes CLI). Podràs veure les credencials de la BBDD per utilitzar-ho en el PDO després.<br />
<br />
Crea una pàgina PHP d'una TASKLIST amb PostgreSQL. Ha de quedar més o menys com aquesta:<br />
https://floating-beyond-40727.herokuapp.com<br />
<br />
Post utilitzar aquest exemple de PDO:<br />
https://uf.ctrl-alt-d.net/material/mostra/50/php-acces-a-dades-amb-pdo<br />
<br />
Caldrà que creis la taula, un formulari per entrar les tasks, i visualitzar-les.<br />
<br />
=== Accedint a la shell del PostgreSQL ===<br />
Normalment, i si no tenim algun proxy o tallafocs intermig, ens podem connectar des de la shell LOCAL amb:<br />
$ heroku pg:psql<br />
<br />
Però si tenim algun d'aquests casos de proxy/tallafocs, podem fer un hack:<br />
# Ens loguem a la web de Heroku<br />
# Entrem a la nostra aplicació -> More... -> Run console<br />
# Executem "bash"<br />
# Dintre de la consola web, executem: <pre>$ psql $DATABASE_URL</pre><br />
#: Podria ser que enlloc de $DATABASE_URL la variable fos $HEROKU_POSTGRESQL_WHITE_URL<br />
#: Per examinar totes les variables d'entorn pots executar "env" a la shell<br />
<br />
=== Carregar un BD sobre Postgre a Heroku ===<br />
Podeu [http://pgfoundry.org/projects/dbsamples/ descarregar BBDD d'exemple aquí]. Per exemple, la típica world.sql que també te MySQL.<br />
<br />
Per carregar la vostra BD sobre Heroku només cal fer:<br />
$ heroku pg:psql < lamevaBD.sql<br />
<br />
<br><br />
<br />
== Per desenvolupar en local ==<br />
Per treballar més àgilment convé treballar en local. Només desplegarem el projecte a Heroku quan el tinguem més o menys funcional.<br />
<br />
En principi hauria de funciona el següent per treballar en local (per un projecte en PHP):<br />
<br />
$ cd my-heroku-project<br />
$ composer install<br />
$ heroku local<br />
<br />
Però sempre hi ha mes coses que controlar:<br />
<br />
# Haurieu de tenir instal·lat ja PostgreSQL a la màquina local, si heu arribat aquí. En cas contrari, l'instal·leu amb APT.<br />
# Mireu-vos l'article [[PostgreSQL]] per iniciar-vos a com utilitzar aquesta BDD en local. Caldrà crear una BD i usuari/contrasenya per poder accedir-hi. El nom d'usuari ha de ser el mateix que el del sistema operatiu.<br />
#: Es recomana (per simplificar): crear un usuari amb el mateix nom del del SO, i crear una BBDD amb el mateix nom de l'usuari.<br />
# Canvieu la contrasenya de l'usuari de Postgre amb:<pre>postgre=>ALTER USER enric PASSWORD 'enric123';</pre><br />
# Si el vostre projecte és PHP pur, hauríem de posar-lo a la carpeta <code>/var/www/html</code> per publicar-ho a l'Apache. Però tenim maneres alternatives per publicar-ho. En concret, aquesta, dins la pròpia carpeta del projecte:<pre>php -S localhost:8080 -t ./ index.php</pre><br />
# Visiteu amb el navegador per visualitzar:<pre>http://localhost:8080</pre><br />
# Les instruccions de connexió a BD amb PHP no us funcionaran. Caldrà que construïu la variable $DATABASE_URL adequadament abans d'executar la comanda de PHP:<pre>$ export DATABASE_URL=postgres://enric:enric123@localhost:5432/enric</pre><br />
<br />
<br />
<br><br />
<br />
== Heroku amb frameworks ==<br />
* [[Laravel#Heroku]]<br />
* [[Django_en_producci%C3%B3#Django_en_producci.C3.B3_amb_Heroku|Django amb Heroku]]</div>Enrichttps://cacauet.org/wiki/index.php?title=E-mail_Linux_amb_Docker&diff=4216E-mail Linux amb Docker2020-12-10T18:28:21Z<p>Enric: /* Obrint ports a Amazon AWS */</p>
<hr />
<div><br />
<nowiki>#FpInfor #Asix #AsixMp08 #AsixMp08Uf3 #AsixMp08Uf03 #Smx #SmxMp07 #SmxMp07Uf2 #SmxMp07Uf02</nowiki><br />
<br />
<br />
== Introducció ==<br />
El servei de [[correu electrònic]] és força complexe ja que es composa de diversos processos o ''daemons''. A part del típic servei de MTA (postfix, sendmail, etc.) ens cal també un servei de Fetchmail (Courier, Dovecot), antivirus, anti-spam, etc., a part de configurar els certificats i modes d'autenticació encriptada.<br />
<br />
El sistema de contenidors [[Docker]] ens facilita tota aquesta posada en marxa del servei. Bé, en concret Docker solament no, sinó algú que s'ha currat el sistema de correu complert i n'ha fet una versió ''dockeritzada''. Per poder fer aquesta pràctica cal que estiguis fortament familiaritzat amb [[Docker]].<br />
<br />
Farem aquesta pràctica '''en una màquina virtual Amazon AWS EC2'''. Si no has treballat amb elles mira't l'article [[AWS: Amazon Web Services]]. Això és per diversos motius:<br />
* Necessitem una IP fixa (les dinàmiques estan en una ''blacklist'' i els grans servidors com gmail o hotmail no ens permetran enviar-los emails). Les ''elastic IPs'' de AWS ens ho permetran.<br />
* Els instituts solen tenir limitades les connexions sortints de correu per evitar els spammers i accions de segons quins virus.<br />
<br />
<br><br />
<br />
== Posta en marxa del docker ==<br />
<br />
=== Prerequists: docker-compose ===<br />
En Ubuntu existeix el package docker-compose, però és una versió antiga i necessitem la versió més actual.<br />
<br />
Instal·la la darrera versió seguint aquestes explicacions:<br />
https://docs.docker.com/compose/install/<br />
<br />
=== Prerequisits: MX records ===<br />
El correu electrònic utilitza els '''registres MX''', enlloc dels habituals ''registres A'' en el nostre DNS server (del registrador del domini).<br />
<br />
Ves, doncs, al panell de control del teu registrador (.com o .tk) i crea un registre MX. Et demanarà que el reenviis cap a un domini definit en un registre A prèviament creat. Típicament la gent sol fer un registre A amb mail.elmeudomini.com i el MX sense subdomini el reenvia a aquest.<br />
<br />
=== Explorant imatges de Docker ===<br />
Per veure quines opcions tenim podem executar:<br />
$ docker search mail<br />
<br />
A mi m'ha funcionat prou bé la versió de Thomas Vial, que és la 1a que surt a la llista amb força "stars" (aka "likes"). Podeu trobar el codi aquí per tafanejar-lo:<br />
https://github.com/tomav/docker-mailserver<br />
<br />
=== Posta en marxa del mailserver ===<br />
Caldrà que coneguis '''docker-composer''' per posar en marxa el docker-mailserver.<br />
<br />
Segueix les instruccions que explica el desenvolupador en el README.<br />
<br />
IMPORTANT: modifiqueu els següents paràmetres del <code>docker-compose.yml</code><br />
# Deshabiliteu el mòdul FAIL2BAN, ja que per fer proves ens pot molestar. És un mòdul molt útil que prohibeix les IPs que fallen en la autenticació diverses vegades. Molt interessant per seguretat, però pot fastidiar-nos les proves. Canvieu la variable d'entorn:<pre> - ENABLE_FAIL2BAN=0</pre><br />
# Poseu els 2 volums <code>mailstate</code> i <code>maildata</code> com a directoris locals. És convenient per diversos motius:<br />
#* Permet fer persistents els arxius amb els correus dels usuaris<br />
#* Triga menys a arrencar el contenidor (ha de regenerar menys arxius)<br />
<br />
=== Creant comptes ===<br />
Abans que el nostre servidor sigui operatiu caldrà crear diversos comptes d'usuari. Per fer-los consulta el README del docker.<br />
<br />
Recorda que pots crear comptes de diferents dominis, fes-ne al menys de 2 dominis diferents.<br />
<br />
<br />
=== Activant memòria virtual ===<br />
Per algunes aplicacions podríem necessitar memòria virtual o swap, però les màquines EC2 inicialment no en porten. És el cas del docker-mailserver. El sistema pot fallar si no tenim prou RAM, 1 GB és molt just per a algunes aplicacions.<br />
<br />
[https://github.com/tomav/docker-mailserver/issues/6 Com explica aquest ''issue''], el ''spamd'' i/o el ''clamav'' fallen si tenim poca RAM.<br />
<br />
Utilitza aquest [https://www.digitalocean.com/community/tutorials/how-to-add-swap-on-ubuntu-14-04 tutorial per afegir memòria virtual a un EC2].<br />
<br />
Amb 1 GB n'hi ha prou, no afegiu més pq el disc dur és petit (8 GB) i si ens passem podem saturar-lo i fer que la màquina funcioni malament.<br />
<br />
<br><br />
<br />
=== Obrint ports a Amazon AWS ===<br />
Si ho realitzem sobre un servidor de Amazon AWS cal fer 2 coses:<br />
* Obrir el ports necessaris (25,993,465,587) al ''security group'' de la nostra instància.<br />
* [https://scrum.ieti.cat/scrum/projecte/7#sprint-37 Demanar a Amazon AWS que aixequin la restricció del port 25 de sortida del servidor]. Aquesta mesura va aparèixer fa uns anys per evitar que els servidors de AWS fessin spam, ja que això acaba per fer entrar les IPs de AWS en les blacklist de Spamhaus.<br />
* Comprovar que la IP de la meva instància no està llistada en les [https://www.spamhaus.org/ blacklist de Spamhaus].<br />
<br />
<br><br />
<br />
== Accedint des de clients ==<br />
<br />
=== Test amb TELNET ===<br />
Podem enviar un missatge al nostre servidor, sempre i quan el destinatari sigui alguna bústia interna. Proveu d'accedir al port 25 del vostre servidor de forma externa, i feu un email tal i [https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol com explica l'apartat "SMTP transport example" de l'aritcle sobre SMTP de la Vikipèdia].<br />
<br />
D'aquesta manera podreu veure una mica més en detall com funcionen els ''internals'' del SMTP.<br />
<br />
Proveu també d'enviar un email a una adreça externa, i mostra a l'informe quin error et dona.<br />
<br />
Proveu també de fer el mateix des del propi servidor. Veureu que feu el telnet des de localhost podreu enviar emails on vulgueu, i no només a les adreces internes.<br />
<br />
=== Accedint via IMAPS ===<br />
Configura una aplicació client d'email (com Outlook, Thunderbird, etc.) per a accedir al teu servidor i llegir els correus via IMAPS. '''Es recomana fer-ho des d'una aplicació de correu per al mòbil, en concret Bluemail és força bona'''.<br />
<br />
Abans de res cal obrir els ports del servidor 993, 25, 587. Per testejar si el vostre servidor és accessible es recomana la comanda linux ''nmap'' per veure quins ports teniu oberts, per ex:<br />
$ nmap jolgorio.tk<br />
<br />
Starting Nmap 7.01 ( https://nmap.org ) at 2017-02-15 20:30 CET<br />
Nmap scan report for jolgorio.tk (54.229.49.51)<br />
Host is up (0.024s latency).<br />
rDNS record for 54.229.49.51: ec2-54-229-49-51.eu-west-1.compute.amazonaws.com<br />
Not shown: 992 filtered ports<br />
PORT STATE SERVICE<br />
22/tcp open ssh<br />
'''25/tcp open smtp'''<br />
80/tcp open http<br />
443/tcp open https<br />
465/tcp closed smtps<br />
'''587/tcp open submission'''<br />
'''993/tcp open imaps'''<br />
8081/tcp closed blackice-icecap<br />
<br />
Nmap done: 1 IP address (1 host up) scanned in 5.26 seconds<br />
<br />
És important accedir a través de la versió segura (IMAPS al port 993 i <strike>no al IMAP - port 143</strike>) per permetre la confidencialitat de la transferència de dades.<br />
<br />
Tingues en compte que al no tenir els certificats no la validació del SSL no serà correcta. Cal configurar la utilització del SSL sense verificació dels certificats.<br />
<br />
Resumint, la configuració del vostre client seria:<br />
* Correu entrant: IMAPS, port 993, SSL, Contrasenya simple, ometre comprovació de certificats<br />
* Correu sortint: SMTPS, port 587, STARTTLS, Contrasenya simple, ometre comprovació de certificats<br />
<br />
=== Webmail ===<br />
Busca una imatge Docker d'un software de webmail, instal·la-la en el teu servidor i configura-la perquè es connecti al servidor de correu que hem realitzat fins ara.<br />
<br />
Per alguns d'aquests softwares més sofisticats (com Roundcube) caldrà que instal·lis també una base de dades MySQL (guarda configuracions de la interfície, preferències d'usuari, etc.). Altres més senzills potser no la necessiten.<br />
<br />
Aquesta versió del Roundcube està muntada amb sqlite i no necessita tant setup com en el altres casos (per lligar-la amb mysql es fa més feixuc). L'únic inconvenient és que els settings desapareixen si reiniciem el contenidor, però pot ser un mal menor:<br />
https://hub.docker.com/r/robbertkl/roundcube/<br />
<br />
Si l'instal·leu a un VPS com el de Amazon AWS, us trobareu que haureu de publicar un port per veure el webmail. Però clar, accedir al nostre correu a través, per exemple de http://elmeudomini.com:9000 fa lleig. Solució:<br />
# Utilitzar un túnel SSH per accedir-hi i depurar el funcionament del webmail.<br />
# Visualitzar el roundcube en una URL principal (o sigui, del port 80 del domini). Tenim varies opcions:<br />
#* Activar el mòdul de proxy invers del Apache per visualitzar el webmail en una altra adreça com: <pre>http://elmeudomini.com/webmail</pre><br />
#* Fer un virtual server en un subdomini per accedir al webmail, per exemple: <pre>http://webmail.elmeudomini.com</pre><br />
<br />
En ambdós casos us caldrà activar el mòdul de proxy invers i connectar-se per túnel per depurar. [[Tomcat#Accés per túnel al manager|Aquest article ho explica]] (és pel Tomcat, però us servirà de forma molt similar).<br />
<br />
Per tal que el container del Roundcube funcioni, caldrà ajustar les següents variables (si ho feu amb docker-compose va tal qual, sense cometes; si ho feu des de docker a seques, cal que poseu cometes simples en l'argument, per ex.'ssl://mail'):<br />
ROUNDCUBE_DEFAULT_HOST=ssl://mail<br />
ROUNDCUBE_DEFAULT_PORT=993<br />
ROUNDCUBE_SMTP_SERVER=tls://mail<br />
ROUNDCUBE_SMTP_PORT=587<br />
<br />
Si, a més, voleu poder controlar els filtres d'email des del Roundcube, haureu de configurar:<br />
ROUNDCUBE_MANAGESIEVE_HOST=mail<br />
ROUNDCUBE_MANAGESIEVE_USETLS=true<br />
<br />
<br><br />
<br />
== Tunejant el servidor ==<br />
Per acabar de fer un sistema competent, necessitarem diversos ajustos:<br />
* Familiaritza't amb AMAVIS, el software que gestiona el antivirus i el anti-spam (spamassassin): <pre>https://help.ubuntu.com/community/PostfixAmavisNew</pre><br />
* Millora la detecció del anti-spam amb aquests consells: <pre>http://linux.kieser.net/salearn.html</pre><br />
<br />
<br><br />
<br />
== Seguretat en servei de correu electrònic ==<br />
La seguretat del nostre servei gira entorn de 3 eixos principals:<br />
# '''Exploits''': si el nostre servei és "petable" (per un bug o alguna operació maliciosa que explota una debilitat) el nostre sistema es pot fer vulnerable a intrusions. Per combatre això convé:<br />
#* Estar a la darrera versió del sistema operatiu (al menys en el parxes de seguretat) i del servei que fem servir.<br />
#* Utilitzar docker per aïllar parts del sistema. Si el procés de correu és vulnerable, una possible intrusió només podrà accedir als arxius de correu, i no a altres serveis.<br />
# '''Virus''': l'email és una gran porta d'entrada al sistema. Poden entrar virus i usuaris incautes poden introduir-los involuntàriament en el sistema. Calen diverses eines:<br />
#* Antivirus servidor: Clam / Amavis (incloses al docker-mailserver)<br />
#* Antivirus PC client: Avast, Panda, .<br />
# '''SPAM''': el maldecap més gran per a la implantació d'un servidor de correu. Ens calen 2 tipus d'eines:<br />
#* SpamAssassin : ens permet filtrar els ''spam'' a la nostra ''inbox'' (inclòs al docker-mailserver). Sol aprendre sol en base a algorismes heurístics, però té algunes comandes per "ensenyar-lo" i apuntar-li quins son els autèntics SPAM. Tenir [https://es.wikipedia.org/wiki/Honeypot un '''''honeypot''''' sol ser interessant] pel bon funcionament del server.<br />
#* Sistemes de signatura per validació i reputació del nostre servidor de correu<br />
<br />
=== Signatura, autenticitat i reputació dels nostres emails ===<br />
El SPAM (correu no sol·licitat o ''correu brossa'') és una de les grans dificultats per desplegar un servidor d'email. Al ser un sistema obert, on tothom pot enviar a qualsevol adreça, el perill de tenir la inbox inundada i fer el servei inutilitzable obliga a algun tipus de protecció per tal que el sistema sigui usable pels usuaris finals.<br />
<br />
Els grans proveidors de comptes de correu (Google, Hotmail, Yahoo) van idear certes mesures per assegurar l'origen dels emails, i impedir que qualsevol pugues enviar un email amb qualsevol remitent (cosa que d'entrada era i segueix sent possible). D'aquests sistemes, en destaquem aquests 3:<br />
* [https://es.wikipedia.org/wiki/DomainKeys_Identified_Mail DKIM]: bàsicament consisteix en signar tots els emails amb una clau privada, i presentar la clau pública al servidor DNS.<br />
* [https://returnpath.com/es/blog/como-explicar-dmarc-en-espanol-claro-y-conciso/ DMARC]<br />
* [https://es.wikipedia.org/wiki/Sender_Policy_Framework SPF]: similar a DKIM, inclourem certa informació als registres TXT del DNS, però en aquest cas per associar unes IPs concretes des de les que serà vàlid enviar els correus del nostre domini.<br />
<br />
Aquests mecanismes permeten als sistemes destinataris identificar si el correu que li arriba és bo. Si no quadra, la probabilitat de que sigui SPAM és molt alta i el filtra cap a la spam box.<br />
<br />
Pel docker-mailserver farem:<br />
* [https://github.com/tomav/docker-mailserver#generate-dkim-keys Configurar la signatura DKIM]. Les eines que disposa et crearan les claus públiques i privades, i t'indicaran com publicar la part pública dins un registre TXT del teu DNS.<br />
* [https://github.com/tomav/docker-mailserver/wiki/Configure-SPF Configurar SPF apuntant a la IP del teu servidor de e-mail].<br />
<br />
=== Comprovant la nostra reputació ===<br />
Utilitza aquesta eina per saber si has configurat correctament els diferents sistemes de signatura i validació d'autenticitat dels nostres emails.<br />
<br />
https://www.mail-tester.com/<br />
<br />
<br><br />
<br />
== Ampliacions possibles ==<br />
Si amb això no has tingut prou:<br />
# Activa el protocol POP3 i comprova-ho amb un client.<br />
# Activa FAIL2BAN tal i com s'explica a la web del contenidor, i comprova que funciona.<br />
#* Per defecte FAIL2BAN et baneja la teva IP durant 8 hores si falles 3 cops consecutius en un login.<br />
#* Modifica FAIL2BAN per canviar el paràmetre dels 3 errors i fer que siguin 10.<br />
# Utilitzant TELNET:<br />
#* Envia un email amb autenticació via SMTP + STARTSSL.<br />
#* Accedeix a llegir els missatges via IMAP sense encriptació.<br />
#* Accedeix a llegir els missatges via POP3 sense encriptació.<br />
# Troba la manera de canviar dinàmicament la contrasenya dels usuaris que tens al teu sistema dockeritzat. Algunes possibilitats:<br />
#* Explora la configuració amb un servidor LDAP. Pot ser-te d'utilitat l'article [[Servidor LDAP en Debian/Ubuntu]]<br />
#* Pots intentar fer-ho "a pèl":<br />
#**Investiga com fer-ho des de la pròpia línia de comandes del contenidor.<br />
#** Fes un script per canviar la contrasenya d'un usuari de forma interactiva.<br />
#** Fes una pàgina web que permeti modificar la contrasenya d'un compte.<br />
# Prova el mateix que hem fet fins ara per la creació o eliminació de comptes de forma dinàmica.<br />
# Investiga com fer un servidor "catch-all". Aquest [https://github.com/tomav/docker-mailserver/issues/516 issue del mateix creador del docker-mailserver] et servirà.<br />
# El servidor d'email té un mòdul per fer filtres d'emails anomenat SIEVE. El podem habilitar fent:<br />
#* Activant el MANAGESIEVE del mailserver<br />
#* Configurar el Roundcube com a interfície per a crear i editar els filtres del server. Caldrà afegir alguna variable d'entorn del Roundcube per activar-lo.<br />
# [http://serverfault.com/questions/484082/how-should-i-test-clam-anti-virus Testeja l'antivirus Clamav].<br />
<br />
<br><br />
<br />
== Troubleshooting ==<br />
Et poden donar problemes diverses coses:<br />
* Memòria virtual del servidor: si no la tens activada, és fàcil que l'antivirus del mailserver-docker peti i deixi de funcionar tot plegat. Consulta com afegir swap al teu AWS.<br />
* FAIL2BAN : el mòdul et prohibeix connectar-te a la teva màquina si ha fallat l'autenticació. Deshabilita FAIL2BAN en la conf del mailserver-docker<br />
* Paràmetres del client : <br />
* Emails van a SPAM: comprova la carpeta de spam del correu del destinatari, és molt fàcil que els envii allà.<br />
* Ports del teu servidor tancats: vigila els security-groups del teu AWS <br />
* No podem enviar correus amb el [https://scrum.ieti.cat/scrum/projecte/7#sprint-37 Amazon AWS: cal demanar que aixequin la restricció del port 25 del servidor].<br />
<br />
<br></div>Enrichttps://cacauet.org/wiki/index.php?title=E-mail_Linux_amb_Docker&diff=4215E-mail Linux amb Docker2020-12-10T18:25:59Z<p>Enric: /* Activant memòria virtual */</p>
<hr />
<div><br />
<nowiki>#FpInfor #Asix #AsixMp08 #AsixMp08Uf3 #AsixMp08Uf03 #Smx #SmxMp07 #SmxMp07Uf2 #SmxMp07Uf02</nowiki><br />
<br />
<br />
== Introducció ==<br />
El servei de [[correu electrònic]] és força complexe ja que es composa de diversos processos o ''daemons''. A part del típic servei de MTA (postfix, sendmail, etc.) ens cal també un servei de Fetchmail (Courier, Dovecot), antivirus, anti-spam, etc., a part de configurar els certificats i modes d'autenticació encriptada.<br />
<br />
El sistema de contenidors [[Docker]] ens facilita tota aquesta posada en marxa del servei. Bé, en concret Docker solament no, sinó algú que s'ha currat el sistema de correu complert i n'ha fet una versió ''dockeritzada''. Per poder fer aquesta pràctica cal que estiguis fortament familiaritzat amb [[Docker]].<br />
<br />
Farem aquesta pràctica '''en una màquina virtual Amazon AWS EC2'''. Si no has treballat amb elles mira't l'article [[AWS: Amazon Web Services]]. Això és per diversos motius:<br />
* Necessitem una IP fixa (les dinàmiques estan en una ''blacklist'' i els grans servidors com gmail o hotmail no ens permetran enviar-los emails). Les ''elastic IPs'' de AWS ens ho permetran.<br />
* Els instituts solen tenir limitades les connexions sortints de correu per evitar els spammers i accions de segons quins virus.<br />
<br />
<br><br />
<br />
== Posta en marxa del docker ==<br />
<br />
=== Prerequists: docker-compose ===<br />
En Ubuntu existeix el package docker-compose, però és una versió antiga i necessitem la versió més actual.<br />
<br />
Instal·la la darrera versió seguint aquestes explicacions:<br />
https://docs.docker.com/compose/install/<br />
<br />
=== Prerequisits: MX records ===<br />
El correu electrònic utilitza els '''registres MX''', enlloc dels habituals ''registres A'' en el nostre DNS server (del registrador del domini).<br />
<br />
Ves, doncs, al panell de control del teu registrador (.com o .tk) i crea un registre MX. Et demanarà que el reenviis cap a un domini definit en un registre A prèviament creat. Típicament la gent sol fer un registre A amb mail.elmeudomini.com i el MX sense subdomini el reenvia a aquest.<br />
<br />
=== Explorant imatges de Docker ===<br />
Per veure quines opcions tenim podem executar:<br />
$ docker search mail<br />
<br />
A mi m'ha funcionat prou bé la versió de Thomas Vial, que és la 1a que surt a la llista amb força "stars" (aka "likes"). Podeu trobar el codi aquí per tafanejar-lo:<br />
https://github.com/tomav/docker-mailserver<br />
<br />
=== Posta en marxa del mailserver ===<br />
Caldrà que coneguis '''docker-composer''' per posar en marxa el docker-mailserver.<br />
<br />
Segueix les instruccions que explica el desenvolupador en el README.<br />
<br />
IMPORTANT: modifiqueu els següents paràmetres del <code>docker-compose.yml</code><br />
# Deshabiliteu el mòdul FAIL2BAN, ja que per fer proves ens pot molestar. És un mòdul molt útil que prohibeix les IPs que fallen en la autenticació diverses vegades. Molt interessant per seguretat, però pot fastidiar-nos les proves. Canvieu la variable d'entorn:<pre> - ENABLE_FAIL2BAN=0</pre><br />
# Poseu els 2 volums <code>mailstate</code> i <code>maildata</code> com a directoris locals. És convenient per diversos motius:<br />
#* Permet fer persistents els arxius amb els correus dels usuaris<br />
#* Triga menys a arrencar el contenidor (ha de regenerar menys arxius)<br />
<br />
=== Creant comptes ===<br />
Abans que el nostre servidor sigui operatiu caldrà crear diversos comptes d'usuari. Per fer-los consulta el README del docker.<br />
<br />
Recorda que pots crear comptes de diferents dominis, fes-ne al menys de 2 dominis diferents.<br />
<br />
<br />
=== Activant memòria virtual ===<br />
Per algunes aplicacions podríem necessitar memòria virtual o swap, però les màquines EC2 inicialment no en porten. És el cas del docker-mailserver. El sistema pot fallar si no tenim prou RAM, 1 GB és molt just per a algunes aplicacions.<br />
<br />
[https://github.com/tomav/docker-mailserver/issues/6 Com explica aquest ''issue''], el ''spamd'' i/o el ''clamav'' fallen si tenim poca RAM.<br />
<br />
Utilitza aquest [https://www.digitalocean.com/community/tutorials/how-to-add-swap-on-ubuntu-14-04 tutorial per afegir memòria virtual a un EC2].<br />
<br />
Amb 1 GB n'hi ha prou, no afegiu més pq el disc dur és petit (8 GB) i si ens passem podem saturar-lo i fer que la màquina funcioni malament.<br />
<br />
<br><br />
<br />
=== Obrint ports a Amazon AWS ===<br />
Si ho realitzem sobre un servidor de Amazon AWS cal fer 2 coses:<br />
* Obrir el ports necessaris (25,993,465,587) al ''security group'' de la nostra instància.<br />
* [https://scrum.ieti.cat/scrum/projecte/7#sprint-37 Demanar a Amazon AWS que aixequin la restricció del port 25 de sortida del servidor]. Aquesta mesura va aparèixer fa uns anys per evitar que els servidors de AWS fessin spam, ja que això acaba per fer entrar les IPs de AWS en les blacklist de Spamhaus.<br />
<br />
<br><br />
<br />
== Accedint des de clients ==<br />
<br />
=== Test amb TELNET ===<br />
Podem enviar un missatge al nostre servidor, sempre i quan el destinatari sigui alguna bústia interna. Proveu d'accedir al port 25 del vostre servidor de forma externa, i feu un email tal i [https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol com explica l'apartat "SMTP transport example" de l'aritcle sobre SMTP de la Vikipèdia].<br />
<br />
D'aquesta manera podreu veure una mica més en detall com funcionen els ''internals'' del SMTP.<br />
<br />
Proveu també d'enviar un email a una adreça externa, i mostra a l'informe quin error et dona.<br />
<br />
Proveu també de fer el mateix des del propi servidor. Veureu que feu el telnet des de localhost podreu enviar emails on vulgueu, i no només a les adreces internes.<br />
<br />
=== Accedint via IMAPS ===<br />
Configura una aplicació client d'email (com Outlook, Thunderbird, etc.) per a accedir al teu servidor i llegir els correus via IMAPS. '''Es recomana fer-ho des d'una aplicació de correu per al mòbil, en concret Bluemail és força bona'''.<br />
<br />
Abans de res cal obrir els ports del servidor 993, 25, 587. Per testejar si el vostre servidor és accessible es recomana la comanda linux ''nmap'' per veure quins ports teniu oberts, per ex:<br />
$ nmap jolgorio.tk<br />
<br />
Starting Nmap 7.01 ( https://nmap.org ) at 2017-02-15 20:30 CET<br />
Nmap scan report for jolgorio.tk (54.229.49.51)<br />
Host is up (0.024s latency).<br />
rDNS record for 54.229.49.51: ec2-54-229-49-51.eu-west-1.compute.amazonaws.com<br />
Not shown: 992 filtered ports<br />
PORT STATE SERVICE<br />
22/tcp open ssh<br />
'''25/tcp open smtp'''<br />
80/tcp open http<br />
443/tcp open https<br />
465/tcp closed smtps<br />
'''587/tcp open submission'''<br />
'''993/tcp open imaps'''<br />
8081/tcp closed blackice-icecap<br />
<br />
Nmap done: 1 IP address (1 host up) scanned in 5.26 seconds<br />
<br />
És important accedir a través de la versió segura (IMAPS al port 993 i <strike>no al IMAP - port 143</strike>) per permetre la confidencialitat de la transferència de dades.<br />
<br />
Tingues en compte que al no tenir els certificats no la validació del SSL no serà correcta. Cal configurar la utilització del SSL sense verificació dels certificats.<br />
<br />
Resumint, la configuració del vostre client seria:<br />
* Correu entrant: IMAPS, port 993, SSL, Contrasenya simple, ometre comprovació de certificats<br />
* Correu sortint: SMTPS, port 587, STARTTLS, Contrasenya simple, ometre comprovació de certificats<br />
<br />
=== Webmail ===<br />
Busca una imatge Docker d'un software de webmail, instal·la-la en el teu servidor i configura-la perquè es connecti al servidor de correu que hem realitzat fins ara.<br />
<br />
Per alguns d'aquests softwares més sofisticats (com Roundcube) caldrà que instal·lis també una base de dades MySQL (guarda configuracions de la interfície, preferències d'usuari, etc.). Altres més senzills potser no la necessiten.<br />
<br />
Aquesta versió del Roundcube està muntada amb sqlite i no necessita tant setup com en el altres casos (per lligar-la amb mysql es fa més feixuc). L'únic inconvenient és que els settings desapareixen si reiniciem el contenidor, però pot ser un mal menor:<br />
https://hub.docker.com/r/robbertkl/roundcube/<br />
<br />
Si l'instal·leu a un VPS com el de Amazon AWS, us trobareu que haureu de publicar un port per veure el webmail. Però clar, accedir al nostre correu a través, per exemple de http://elmeudomini.com:9000 fa lleig. Solució:<br />
# Utilitzar un túnel SSH per accedir-hi i depurar el funcionament del webmail.<br />
# Visualitzar el roundcube en una URL principal (o sigui, del port 80 del domini). Tenim varies opcions:<br />
#* Activar el mòdul de proxy invers del Apache per visualitzar el webmail en una altra adreça com: <pre>http://elmeudomini.com/webmail</pre><br />
#* Fer un virtual server en un subdomini per accedir al webmail, per exemple: <pre>http://webmail.elmeudomini.com</pre><br />
<br />
En ambdós casos us caldrà activar el mòdul de proxy invers i connectar-se per túnel per depurar. [[Tomcat#Accés per túnel al manager|Aquest article ho explica]] (és pel Tomcat, però us servirà de forma molt similar).<br />
<br />
Per tal que el container del Roundcube funcioni, caldrà ajustar les següents variables (si ho feu amb docker-compose va tal qual, sense cometes; si ho feu des de docker a seques, cal que poseu cometes simples en l'argument, per ex.'ssl://mail'):<br />
ROUNDCUBE_DEFAULT_HOST=ssl://mail<br />
ROUNDCUBE_DEFAULT_PORT=993<br />
ROUNDCUBE_SMTP_SERVER=tls://mail<br />
ROUNDCUBE_SMTP_PORT=587<br />
<br />
Si, a més, voleu poder controlar els filtres d'email des del Roundcube, haureu de configurar:<br />
ROUNDCUBE_MANAGESIEVE_HOST=mail<br />
ROUNDCUBE_MANAGESIEVE_USETLS=true<br />
<br />
<br><br />
<br />
== Tunejant el servidor ==<br />
Per acabar de fer un sistema competent, necessitarem diversos ajustos:<br />
* Familiaritza't amb AMAVIS, el software que gestiona el antivirus i el anti-spam (spamassassin): <pre>https://help.ubuntu.com/community/PostfixAmavisNew</pre><br />
* Millora la detecció del anti-spam amb aquests consells: <pre>http://linux.kieser.net/salearn.html</pre><br />
<br />
<br><br />
<br />
== Seguretat en servei de correu electrònic ==<br />
La seguretat del nostre servei gira entorn de 3 eixos principals:<br />
# '''Exploits''': si el nostre servei és "petable" (per un bug o alguna operació maliciosa que explota una debilitat) el nostre sistema es pot fer vulnerable a intrusions. Per combatre això convé:<br />
#* Estar a la darrera versió del sistema operatiu (al menys en el parxes de seguretat) i del servei que fem servir.<br />
#* Utilitzar docker per aïllar parts del sistema. Si el procés de correu és vulnerable, una possible intrusió només podrà accedir als arxius de correu, i no a altres serveis.<br />
# '''Virus''': l'email és una gran porta d'entrada al sistema. Poden entrar virus i usuaris incautes poden introduir-los involuntàriament en el sistema. Calen diverses eines:<br />
#* Antivirus servidor: Clam / Amavis (incloses al docker-mailserver)<br />
#* Antivirus PC client: Avast, Panda, .<br />
# '''SPAM''': el maldecap més gran per a la implantació d'un servidor de correu. Ens calen 2 tipus d'eines:<br />
#* SpamAssassin : ens permet filtrar els ''spam'' a la nostra ''inbox'' (inclòs al docker-mailserver). Sol aprendre sol en base a algorismes heurístics, però té algunes comandes per "ensenyar-lo" i apuntar-li quins son els autèntics SPAM. Tenir [https://es.wikipedia.org/wiki/Honeypot un '''''honeypot''''' sol ser interessant] pel bon funcionament del server.<br />
#* Sistemes de signatura per validació i reputació del nostre servidor de correu<br />
<br />
=== Signatura, autenticitat i reputació dels nostres emails ===<br />
El SPAM (correu no sol·licitat o ''correu brossa'') és una de les grans dificultats per desplegar un servidor d'email. Al ser un sistema obert, on tothom pot enviar a qualsevol adreça, el perill de tenir la inbox inundada i fer el servei inutilitzable obliga a algun tipus de protecció per tal que el sistema sigui usable pels usuaris finals.<br />
<br />
Els grans proveidors de comptes de correu (Google, Hotmail, Yahoo) van idear certes mesures per assegurar l'origen dels emails, i impedir que qualsevol pugues enviar un email amb qualsevol remitent (cosa que d'entrada era i segueix sent possible). D'aquests sistemes, en destaquem aquests 3:<br />
* [https://es.wikipedia.org/wiki/DomainKeys_Identified_Mail DKIM]: bàsicament consisteix en signar tots els emails amb una clau privada, i presentar la clau pública al servidor DNS.<br />
* [https://returnpath.com/es/blog/como-explicar-dmarc-en-espanol-claro-y-conciso/ DMARC]<br />
* [https://es.wikipedia.org/wiki/Sender_Policy_Framework SPF]: similar a DKIM, inclourem certa informació als registres TXT del DNS, però en aquest cas per associar unes IPs concretes des de les que serà vàlid enviar els correus del nostre domini.<br />
<br />
Aquests mecanismes permeten als sistemes destinataris identificar si el correu que li arriba és bo. Si no quadra, la probabilitat de que sigui SPAM és molt alta i el filtra cap a la spam box.<br />
<br />
Pel docker-mailserver farem:<br />
* [https://github.com/tomav/docker-mailserver#generate-dkim-keys Configurar la signatura DKIM]. Les eines que disposa et crearan les claus públiques i privades, i t'indicaran com publicar la part pública dins un registre TXT del teu DNS.<br />
* [https://github.com/tomav/docker-mailserver/wiki/Configure-SPF Configurar SPF apuntant a la IP del teu servidor de e-mail].<br />
<br />
=== Comprovant la nostra reputació ===<br />
Utilitza aquesta eina per saber si has configurat correctament els diferents sistemes de signatura i validació d'autenticitat dels nostres emails.<br />
<br />
https://www.mail-tester.com/<br />
<br />
<br><br />
<br />
== Ampliacions possibles ==<br />
Si amb això no has tingut prou:<br />
# Activa el protocol POP3 i comprova-ho amb un client.<br />
# Activa FAIL2BAN tal i com s'explica a la web del contenidor, i comprova que funciona.<br />
#* Per defecte FAIL2BAN et baneja la teva IP durant 8 hores si falles 3 cops consecutius en un login.<br />
#* Modifica FAIL2BAN per canviar el paràmetre dels 3 errors i fer que siguin 10.<br />
# Utilitzant TELNET:<br />
#* Envia un email amb autenticació via SMTP + STARTSSL.<br />
#* Accedeix a llegir els missatges via IMAP sense encriptació.<br />
#* Accedeix a llegir els missatges via POP3 sense encriptació.<br />
# Troba la manera de canviar dinàmicament la contrasenya dels usuaris que tens al teu sistema dockeritzat. Algunes possibilitats:<br />
#* Explora la configuració amb un servidor LDAP. Pot ser-te d'utilitat l'article [[Servidor LDAP en Debian/Ubuntu]]<br />
#* Pots intentar fer-ho "a pèl":<br />
#**Investiga com fer-ho des de la pròpia línia de comandes del contenidor.<br />
#** Fes un script per canviar la contrasenya d'un usuari de forma interactiva.<br />
#** Fes una pàgina web que permeti modificar la contrasenya d'un compte.<br />
# Prova el mateix que hem fet fins ara per la creació o eliminació de comptes de forma dinàmica.<br />
# Investiga com fer un servidor "catch-all". Aquest [https://github.com/tomav/docker-mailserver/issues/516 issue del mateix creador del docker-mailserver] et servirà.<br />
# El servidor d'email té un mòdul per fer filtres d'emails anomenat SIEVE. El podem habilitar fent:<br />
#* Activant el MANAGESIEVE del mailserver<br />
#* Configurar el Roundcube com a interfície per a crear i editar els filtres del server. Caldrà afegir alguna variable d'entorn del Roundcube per activar-lo.<br />
# [http://serverfault.com/questions/484082/how-should-i-test-clam-anti-virus Testeja l'antivirus Clamav].<br />
<br />
<br><br />
<br />
== Troubleshooting ==<br />
Et poden donar problemes diverses coses:<br />
* Memòria virtual del servidor: si no la tens activada, és fàcil que l'antivirus del mailserver-docker peti i deixi de funcionar tot plegat. Consulta com afegir swap al teu AWS.<br />
* FAIL2BAN : el mòdul et prohibeix connectar-te a la teva màquina si ha fallat l'autenticació. Deshabilita FAIL2BAN en la conf del mailserver-docker<br />
* Paràmetres del client : <br />
* Emails van a SPAM: comprova la carpeta de spam del correu del destinatari, és molt fàcil que els envii allà.<br />
* Ports del teu servidor tancats: vigila els security-groups del teu AWS <br />
* No podem enviar correus amb el [https://scrum.ieti.cat/scrum/projecte/7#sprint-37 Amazon AWS: cal demanar que aixequin la restricció del port 25 del servidor].<br />
<br />
<br></div>Enrichttps://cacauet.org/wiki/index.php?title=E-mail_Linux_amb_Docker&diff=4214E-mail Linux amb Docker2020-12-10T18:21:56Z<p>Enric: /* Troubleshooting */</p>
<hr />
<div><br />
<nowiki>#FpInfor #Asix #AsixMp08 #AsixMp08Uf3 #AsixMp08Uf03 #Smx #SmxMp07 #SmxMp07Uf2 #SmxMp07Uf02</nowiki><br />
<br />
<br />
== Introducció ==<br />
El servei de [[correu electrònic]] és força complexe ja que es composa de diversos processos o ''daemons''. A part del típic servei de MTA (postfix, sendmail, etc.) ens cal també un servei de Fetchmail (Courier, Dovecot), antivirus, anti-spam, etc., a part de configurar els certificats i modes d'autenticació encriptada.<br />
<br />
El sistema de contenidors [[Docker]] ens facilita tota aquesta posada en marxa del servei. Bé, en concret Docker solament no, sinó algú que s'ha currat el sistema de correu complert i n'ha fet una versió ''dockeritzada''. Per poder fer aquesta pràctica cal que estiguis fortament familiaritzat amb [[Docker]].<br />
<br />
Farem aquesta pràctica '''en una màquina virtual Amazon AWS EC2'''. Si no has treballat amb elles mira't l'article [[AWS: Amazon Web Services]]. Això és per diversos motius:<br />
* Necessitem una IP fixa (les dinàmiques estan en una ''blacklist'' i els grans servidors com gmail o hotmail no ens permetran enviar-los emails). Les ''elastic IPs'' de AWS ens ho permetran.<br />
* Els instituts solen tenir limitades les connexions sortints de correu per evitar els spammers i accions de segons quins virus.<br />
<br />
<br><br />
<br />
== Posta en marxa del docker ==<br />
<br />
=== Prerequists: docker-compose ===<br />
En Ubuntu existeix el package docker-compose, però és una versió antiga i necessitem la versió més actual.<br />
<br />
Instal·la la darrera versió seguint aquestes explicacions:<br />
https://docs.docker.com/compose/install/<br />
<br />
=== Prerequisits: MX records ===<br />
El correu electrònic utilitza els '''registres MX''', enlloc dels habituals ''registres A'' en el nostre DNS server (del registrador del domini).<br />
<br />
Ves, doncs, al panell de control del teu registrador (.com o .tk) i crea un registre MX. Et demanarà que el reenviis cap a un domini definit en un registre A prèviament creat. Típicament la gent sol fer un registre A amb mail.elmeudomini.com i el MX sense subdomini el reenvia a aquest.<br />
<br />
=== Explorant imatges de Docker ===<br />
Per veure quines opcions tenim podem executar:<br />
$ docker search mail<br />
<br />
A mi m'ha funcionat prou bé la versió de Thomas Vial, que és la 1a que surt a la llista amb força "stars" (aka "likes"). Podeu trobar el codi aquí per tafanejar-lo:<br />
https://github.com/tomav/docker-mailserver<br />
<br />
=== Posta en marxa del mailserver ===<br />
Caldrà que coneguis '''docker-composer''' per posar en marxa el docker-mailserver.<br />
<br />
Segueix les instruccions que explica el desenvolupador en el README.<br />
<br />
IMPORTANT: modifiqueu els següents paràmetres del <code>docker-compose.yml</code><br />
# Deshabiliteu el mòdul FAIL2BAN, ja que per fer proves ens pot molestar. És un mòdul molt útil que prohibeix les IPs que fallen en la autenticació diverses vegades. Molt interessant per seguretat, però pot fastidiar-nos les proves. Canvieu la variable d'entorn:<pre> - ENABLE_FAIL2BAN=0</pre><br />
# Poseu els 2 volums <code>mailstate</code> i <code>maildata</code> com a directoris locals. És convenient per diversos motius:<br />
#* Permet fer persistents els arxius amb els correus dels usuaris<br />
#* Triga menys a arrencar el contenidor (ha de regenerar menys arxius)<br />
<br />
=== Creant comptes ===<br />
Abans que el nostre servidor sigui operatiu caldrà crear diversos comptes d'usuari. Per fer-los consulta el README del docker.<br />
<br />
Recorda que pots crear comptes de diferents dominis, fes-ne al menys de 2 dominis diferents.<br />
<br />
<br />
=== Activant memòria virtual ===<br />
Per algunes aplicacions podríem necessitar memòria virtual o swap, però les màquines EC2 inicialment no en porten. És el cas del docker-mailserver. El sistema pot fallar si no tenim prou RAM, 1 GB és molt just per a algunes aplicacions.<br />
<br />
[https://github.com/tomav/docker-mailserver/issues/6 Com explica aquest ''issue''], el ''spamd'' i/o el ''clamav'' fallen si tenim poca RAM.<br />
<br />
Utilitza aquest [https://www.digitalocean.com/community/tutorials/how-to-add-swap-on-ubuntu-14-04 tutorial per afegir memòria virtual a un EC2].<br />
<br />
Amb 1 GB n'hi ha prou, no afegiu més pq el disc dur és petit (8 GB) i si ens passem podem saturar-lo i fer que la màquina funcioni malament.<br />
<br />
<br><br />
<br />
== Accedint des de clients ==<br />
<br />
=== Test amb TELNET ===<br />
Podem enviar un missatge al nostre servidor, sempre i quan el destinatari sigui alguna bústia interna. Proveu d'accedir al port 25 del vostre servidor de forma externa, i feu un email tal i [https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol com explica l'apartat "SMTP transport example" de l'aritcle sobre SMTP de la Vikipèdia].<br />
<br />
D'aquesta manera podreu veure una mica més en detall com funcionen els ''internals'' del SMTP.<br />
<br />
Proveu també d'enviar un email a una adreça externa, i mostra a l'informe quin error et dona.<br />
<br />
Proveu també de fer el mateix des del propi servidor. Veureu que feu el telnet des de localhost podreu enviar emails on vulgueu, i no només a les adreces internes.<br />
<br />
=== Accedint via IMAPS ===<br />
Configura una aplicació client d'email (com Outlook, Thunderbird, etc.) per a accedir al teu servidor i llegir els correus via IMAPS. '''Es recomana fer-ho des d'una aplicació de correu per al mòbil, en concret Bluemail és força bona'''.<br />
<br />
Abans de res cal obrir els ports del servidor 993, 25, 587. Per testejar si el vostre servidor és accessible es recomana la comanda linux ''nmap'' per veure quins ports teniu oberts, per ex:<br />
$ nmap jolgorio.tk<br />
<br />
Starting Nmap 7.01 ( https://nmap.org ) at 2017-02-15 20:30 CET<br />
Nmap scan report for jolgorio.tk (54.229.49.51)<br />
Host is up (0.024s latency).<br />
rDNS record for 54.229.49.51: ec2-54-229-49-51.eu-west-1.compute.amazonaws.com<br />
Not shown: 992 filtered ports<br />
PORT STATE SERVICE<br />
22/tcp open ssh<br />
'''25/tcp open smtp'''<br />
80/tcp open http<br />
443/tcp open https<br />
465/tcp closed smtps<br />
'''587/tcp open submission'''<br />
'''993/tcp open imaps'''<br />
8081/tcp closed blackice-icecap<br />
<br />
Nmap done: 1 IP address (1 host up) scanned in 5.26 seconds<br />
<br />
És important accedir a través de la versió segura (IMAPS al port 993 i <strike>no al IMAP - port 143</strike>) per permetre la confidencialitat de la transferència de dades.<br />
<br />
Tingues en compte que al no tenir els certificats no la validació del SSL no serà correcta. Cal configurar la utilització del SSL sense verificació dels certificats.<br />
<br />
Resumint, la configuració del vostre client seria:<br />
* Correu entrant: IMAPS, port 993, SSL, Contrasenya simple, ometre comprovació de certificats<br />
* Correu sortint: SMTPS, port 587, STARTTLS, Contrasenya simple, ometre comprovació de certificats<br />
<br />
=== Webmail ===<br />
Busca una imatge Docker d'un software de webmail, instal·la-la en el teu servidor i configura-la perquè es connecti al servidor de correu que hem realitzat fins ara.<br />
<br />
Per alguns d'aquests softwares més sofisticats (com Roundcube) caldrà que instal·lis també una base de dades MySQL (guarda configuracions de la interfície, preferències d'usuari, etc.). Altres més senzills potser no la necessiten.<br />
<br />
Aquesta versió del Roundcube està muntada amb sqlite i no necessita tant setup com en el altres casos (per lligar-la amb mysql es fa més feixuc). L'únic inconvenient és que els settings desapareixen si reiniciem el contenidor, però pot ser un mal menor:<br />
https://hub.docker.com/r/robbertkl/roundcube/<br />
<br />
Si l'instal·leu a un VPS com el de Amazon AWS, us trobareu que haureu de publicar un port per veure el webmail. Però clar, accedir al nostre correu a través, per exemple de http://elmeudomini.com:9000 fa lleig. Solució:<br />
# Utilitzar un túnel SSH per accedir-hi i depurar el funcionament del webmail.<br />
# Visualitzar el roundcube en una URL principal (o sigui, del port 80 del domini). Tenim varies opcions:<br />
#* Activar el mòdul de proxy invers del Apache per visualitzar el webmail en una altra adreça com: <pre>http://elmeudomini.com/webmail</pre><br />
#* Fer un virtual server en un subdomini per accedir al webmail, per exemple: <pre>http://webmail.elmeudomini.com</pre><br />
<br />
En ambdós casos us caldrà activar el mòdul de proxy invers i connectar-se per túnel per depurar. [[Tomcat#Accés per túnel al manager|Aquest article ho explica]] (és pel Tomcat, però us servirà de forma molt similar).<br />
<br />
Per tal que el container del Roundcube funcioni, caldrà ajustar les següents variables (si ho feu amb docker-compose va tal qual, sense cometes; si ho feu des de docker a seques, cal que poseu cometes simples en l'argument, per ex.'ssl://mail'):<br />
ROUNDCUBE_DEFAULT_HOST=ssl://mail<br />
ROUNDCUBE_DEFAULT_PORT=993<br />
ROUNDCUBE_SMTP_SERVER=tls://mail<br />
ROUNDCUBE_SMTP_PORT=587<br />
<br />
Si, a més, voleu poder controlar els filtres d'email des del Roundcube, haureu de configurar:<br />
ROUNDCUBE_MANAGESIEVE_HOST=mail<br />
ROUNDCUBE_MANAGESIEVE_USETLS=true<br />
<br />
<br><br />
<br />
== Tunejant el servidor ==<br />
Per acabar de fer un sistema competent, necessitarem diversos ajustos:<br />
* Familiaritza't amb AMAVIS, el software que gestiona el antivirus i el anti-spam (spamassassin): <pre>https://help.ubuntu.com/community/PostfixAmavisNew</pre><br />
* Millora la detecció del anti-spam amb aquests consells: <pre>http://linux.kieser.net/salearn.html</pre><br />
<br />
<br><br />
<br />
== Seguretat en servei de correu electrònic ==<br />
La seguretat del nostre servei gira entorn de 3 eixos principals:<br />
# '''Exploits''': si el nostre servei és "petable" (per un bug o alguna operació maliciosa que explota una debilitat) el nostre sistema es pot fer vulnerable a intrusions. Per combatre això convé:<br />
#* Estar a la darrera versió del sistema operatiu (al menys en el parxes de seguretat) i del servei que fem servir.<br />
#* Utilitzar docker per aïllar parts del sistema. Si el procés de correu és vulnerable, una possible intrusió només podrà accedir als arxius de correu, i no a altres serveis.<br />
# '''Virus''': l'email és una gran porta d'entrada al sistema. Poden entrar virus i usuaris incautes poden introduir-los involuntàriament en el sistema. Calen diverses eines:<br />
#* Antivirus servidor: Clam / Amavis (incloses al docker-mailserver)<br />
#* Antivirus PC client: Avast, Panda, .<br />
# '''SPAM''': el maldecap més gran per a la implantació d'un servidor de correu. Ens calen 2 tipus d'eines:<br />
#* SpamAssassin : ens permet filtrar els ''spam'' a la nostra ''inbox'' (inclòs al docker-mailserver). Sol aprendre sol en base a algorismes heurístics, però té algunes comandes per "ensenyar-lo" i apuntar-li quins son els autèntics SPAM. Tenir [https://es.wikipedia.org/wiki/Honeypot un '''''honeypot''''' sol ser interessant] pel bon funcionament del server.<br />
#* Sistemes de signatura per validació i reputació del nostre servidor de correu<br />
<br />
=== Signatura, autenticitat i reputació dels nostres emails ===<br />
El SPAM (correu no sol·licitat o ''correu brossa'') és una de les grans dificultats per desplegar un servidor d'email. Al ser un sistema obert, on tothom pot enviar a qualsevol adreça, el perill de tenir la inbox inundada i fer el servei inutilitzable obliga a algun tipus de protecció per tal que el sistema sigui usable pels usuaris finals.<br />
<br />
Els grans proveidors de comptes de correu (Google, Hotmail, Yahoo) van idear certes mesures per assegurar l'origen dels emails, i impedir que qualsevol pugues enviar un email amb qualsevol remitent (cosa que d'entrada era i segueix sent possible). D'aquests sistemes, en destaquem aquests 3:<br />
* [https://es.wikipedia.org/wiki/DomainKeys_Identified_Mail DKIM]: bàsicament consisteix en signar tots els emails amb una clau privada, i presentar la clau pública al servidor DNS.<br />
* [https://returnpath.com/es/blog/como-explicar-dmarc-en-espanol-claro-y-conciso/ DMARC]<br />
* [https://es.wikipedia.org/wiki/Sender_Policy_Framework SPF]: similar a DKIM, inclourem certa informació als registres TXT del DNS, però en aquest cas per associar unes IPs concretes des de les que serà vàlid enviar els correus del nostre domini.<br />
<br />
Aquests mecanismes permeten als sistemes destinataris identificar si el correu que li arriba és bo. Si no quadra, la probabilitat de que sigui SPAM és molt alta i el filtra cap a la spam box.<br />
<br />
Pel docker-mailserver farem:<br />
* [https://github.com/tomav/docker-mailserver#generate-dkim-keys Configurar la signatura DKIM]. Les eines que disposa et crearan les claus públiques i privades, i t'indicaran com publicar la part pública dins un registre TXT del teu DNS.<br />
* [https://github.com/tomav/docker-mailserver/wiki/Configure-SPF Configurar SPF apuntant a la IP del teu servidor de e-mail].<br />
<br />
=== Comprovant la nostra reputació ===<br />
Utilitza aquesta eina per saber si has configurat correctament els diferents sistemes de signatura i validació d'autenticitat dels nostres emails.<br />
<br />
https://www.mail-tester.com/<br />
<br />
<br><br />
<br />
== Ampliacions possibles ==<br />
Si amb això no has tingut prou:<br />
# Activa el protocol POP3 i comprova-ho amb un client.<br />
# Activa FAIL2BAN tal i com s'explica a la web del contenidor, i comprova que funciona.<br />
#* Per defecte FAIL2BAN et baneja la teva IP durant 8 hores si falles 3 cops consecutius en un login.<br />
#* Modifica FAIL2BAN per canviar el paràmetre dels 3 errors i fer que siguin 10.<br />
# Utilitzant TELNET:<br />
#* Envia un email amb autenticació via SMTP + STARTSSL.<br />
#* Accedeix a llegir els missatges via IMAP sense encriptació.<br />
#* Accedeix a llegir els missatges via POP3 sense encriptació.<br />
# Troba la manera de canviar dinàmicament la contrasenya dels usuaris que tens al teu sistema dockeritzat. Algunes possibilitats:<br />
#* Explora la configuració amb un servidor LDAP. Pot ser-te d'utilitat l'article [[Servidor LDAP en Debian/Ubuntu]]<br />
#* Pots intentar fer-ho "a pèl":<br />
#**Investiga com fer-ho des de la pròpia línia de comandes del contenidor.<br />
#** Fes un script per canviar la contrasenya d'un usuari de forma interactiva.<br />
#** Fes una pàgina web que permeti modificar la contrasenya d'un compte.<br />
# Prova el mateix que hem fet fins ara per la creació o eliminació de comptes de forma dinàmica.<br />
# Investiga com fer un servidor "catch-all". Aquest [https://github.com/tomav/docker-mailserver/issues/516 issue del mateix creador del docker-mailserver] et servirà.<br />
# El servidor d'email té un mòdul per fer filtres d'emails anomenat SIEVE. El podem habilitar fent:<br />
#* Activant el MANAGESIEVE del mailserver<br />
#* Configurar el Roundcube com a interfície per a crear i editar els filtres del server. Caldrà afegir alguna variable d'entorn del Roundcube per activar-lo.<br />
# [http://serverfault.com/questions/484082/how-should-i-test-clam-anti-virus Testeja l'antivirus Clamav].<br />
<br />
<br><br />
<br />
== Troubleshooting ==<br />
Et poden donar problemes diverses coses:<br />
* Memòria virtual del servidor: si no la tens activada, és fàcil que l'antivirus del mailserver-docker peti i deixi de funcionar tot plegat. Consulta com afegir swap al teu AWS.<br />
* FAIL2BAN : el mòdul et prohibeix connectar-te a la teva màquina si ha fallat l'autenticació. Deshabilita FAIL2BAN en la conf del mailserver-docker<br />
* Paràmetres del client : <br />
* Emails van a SPAM: comprova la carpeta de spam del correu del destinatari, és molt fàcil que els envii allà.<br />
* Ports del teu servidor tancats: vigila els security-groups del teu AWS <br />
* No podem enviar correus amb el [https://scrum.ieti.cat/scrum/projecte/7#sprint-37 Amazon AWS: cal demanar que aixequin la restricció del port 25 del servidor].<br />
<br />
<br></div>Enrichttps://cacauet.org/wiki/index.php?title=Correu_electr%C3%B2nic&diff=4213Correu electrònic2020-12-10T17:58:52Z<p>Enric: /* Requisits per tenir un servidor d'email */</p>
<hr />
<div>Correu electrònic o e-mail.<br />
<br />
== Introducció ==<br />
Segons la Wikipèdia: ''"El correu electrònic o a vegades, correu-e (anomenat en anglès e-mail, o email) es refereix al sistema que permet redactar, enviar i rebre missatges o cartes (missives, lletres) utilitzant sistemes de comunicació electrònica. També s'hi poden adjuntar documents electrònics o altres fitxers."''<br />
<br />
Enllaç a "E-mail" o "Correu electrònic": http://ca.wikipedia.org/wiki/Correu_electr%C3%B2nic<br />
<br />
<br />
== Servidors de correu electrònic ==<br />
<br />
[[Fitxer:Teoria.email1.png|700px]]<br />
<br />
Diferents parts del servidor de correu:<br />
* '''MTA''': [http://en.wikipedia.org/wiki/Message_transfer_agent Message Transfer Agent] o també "Mail Transfer Agent" (valen els dos). El propi programa de SERVIDOR correu:<br />
** GNU/Linux:<br />
*** [[Sendmail]]<br />
*** [[Postfix]]<br />
*** [[Exim]]<br />
** Windows:<br />
*** [[Microsoft Exchange]]<br />
* '''MUA:''' [http://en.wikipedia.org/wiki/Mail_user_agent Mail User Agent]. El programa que utilitza el client.<br />
** GNU/Linux: Thunderbird, Evolution<br />
** Windows: Thunderbird, Outlook<br />
* '''MDA: Mail Delivery Agent'''. Programa intermig per filtrar SPAM, seleccionar usuari, etc.<br />
* '''Mailbox''': Arxius de disc on es guarden els missatges i ''attachments''.<br />
* '''Fetchmail''': programa que actua d'interfície amb el client (MUA) mitjançant els protocols POP i IMAP (entre d'altres).<br />
<br />
<br><br />
<br />
== Protocols implicats ==<br />
* '''SMTP: Simple Mail Transfer Protocol'''. Utilitza diversos ports:<br />
** Port 25: enviament de correus entre servidors.<br />
** Port 587 (submission) o 465 (no-standard): port per a enviament de correus per part de clients.<br />
* '''POP3: Post Office Protocol'''. (Port 110)<br />
* '''IMAP: Internet Message Access Protocol'''. (Port 143)<br />
* '''IMAPS''': IMAP over SSL (Port 993)<br />
* '''POP3S''': POP3 over SSL (port 995)<br />
<br />
<br><br />
<br />
== Seguretat ==<br />
La seguretat en els emails depèn de diversos factors a solucionar:<br />
* '''Autenticació''': l'usuari que vol accedir<br />
* '''[[Encriptació]]''': mitjançant la [[encriptació]] assegurem que la conversa serà confidencial, és a dir, que si algun intrús la escolta no podrà llegir-la (no podrà desencriptar-la).<br />
** SSL: Secure-Sockets Layer o "capa de sockets segurs". Per poder implementar-la cal un port a part que disposi d'aquesta capa de seguretat de bon principi.<br />
** STARTTLS: També conegut per "[https://en.wikipedia.org/wiki/Opportunistic_TLS TLS oportunístic]". Ens permet canviar a una versió segura "sobre la marxa" dins d'un protocol no segur inicialment. D'aquesta manera es pot reutilitzar el port original afegint-li algun ''middleware'' que encripti i desencripti.<br />
* '''Certificats''': amb els certificats, una empresa externa confiable (Verisign, etc.) dóna fe que qui estem contactant és qui diu ser. Per tant, en aquest procés no només intervindrà la nostra configuració, sinó que el client consultarà a la CA (Certification Authority) si el nostre site és de confiança.<br />
<br />
<br><br />
<br />
== Webmail ==<br />
En el cas del webmail al client nomé li cal un navegador o ''browser''. El servidor web es connecta amb el servidor d'email mitjançant els protocols estàndards (o d'altres) i serveix al client en forma de HTML (mitjançant el protocol HTTP o HTTPS).<br />
<br />
[[Fitxer:webmail.png|700px]]<br />
<br />
<br />
== Requisits per tenir un servidor d'email ==<br />
Diverses forces adverses es conjuren per no deixar-nos tenir un servidor d'email. És degut a les mesures de seguretat que posen tots els servidors als ''spammers''.<br />
<br />
Per poder tenir un servidor d'email funcionant heu d'assegurar-vos que:<br />
* Teniu una '''IP fixa''', és a dir, no val la típica IP dinàmica del ADSL. Això ens ho subministra el nostre ISP (vomistar, polafone, etc.) i cal pagar una quota mensual per tenir-la (abans era més raonable, ara resulta molt cara, entorn els 15€+IVA).<br />
* No hi ha un ''proxy'' que us tanqui el port 25 de sortida. A casa no sol passar, però als instituts i a moltes institucions ho fan per evitar spammers i així evitar que posin la IP del centre a llistes negres (recordem que tots sortim amb la mateixa IP pel NAT).<br />
** El efecte colateral del proxy que tenca el port 25 és que NO podem utilitzar cap client de correu sortint com el Thunderbird o Outlook (tot i que el correu entrant sí que funciona perquè va pels ports del POP i IMAP).<br />
* La nostra '''IP no està en una llista negra'''. Per comprovar-ho podeu anar aquí:<pre>https://www.spamhaus.org/lookup/</pre><br />
** En cas que la tingueu en una ''blacklist'' seguiu les instruccions de la web per (a) treure-la de la llista i (b) evitar que us la tornin a posar (típicament passa quan hi ha màquines dintre de la organització que envien ''spam'' per algun virus).<br />
* Si esteu fent servir [https://aws.amazon.com/premiumsupport/knowledge-center/ec2-port-25-throttle/ Amazon AWS, caldrà que desactiveu la restricció del port 25 de sortida d'emails].<br />
<br />
<br><br />
<br />
== Seguretat en servei de correu electrònic ==<br />
La seguretat del nostre servei gira entorn de 3 eixos principals:<br />
# '''Exploits''': si el nostre servei és "petable" (per un bug o alguna operació maliciosa que explota una debilitat) el nostre sistema es pot fer vulnerable a intrusions. Per combatre això convé:<br />
#* Estar a la darrera versió del sistema operatiu (al menys en el parxes de seguretat) i del servei que fem servir.<br />
#* Utilitzar docker per aïllar parts del sistema. Si el procés de correu és vulnerable, una possible intrusió només podrà accedir als arxius de correu, i no a altres serveis.<br />
# '''Virus''': l'email és una gran porta d'entrada al sistema. Poden entrar virus i usuaris incautes poden introduir-los involuntàriament en el sistema. Calen diverses eines:<br />
#* Antivirus servidor: Clam / Amavis (incloses al docker-mailserver)<br />
#* Antivirus PC client: Avast, Panda, .<br />
# '''SPAM''': el maldecap més gran per a la implantació d'un servidor de correu. Ens calen 2 tipus d'eines:<br />
#* SpamAssassin : ens permet filtrar els ''spam'' a la nostra ''inbox'' (inclòs al docker-mailserver). Sol aprendre sol en base a algorismes heurístics, però té algunes comandes per "ensenyar-lo" i apuntar-li quins son els autèntics SPAM. Tenir [https://es.wikipedia.org/wiki/Honeypot un '''''honeypot''''' sol ser interessant] pel bon funcionament del server.<br />
#* Sistemes de signatura per validació i reputació del nostre servidor de correu<br />
<br />
=== Signatura, autenticitat i reputació dels nostres emails ===<br />
El SPAM (correu no sol·licitat o ''correu brossa'') és una de les grans dificultats per desplegar un servidor d'email. Al ser un sistema obert, on tothom pot enviar a qualsevol adreça, el perill de tenir la inbox inundada i fer el servei inutilitzable obliga a algun tipus de protecció per tal que el sistema sigui usable pels usuaris finals.<br />
<br />
Els grans proveidors de comptes de correu (Google, Hotmail, Yahoo) van idear certes mesures per assegurar l'origen dels emails, i impedir que qualsevol pugues enviar un email amb qualsevol remitent (cosa que d'entrada era i segueix sent possible). D'aquests sistemes, en destaquem aquests 3:<br />
* [https://es.wikipedia.org/wiki/DomainKeys_Identified_Mail DKIM]: bàsicament consisteix en signar tots els emails amb una clau privada, i presentar la clau pública al servidor DNS.<br />
* [https://returnpath.com/es/blog/como-explicar-dmarc-en-espanol-claro-y-conciso/ DMARC]<br />
* [https://es.wikipedia.org/wiki/Sender_Policy_Framework SPF]: similar a DKIM, inclourem certa informació als registres TXT del DNS, però en aquest cas per associar unes IPs concretes des de les que serà vàlid enviar els correus del nostre domini.<br />
<br />
Aquests mecanismes permeten als sistemes destinataris identificar si el correu que li arriba és bo. Si no quadra, la probabilitat de que sigui SPAM és molt alta i el filtra cap a la spam box.<br />
<br />
=== Comprovant la nostra reputació ===<br />
Utilitza aquesta eina per saber si has configurat correctament els diferents sistemes de signatura i validació d'autenticitat dels nostres emails.<br />
<br />
https://www.mail-tester.com/<br />
<br />
<br></div>Enrichttps://cacauet.org/wiki/index.php?title=SQL_injection&diff=4212SQL injection2020-12-10T14:27:06Z<p>Enric: /* Introducció */</p>
<hr />
<div>SQL injection és una forma d'atac cibernètic per manipular la base de dades remota a través dels formularis.<br />
<br />
== Introducció ==<br />
Una bona manera d'introduir-se a aquest tema és amb aquest acudit:<br />
<br />
http://stackoverflow.com/questions/332365/how-does-the-sql-injection-from-the-bobby-tables-xkcd-comic-work?rq=1<br />
<br />
Fes-li un cop d'ull a aquests articles també per veure solucions:<br />
<br />
http://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php?rq=1<br />
https://diego.com.es/tutorial-de-pdo<br />
<br />
<br><br />
<br />
== Coneixements previs ==<br />
Cal que coneixem el llenguatge de programació PHP i el llenguatge de manipulació de dades SQL.<br />
* [[Curs de PHP]]<br />
* [[Curs de SQL]]<br />
* Partirem d'aquests exemples:<br />
** Utilitzant [https://uf.ctrl-alt-d.net/material/mostra/50/php-acces-a-dades-amb-pdo PDO]<br />
** Utilitzant mysqli [[PHP MySQL select]]<br />
<br />
<br><br />
<br />
== Un petit exemple amb LOGIN ==<br />
Qualsevol formulari on l'usuari pugui entrar text lliure pot ser un punt vulnerable. Per exemple, el formulari de ''login'' típic per entrar al sistema.<br />
<br />
En aquest exemple tenim la taula d'usuaris típica:<br />
mysql> desc users;<br />
+----------+--------------+------+-----+---------+----------------+<br />
| Field | Type | Null | Key | Default | Extra |<br />
+----------+--------------+------+-----+---------+----------------+<br />
| id | int(11) | NO | PRI | NULL | auto_increment |<br />
| username | varchar(200) | YES | | NULL | |<br />
| name | varchar(200) | YES | | NULL | |<br />
| password | varchar(600) | YES | | NULL | |<br />
+----------+--------------+------+-----+---------+----------------+<br />
4 rows in set (0,01 sec)<br />
<br />
En aquest cas, tenim diversos usuaris: enric, crypto, pepa i manolo. La password està encriptada amb SHA2-512<br />
<br />
El més habitual és entrar el teu nom d'usuari i la password, i llavors entraríem amb l'usuari.<br />
<br />
Fixeu-vos en què la sentència SQL que apareix abans del formulari no hi hauria de ser, la hem posat per il·lustrar quin serà la manera de perpetrar la injecció.<br />
<br />
[[Fitxer:Sqlinjection1.png|600px]]<br />
<br />
----<br />
<br />
La sentència que hem executat utilitza el ''username'' i ''password'' que l'usuari ha subministrat.<br />
<br />
Però si enlloc de posar el nom d'usuari posem una sentència SQL hàbil i preclara, podem manipular la ''query'' que finalment enviarem a la base de dades. En el següent exemple, '''enlloc del nom d'usuari entrarem''':<br />
<br />
enric' or 1=1; -- lala'<br />
<br />
...que es transformarà en el següent:<br />
<br />
SELECT * FROM users WHERE username='enric' or 1=1; -- lala' AND password=SHA2('asd',512);<br />
<br />
El què hi ha després de la "--" es transforma en un comentari, pel que s'ignora. I al haver posat "OR 1=1", ens donarà TRUE per a tots els registres.<br />
<br />
I el resultat serà aquest:<br />
<br />
[[Fitxer:Sqlinjection3.png|600px]]<br />
<br />
...que com podreu imaginar, és una possible manera de liar el codi i efectuar un "fals positiu" i entrar amb el nom d'usuari que vulguem (o que puguem, que en segons quina situació pot ser suficient per entrar en algun lloc amb privilegis).<br />
<br />
<br><br />
<br />
== Llibreries ==<br />
Hi ha 2 llibreries per accedir MySQL des de PHP. Ambdúes se suposa que NO permeten fer 2 queries seguides (per seguretat).<br />
* [https://uf.ctrl-alt-d.net/material/mostra/50/php-acces-a-dades-amb-pdo PDO]<br />
* [http://php.net/manual/es/book.mysql.php mysql original] (obsoleta)<br />
* [http://php.net/manual/es/book.mysqli.php mysqli : mysql millorada]<br />
<br />
Si es permetés això (en anteriors versions sí que passava), què creus que passaria si introdueixo això com a nom d'usuari?<br />
enric' or 1=1; drop table usuaris; -- lala</div>Enrichttps://cacauet.org/wiki/index.php?title=PHP_MySQL_select&diff=4211PHP MySQL select2020-11-18T19:07:23Z<p>Enric: /* Codi font de l'exemple */</p>
<hr />
<div>Utilitzarem les [http://es2.php.net/manual/en/book.mysql.php funcions PHP] per accedir al SGBD MySQL. Consulteu-les [http://es2.php.net/manual/en/book.mysql.php aquí].<br />
<br />
A grans trets, el proceś general per atacar un SGBD és aquest:<br />
#Connexió a la BBDD<br />
#Crear i enviar query<br />
#Obtenir resultats i mostrar-los per pantalla<br />
<br />
<br />
En aquest darrer pas (obtenir i mostrar resultats) cal fixar-se especialment en l' '''estructura de control''' que necessitarem:<br />
*'''Bucle de registres''': (''while'') iterarà per cadascuna de les files de la taula. Haurà de ser un bucle tipus '''''while''''' ja que no sabem quan arribarem a la darrera fila.<br />
<br />
<br />
== Procés detallat per extreure dades de MySQL ==<br />
<br />
Per obtenir dades d'una taula MySQL i visualitzar-la utilitzant PHP seguirem les següents passes:<br />
#Connexió<br />
##'''Connectar''' a MySQL amb l'ordre '''''mysql_connect()'''''<br />
##'''Triar la BBDD''' de treball amb '''''mysql_select_db()'''''<br />
#Crear i enviar consulta (query):<br />
##'''Crear la consulta''' i desar-la en una variable, típicament '''''$query = "SELECT ... FROM ... WHERE ..."'''''<br />
##'''Enviar la consulta''' al sistema (SGBD) per obtenir el resultat amb '''''[http://es2.php.net/manual/es/function.mysql-query.php mysql_query()]'''''<br />
##Si no hi ha resultat (0 files o bé hi ha algun error a la sintaxi) posem un missatge d'error i acabem l'execució de la pàgina web amb '''''die($missatge)'''''<br />
#Obtenir resultats i mostrar-los:<br />
##Obrim taula HTML amb <nowiki><table></nowiki> i la capçalera amb <nowiki><thead></nowiki><br />
##'''Bucle while''' pels registres de la taula: com que poden haver-ne varis, farem un bucle (''loop''). Típicament s'utiltiza un '''''while''''' perquè no sabem quan arribarem a la darrera fila<br />
##:(Dins del while) Extreure les dades d'un registre (fila de la BBDD) i emmagatzemar-les en un ''array'' amb alguna d'aquestes funcions:<br />
##*''[http://es2.php.net/manual/es/function.mysql-fetch-row.php mysql_fetch_row()]'': extreu els camps de la fila en un array numèric clàssic.<br />
##*:Per exemple: echo $registre[0]<br />
##*''[http://es2.php.net/manual/es/function.mysql-fetch-assoc.php mysql_fetch_assoc()]'': extreu els camps de la fila en un array associatiu.<br />
##*:Per exemple: echo $registre["titol_original"]<br />
##*''[http://es2.php.net/manual/es/function.mysql-fetch-object.php mysql_fetch_object()]'': extreu els camps en un objecte.<br />
##*:Per exemple: echo $registre->titol_original;<br />
##Obrim la fila de la taula HTML amb <nowiki><tr></nowiki><br />
##Mostrem dades dins de cel·les d'una taula HTML. Haurem de concatenar diverses cadenes de caràcters:<br />
##*Obrir la cel·la de la taula utiltizant <nowiki><td></nowiki><br />
##*Imprimir resultat amb les dades de l'array. Per exemple, $registre["titol_original"]<br />
##*Tancar la cel·la de la taula utiltizant <nowiki></td></nowiki><br />
##Tanquem la fila de la taula HTML amb <nowiki></tr></nowiki><br />
##Tanquem la taula amb <nowiki></table></nowiki><br />
<br />
<br />
== Codi font de l'exemple ==<br />
Per crear i importar la base de dades d'exemple pots consultar [[SQL creacio]]. Utilitzarem la BBDD d'exemple "World" que hi ha a la pàgina oficial de MySQL. La podeu descarregar d'aquí:<br />
https://dev.mysql.com/doc/index-other.html<br />
<br />
Examineu a fons i proveu aquest codi:<br />
<br />
<syntaxhighlight lang="php"><br />
<html><br />
<head><br />
<title>Exemple de lectura de dades a MySQL</title><br />
<style><br />
body{<br />
}<br />
table,td {<br />
border: 1px solid black;<br />
border-spacing: 0px;<br />
}<br />
</style><br />
</head><br />
<br />
<body><br />
<h1>Exemple de lectura de dades a MySQL</h1><br />
<br />
<?php<br />
# (1.1) Connectem a MySQL (host,usuari,contrassenya)<br />
$conn = mysqli_connect('localhost','enric','enric123');<br />
<br />
# (1.2) Triem la base de dades amb la que treballarem<br />
mysqli_select_db($conn, 'world');<br />
<br />
# (2.1) creem el string de la consulta (query)<br />
$consulta = "SELECT * FROM city;";<br />
<br />
# (2.2) enviem la query al SGBD per obtenir el resultat<br />
$resultat = mysqli_query($conn, $consulta);<br />
<br />
# (2.3) si no hi ha resultat (0 files o bé hi ha algun error a la sintaxi)<br />
# posem un missatge d'error i acabem (die) l'execució de la pàgina web<br />
if (!$resultat) {<br />
$message = 'Consulta invàlida: ' . mysqli_error($conn) . "\n";<br />
$message .= 'Consulta realitzada: ' . $consulta;<br />
die($message);<br />
}<br />
?><br />
<br />
<!-- (3.1) aquí va la taula HTML que omplirem amb dades de la BBDD --><br />
<table><br />
<!-- la capçalera de la taula l'hem de fer nosaltres --><br />
<thead><td colspan="4" align="center" bgcolor="cyan">Llistat de ciutats</td></thead><br />
<?php<br />
# (3.2) Bucle while<br />
while( $registre = mysqli_fetch_assoc($resultat) )<br />
{<br />
# els \t (tabulador) i els \n (salt de línia) son perquè el codi font quedi llegible<br />
<br />
# (3.3) obrim fila de la taula HTML amb <tr><br />
echo "\t<tr>\n";<br />
<br />
# (3.4) cadascuna de les columnes ha d'anar precedida d'un <td><br />
# després concatenar el contingut del camp del registre<br />
# i tancar amb un </td><br />
echo "\t\t<td>".$registre["Name"]."</td>\n";<br />
echo "\t\t<td>".$registre['CountryCode']."</td>\n";<br />
echo "\t\t<td>".$registre["District"]."</td>\n";<br />
echo "\t\t<td>".$registre['Population']."</td>\n";<br />
<br />
# (3.5) tanquem la fila<br />
echo "\t</tr>\n";<br />
}<br />
?><br />
<!-- (3.6) tanquem la taula --><br />
</table> <br />
</body><br />
</html><br />
</syntaxhighlight><br />
<br />
== Exercicis ==<br />
Posa en marxa aquest exemple en la teva màquina Linux. Hauràs de:<br />
* Instal·lar apache2 i php5<br />
* Comproveu que el servidor Apache funciona apuntant el ''browser'' a http://localhost<br />
* Rearrencar apache amb<br />
*: '''$ sudo apache2ctl restart'''<br />
* Importar la base de dades [[Fitxer:Videoclub.sql]] al vostre servidor MySQL. Si no sabeu com fer-ho, consulteu-ho a [[SQL_creacio]]<br />
* Si no us deixa haureu de donar permisos a la carpeta per poder escriure amb<br />
*: '''$ sudo chmod 777 /var/www'''<br />
*: ULL! Aquesta és una mesura molt poc segura. Només ho fem per anar ràpid. No ho feu mai en un servidor en producció. Si voleu poder escriure en un directori d'usuari es recomana activar el mòdul ''userdir'' de l'apache amb la comanda<br />
*: ''$> sudo a2enmod userdir''<br />
* Copiar i enganxar el codi PHP de l'exemple de més amunt a l'arxiu /var/www/ex1.php<br />
* Apunta el ''browser'' a la direcció: http://localhost/ex1.php<br />
<br />
Opcionalment pots esborrar l'arxiu /var/www/index.html . Així l'apache ens mostrarà els arxius continguts a la carpeta.<br />
<br />
<br />
=== Exercici de filtratge amb WORLD ===<br />
<br />
Amplia l'exemple de les ciutats amb la BBDD World de forma que puguem filtrar les ciutats mostrades amb un menú desplegable (SELECT).<br />
<br />
Guia:<br />
# Pàgina 1: Comença per fer un llistat dels països utilitzant la taula COUNTRY.<br />
# La FK que lliga la taula CITY i la taula COUNTRY és el CountryCode. El formulari ''select'' (ja sigui desplegable o ''radio button'') ha de mostrar el nom del país, però ha d'enviar el CountryCode com a ''value'' a través de GET o POST a la pagina 2.<br />
# Pàgina 2: Agafa el país enviat per l'usuari (GET o POST) i fes una ''query'' que filtri els resultats de la taula CITY i que només mostri les ciutats del país seleccionat.<br />
# Puja aquest projecte a Github i crea un README.md que expliqui com posar en marxa l'exercici perquè funcioni correctament.<br />
# Indica també el nom del país de la ciutat. No ens val el CountryCode, volem el nom del país literal (per exemple, no ens val "FRA" sinó que haria de sortir "France"). Per a fer això caldrà que facis un JOIN.<br />
# Afegeix les banderes dels països al formulari (caldrà cercar-les per internet).<br />
# Afegeix un formulari que permeti afegir noves ciutats. Els països s'han de poder entrar amb un desplegable.<br />
<br />
<br><br />
<br />
=== Exercicis de queries ===<br />
<br />
Realitza els següents exercicis amb la [[Fitxer:Ufs.sql|base de dades de UFs]]. Si no saps com crear-la pots consultar-ho a [[SQL_creacio]].<br />
*'''ex2.php''': mostra les assignatures de 2n de SMX. Cal, doncs, tenir instal·lada la base de dades.<br />
*'''ex3.php''': mostra les assignatures de la ESO.<br />
*'''ex4.php''': mostra el nom dels tots els alumnes.<br />
<br />
Exercicis amb el videoclub [[Fitxer:Videoclub.sql]]:<br />
*'''ex5.php''': mostra tots els lloguers ordenats descendentment per data de sortida.<br />
*'''ex6.php''': mostra els diferents gèneres disponibles ordenats alfabèticament.<br />
<br />
<br />
=== Exercicis amb JOIN ===<br />
IMPORTANT:<br />
*Tituleu adequadament cada pàgina perquè quedi clar quina consulta estem realitzant.<br />
*No val utilitzar IDs al WHERE (per això justament son amb JOIN). Heu de fer servir la paraula o dada tal i com apareix a l'enunciat de cada exercici.<br />
*A totes les consultes ha d'aparèixer, com a mínim, totes les dades que apareixen a l'enunciat.<br />
*:Per exemple, si demanem totes els alumnes matriculats a la ESO ha d'aparèixer no només al nom dels alumnes, sinó també la titulació (ESO).<br />
*Poseu encapçalament a les columnes.<br />
*MOLT IMPORTANT: tingueu en compte que quan es fa un select amb join, poden haver camps de diverses taules amb el mateix nom de columna. A l'utiltizar arrays associatius, la clau de l'array amb la que ens adreçem pot estar superposada i llavors només visualitzarem les dades del darrer camp que apareix en els SELECT. Per solucionar-ho, utilitzeu el AS per reanomenar la columna amb un altre nom que us convingui.<br />
*: Per exemple, al exercici "join1.php", si fem un "SELECT assignatures.*, professors.* FROM ..." tindrem un conflicte entre les columnes "nom" del professor i el "nom" de l'assignatura. Per poder accedir a les dues dades, cal que les expliciteu totes dues (no valen, doncs, els *) i reanomenar-les a ''nom_profe'' i ''nom_assignautra'' amb un "AS".<br />
<br />
<br />
Exercicis:<br />
#'''join1.php''': mostra les assignatures que imparteix el professor Enric Mieza.<br />
#:Resultat: hauria de sortir-vos només l'assignatura de Muntatge i la de Bases de Dades.<br />
#'''join2.php''': llistat de les UFs de l'assignatura "Sistemes Operatius Monolloc".<br />
#'''join3.php''': llistat d'assignatures amb la seva titulació.<br />
#'''join4.php''': nombre de matrícules del curs 2009-2010<br />
#'''join5.php''': recompte de matrícules per curs.<br />
#'''join6.php''': recompte de UFs per assignatura.<br />
#'''join7.php''': llistat de les UFs de les assignatures de SMX, ordenades per número del mòdul (assignatura).<br />
#'''join8.php''': llistat de les assignatures en què està matriculat en Pere Escribano.<br />
#'''join9.php''': llistat de qualificacions (assigntura i UF) de l'alumne Òscar Tabuada.<br />
#'''join10.php''': llistat de qualificacions aprovades dels alumnes del curs 2009-2010.<br />
#'''join11.php''': mitjana de les qualificacions de l'alumne David Dalmau. <br />
#'''join12.php''': llistat d'alumnes aprovats de les UFs de l'assignatura "Sistemes Operatius Monolloc".</div>Enrichttps://cacauet.org/wiki/index.php?title=Git:_comandes&diff=4210Git: comandes2020-10-19T17:02:07Z<p>Enric: /* Branch */</p>
<hr />
<div><nowiki>#FpInfor #DawMp08 #DawMp08Uf04 #DawMp08Uf4</nowiki><br />
<br />
GIT és un sistema de control de versionat semblant a SVN (Subversion). Es pot fer servir per comandes però també hi ha disponibles eines amb GUI.<br />
<br />
== Introducció ==<br />
* Conceptes previs: [[Control de versions]]<br />
* Llibre de referència (en espanyol) http://git-scm.com/book/es<br />
* Interfície gràfica per GIT:<br />
** http://www.rabbitvcs.org/<br />
** http://askubuntu.com/questions/4788/nautilus-git-integration<br />
* Una bona xuleta de totes les funcions de GIT: https://ndpsoftware.com/git-cheatsheet.html<br />
<br />
<br />
Un dels principals atractius és el repositori públic https://github.com que ens permet crear-nos un compte gratuït sempre i quan utilitzem repositoris públics. Pels repositoris privats cal pagar.<br />
<br />
En qualsevol moment podem demanar ajuda sobre una comanda mitjançant:<br />
$ man git-<comanda><br />
Per exemple:<br />
$ man git-status<br />
<br />
== Exemple: clonar un projecte ==<br />
Pots provar de clonar un parell de projectes:<br />
* [https://github.com/emieza/pyges Pyges]: un CMS basat en Pyramid per Google App Engine (GAE).<br />
* [https://github.com/emieza/egipcis Egipcis]: senzill exemple d'autenticació amb Pyramid.<br />
<br />
Instal·la el git al teu PC:<br />
$ sudo apt-get install git<br />
<br />
Clona el projecte Faceschool:<br />
$ git clone https://github.com/lacetans/faceschool.git<br />
<br />
Se't descarregarà a la teva màquina. Activa el virtualenv i posa'l en marxa:<br />
$ source ~/env/bin/activate<br />
$ python manage.py runserver<br />
<br />
Prova-ho també amb el projecte "Egipcis" (és més senzill i triga menys a descarregar).<br />
https://github.com/emieza/egipcis.git<br />
<br />
== Crear un projecte nou ==<br />
# Crea el teu compte a http://github.com<br />
# Crea el nou repositori des de la web (és més fàcil).<br />
#* També ho pots fer amb comandes: https://help.github.com/articles/create-a-repo<br />
# Abans de fer un commit penseu a fer un [https://help.github.com/articles/set-up-git setup del GIT] a la vostra màquina (no és imprescindible però convenient més que res per deixar el nom d'usuari i email a cada commit que fem).<br />
# Feu un '''clone''' del repositori creat.<br />
# Afegiu l''''arxiu .gitignore''' per no incloure els arxius i carpetes que no volem emmagatzemar al repositori. Com a mínim seran (pel cas dels Pyramid ''scaffolds''):<br />
#* *.pyc<br />
#* <nomdelpaquet>-egg.info<br />
# Copiar els arxius del scaffold (o el projecte que sigui) dins del directori clonat.<br />
# Fer un '''add''' de tots els arxius (git add "*").<br />
# Fer un '''commit''' i un '''push''' per actualitzar.<br />
<br />
=== Nou projecte a GITHUB amb comandes locals ===<br />
Crear nou projecte a Github:<br />
$ curl -u 'USER' https://api.github.com/user/repos -d '{"name":"REPO"}'<br />
...òbviament canviant USER pel teu usuari i REPO pel nom del repositori que vols crear. La URL es queda tal qual.<br />
<br />
Si vols crear un projecte en una organització enlloc de dins d'un compte d'usuari:<br />
$ curl -u 'USER' https://api.github.com/orgs/:org_name/repos -d '{"name":"REPO"}'<br />
<br />
Si volem crear un nou projecte i pujar-lo seguidament:<br />
* Crear un projecte del què sigui (PHP, Python, C++, etc.)<br />
* Inicialitzar la carpeta del projecte:<pre>$ git init</pre><br />
* Afegir .gitignore a l'arrel del projecte per evitar afegir arxius indesitjats (com per exemple els .pyc)<br />
* Afegir tots els arxius:<pre>$ git add .</pre><br />
* Consolidar canvis locals:<pre>$ git commit -am "primer commit"</pre><br />
* Afegir remot del Github:<pre>$ git remote add origin https://github.com/USER/REPO.git</pre><br />
* Pujar els arxius al repo:<pre>$ git push origin master</pre><br />
<br />
<br><br />
<br />
== Comandes ==<br />
Per crear un projete el més fàcil és fer-ho des de la interfície web del github.<br />
<br />
Per afegir arxius, directoris, etc. al projecte<br />
$ git add <arxiu1> <arxiu2> ...<br />
<br />
Per descarregar un projecte de nou:<br />
$ git clone <url><br />
La "url" del github sol ser https://github.com/username/projecte.git<br />
<br />
<br />
Per conèixer l'estat del projecte (arxius modificats, afegits, esborrats, etc.):<br />
$ git status<br />
<br />
Per "gravar" tots els canvis fets durant la sessió:<br />
$ git commit -a<br />
Per "gravar" els canvis d'un sol arxiu:<br />
$ git commit <arxiu1> <arxiu2> ...<br />
<br />
Per carregar els canvis al repositori:<br />
$ git push<br />
<br />
Per descarregar els canvis del repositori:<br />
$ git pull<br />
<br />
<br><br />
<br />
== Branch ==<br />
Per fer "branques" al nostre repositori, primer l'heu d'haver clonat, per exemple el [https://github.com/AWS2/welcome projecte Welcome].<br />
<br />
Al ser GIT un sistema de control de versions distribuit, hem de tenir en compte que hi haurà '''branques locals''' i '''branques remotes'''. Normalment la idea és senzilla:<br />
* Crear branca remota en Github (via web, recorda exactament el nom_branca)<br />
* Descarregar (clone) o actualitzar (pull) el repo local.<br />
* Crear la branca. Si es diu igual la branca remota i la local, quedaran enllaçades automàticament.<pre>$ git branch <nom_branca></pre><br />
* Canviar-se localment a la nova branca de treball.<pre>$ git checkout <nom_branca></pre><br />
* Anar fent ''commits'' i ''push''<br />
<br />
Abans de res, serà més fàcil si creem la branca des de la web de GitHub. Això és important abans de fer el PUSH.<br />
<br />
Crear una branca en el nostre repositori local:<br />
$ git branch <nom_branca><br />
<br />
I després pujar-la al nostre repositori:<br />
$ git push origin <nom_branca><br />
<br />
Per exemple:<br />
$ git branch auth<br />
$ git push origin auth<br />
<br />
<br />
Per veure quines branques estan disponibles i quina tenim activa (*):<br />
$ git branch -a<br />
<br />
Per canviar-nos de branca:<br />
$ git checkout <nom_branca><br />
<br />
<code>...editem el nostre codi...</code><br />
<br />
En aquest punt, cal que creem la branca en el remot a través de la web del projecte en GitHub.com (si no ho hem fet ja).<br />
<br />
Finalment carreguem els canvis:<br />
$ git push<br />
(ens demanarà ususari i contrasenya, i òbviament hem de tenir permsisos d'escriptura en el projecte)<br />
<br />
=== Seguir una branca remota ===<br />
Si en el moment de crear la branca local no s'ha enllaçat a la branca remota, ho podem fer amb:<br />
$ git checkout <branca_local><br />
$ git branch -u origin <branca_remota><br />
<br />
<br><br />
<br />
== Merge ==<br />
Una bona referència: http://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging<br />
<br />
En realitat cal 1r fer un checkout de la branca principal i després unir-li la que vols fusionar (que desapareixerà):<br />
<pre><br />
$ git checkout master<br />
$ git merge hotfix<br />
Updating f42c576..3a0874c<br />
Fast-forward<br />
index.html | 2 ++<br />
1 file changed, 2 insertions(+)<br />
</pre><br />
<br />
<br><br />
<br />
== Creant un repo accessible per SSH ==<br />
Aquí veurem com crear un repositori en un servidor on tenim accés per SSH.<br />
<br />
Al '''servidor''' podem crear un repositori remot amb:<br />
$ git init --bare <nom_carpeta><br />
<br />
Al '''client''' podem crear un repositori local entrant a la carpeta i fent (ull, carpeta remota amb path absolut):<br />
$ git init<br />
$ git remote add origin <usuari>@<servidor>:<carpeta_remota><br />
$ touch README<br />
$ git add .<br />
$ git commit -a<br />
$ git push origin master<br />
<br />
...i ja el tenim.<br />
<br />
Podem clonar des de qualsevol lloc amb:<br />
$ git clone <usuari>@<servidor>:<carpeta_remota><br />
<br />
<br><br />
<br />
== Creant una versió Release ==<br />
Ens solem referir a una ''Release'' a una versió concreta d'un programari que "lliurem" al públic o a un client. La traducció literal de ''release'' és exactament "lliurar".<br />
<br />
Quan parlem de ''releases'' parlem de publicar-les a una web, com Github o Gitlab.<br />
<br />
El sistema de versionat GIT només pot etiquetar un commit concret del nostre repositori. Per poder fer una ''release'' a Github, caldrà que abans etiqueteu (tag) el vostre commit de la vostra branca desitjada, i posteriorment creeu la ''release'' amb la interfície de Github.<br />
<br />
Aquí teniu la doc oficial:<br />
<br />
* Git tagging (etiquetado): https://git-scm.com/book/es/v1/Fundamentos-de-Git-Creando-etiquetas<br />
* Github relases: https://help.github.com/articles/creating-releases/</div>Enrichttps://cacauet.org/wiki/index.php?title=Git:_comandes&diff=4209Git: comandes2020-10-19T16:49:02Z<p>Enric: /* Branch */</p>
<hr />
<div><nowiki>#FpInfor #DawMp08 #DawMp08Uf04 #DawMp08Uf4</nowiki><br />
<br />
GIT és un sistema de control de versionat semblant a SVN (Subversion). Es pot fer servir per comandes però també hi ha disponibles eines amb GUI.<br />
<br />
== Introducció ==<br />
* Conceptes previs: [[Control de versions]]<br />
* Llibre de referència (en espanyol) http://git-scm.com/book/es<br />
* Interfície gràfica per GIT:<br />
** http://www.rabbitvcs.org/<br />
** http://askubuntu.com/questions/4788/nautilus-git-integration<br />
* Una bona xuleta de totes les funcions de GIT: https://ndpsoftware.com/git-cheatsheet.html<br />
<br />
<br />
Un dels principals atractius és el repositori públic https://github.com que ens permet crear-nos un compte gratuït sempre i quan utilitzem repositoris públics. Pels repositoris privats cal pagar.<br />
<br />
En qualsevol moment podem demanar ajuda sobre una comanda mitjançant:<br />
$ man git-<comanda><br />
Per exemple:<br />
$ man git-status<br />
<br />
== Exemple: clonar un projecte ==<br />
Pots provar de clonar un parell de projectes:<br />
* [https://github.com/emieza/pyges Pyges]: un CMS basat en Pyramid per Google App Engine (GAE).<br />
* [https://github.com/emieza/egipcis Egipcis]: senzill exemple d'autenticació amb Pyramid.<br />
<br />
Instal·la el git al teu PC:<br />
$ sudo apt-get install git<br />
<br />
Clona el projecte Faceschool:<br />
$ git clone https://github.com/lacetans/faceschool.git<br />
<br />
Se't descarregarà a la teva màquina. Activa el virtualenv i posa'l en marxa:<br />
$ source ~/env/bin/activate<br />
$ python manage.py runserver<br />
<br />
Prova-ho també amb el projecte "Egipcis" (és més senzill i triga menys a descarregar).<br />
https://github.com/emieza/egipcis.git<br />
<br />
== Crear un projecte nou ==<br />
# Crea el teu compte a http://github.com<br />
# Crea el nou repositori des de la web (és més fàcil).<br />
#* També ho pots fer amb comandes: https://help.github.com/articles/create-a-repo<br />
# Abans de fer un commit penseu a fer un [https://help.github.com/articles/set-up-git setup del GIT] a la vostra màquina (no és imprescindible però convenient més que res per deixar el nom d'usuari i email a cada commit que fem).<br />
# Feu un '''clone''' del repositori creat.<br />
# Afegiu l''''arxiu .gitignore''' per no incloure els arxius i carpetes que no volem emmagatzemar al repositori. Com a mínim seran (pel cas dels Pyramid ''scaffolds''):<br />
#* *.pyc<br />
#* <nomdelpaquet>-egg.info<br />
# Copiar els arxius del scaffold (o el projecte que sigui) dins del directori clonat.<br />
# Fer un '''add''' de tots els arxius (git add "*").<br />
# Fer un '''commit''' i un '''push''' per actualitzar.<br />
<br />
=== Nou projecte a GITHUB amb comandes locals ===<br />
Crear nou projecte a Github:<br />
$ curl -u 'USER' https://api.github.com/user/repos -d '{"name":"REPO"}'<br />
...òbviament canviant USER pel teu usuari i REPO pel nom del repositori que vols crear. La URL es queda tal qual.<br />
<br />
Si vols crear un projecte en una organització enlloc de dins d'un compte d'usuari:<br />
$ curl -u 'USER' https://api.github.com/orgs/:org_name/repos -d '{"name":"REPO"}'<br />
<br />
Si volem crear un nou projecte i pujar-lo seguidament:<br />
* Crear un projecte del què sigui (PHP, Python, C++, etc.)<br />
* Inicialitzar la carpeta del projecte:<pre>$ git init</pre><br />
* Afegir .gitignore a l'arrel del projecte per evitar afegir arxius indesitjats (com per exemple els .pyc)<br />
* Afegir tots els arxius:<pre>$ git add .</pre><br />
* Consolidar canvis locals:<pre>$ git commit -am "primer commit"</pre><br />
* Afegir remot del Github:<pre>$ git remote add origin https://github.com/USER/REPO.git</pre><br />
* Pujar els arxius al repo:<pre>$ git push origin master</pre><br />
<br />
<br><br />
<br />
== Comandes ==<br />
Per crear un projete el més fàcil és fer-ho des de la interfície web del github.<br />
<br />
Per afegir arxius, directoris, etc. al projecte<br />
$ git add <arxiu1> <arxiu2> ...<br />
<br />
Per descarregar un projecte de nou:<br />
$ git clone <url><br />
La "url" del github sol ser https://github.com/username/projecte.git<br />
<br />
<br />
Per conèixer l'estat del projecte (arxius modificats, afegits, esborrats, etc.):<br />
$ git status<br />
<br />
Per "gravar" tots els canvis fets durant la sessió:<br />
$ git commit -a<br />
Per "gravar" els canvis d'un sol arxiu:<br />
$ git commit <arxiu1> <arxiu2> ...<br />
<br />
Per carregar els canvis al repositori:<br />
$ git push<br />
<br />
Per descarregar els canvis del repositori:<br />
$ git pull<br />
<br />
<br><br />
<br />
== Branch ==<br />
Per fer "branques" al nostre repositori, primer l'heu d'haver clonat, per exemple el [https://github.com/AWS2/welcome projecte Welcome].<br />
<br />
Al ser GIT un sistema de control de versions distribuit, hem de tenir en compte que hi haurà ''branques locals'' i ''branques remotes''. Normalment la idea és senzilla:<br />
* Crear branca remota en Github<br />
* Descarregar (clone) o actualitzar (pull) el repo local.<br />
* Crear la branca. Si es diu igual la branca remota i la local, quedaran enllaçades automàticament.<br />
* Canviar-se localment a la nova branca de treball.<br />
<br />
Abans de res, serà més fàcil si creem la branca des de la web de GitHub. Això és important abans de fer el PUSH.<br />
<br />
Crear una branca en el nostre repositori local:<br />
$ git branch <nom_branca><br />
<br />
I després pujar-la al nostre repositori:<br />
$ git push origin <nom_branca><br />
<br />
Per exemple:<br />
$ git branch auth<br />
$ git push origin auth<br />
<br />
<br />
Per veure quines branques estan disponibles i quina tenim activa (*):<br />
$ git branch -a<br />
<br />
Per canviar-nos de branca:<br />
$ git checkout <nom_branca><br />
<br />
<code>...editem el nostre codi...</code><br />
<br />
En aquest punt, cal que creem la branca en el remot a través de la web del projecte en GitHub.com (si no ho hem fet ja).<br />
<br />
Finalment carreguem els canvis:<br />
$ git push<br />
(ens demanarà ususari i contrasenya, i òbviament hem de tenir permsisos d'escriptura en el projecte)<br />
<br />
=== Seguir una branca remota ===<br />
Si en el moment de crear la branca local no s'ha enllaçat a la branca remota, ho podem fer amb:<br />
$ git checkout <branca_local><br />
$ git branch -u origin <branca_remota><br />
<br />
<br><br />
<br />
== Merge ==<br />
Una bona referència: http://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging<br />
<br />
En realitat cal 1r fer un checkout de la branca principal i després unir-li la que vols fusionar (que desapareixerà):<br />
<pre><br />
$ git checkout master<br />
$ git merge hotfix<br />
Updating f42c576..3a0874c<br />
Fast-forward<br />
index.html | 2 ++<br />
1 file changed, 2 insertions(+)<br />
</pre><br />
<br />
<br><br />
<br />
== Creant un repo accessible per SSH ==<br />
Aquí veurem com crear un repositori en un servidor on tenim accés per SSH.<br />
<br />
Al '''servidor''' podem crear un repositori remot amb:<br />
$ git init --bare <nom_carpeta><br />
<br />
Al '''client''' podem crear un repositori local entrant a la carpeta i fent (ull, carpeta remota amb path absolut):<br />
$ git init<br />
$ git remote add origin <usuari>@<servidor>:<carpeta_remota><br />
$ touch README<br />
$ git add .<br />
$ git commit -a<br />
$ git push origin master<br />
<br />
...i ja el tenim.<br />
<br />
Podem clonar des de qualsevol lloc amb:<br />
$ git clone <usuari>@<servidor>:<carpeta_remota><br />
<br />
<br><br />
<br />
== Creant una versió Release ==<br />
Ens solem referir a una ''Release'' a una versió concreta d'un programari que "lliurem" al públic o a un client. La traducció literal de ''release'' és exactament "lliurar".<br />
<br />
Quan parlem de ''releases'' parlem de publicar-les a una web, com Github o Gitlab.<br />
<br />
El sistema de versionat GIT només pot etiquetar un commit concret del nostre repositori. Per poder fer una ''release'' a Github, caldrà que abans etiqueteu (tag) el vostre commit de la vostra branca desitjada, i posteriorment creeu la ''release'' amb la interfície de Github.<br />
<br />
Aquí teniu la doc oficial:<br />
<br />
* Git tagging (etiquetado): https://git-scm.com/book/es/v1/Fundamentos-de-Git-Creando-etiquetas<br />
* Github relases: https://help.github.com/articles/creating-releases/</div>Enrichttps://cacauet.org/wiki/index.php?title=Django&diff=4208Django2020-10-06T07:01:44Z<p>Enric: /* SQLite vs MySQL */</p>
<hr />
<div>Django és un ''framework web'' basat en Python molt popular. Està orientat a la rapidesa de desenvolupament.<br />
Django or "The web framework for perfectionists with deadlines".<br />
<br />
<nowiki>#FpInfor #DawMp07 #DawMp07Uf2 #DawMp07Uf02 #DawMpDual</nowiki><br />
<br />
<br />
== Introducció ==<br />
Pàgina oficial:<br />
https://www.djangoproject.com/<br />
<br />
Articles relacionats:<br />
* [[Django en producció]]<br />
* [[Virtualenv]]<br />
<br />
Es basa en un '''paradigma MTV o Model-Template-View'''. És similar al arxiconegut MVC o Model-View-Controller, però la terminologia pot induir a confusions. En el cas de MVC, la ''view'' és la part visual o GUI, mentre que en el MTV, la ''view'' és el codi amb la lògica de negoci (equivaldria al ''controller'' del MVC).<br />
<br />
ULL doncs amb els noms!<br />
Model - '''View''' - Controller<br />
Model - Template - '''View'''<br />
<br />
Django està molt implantat a tot el món web, disposa de gran prestigi i té un creixement ràpid de desenvolupadors i ofertes de feina relacionades.<br />
<br />
Plug-ins interessants:<br />
* [https://django-admin-sortable2.readthedocs.io/en/latest/usage.html django-admin-sortable2]: per poder fer llistes ordenables per JS<br />
* Oauth2<br />
* RIchTextField<br />
* Easy Select2 : per incrustar cercadors amb autocmpletar en els camps de FK o ManyToMany<br />
<br />
<br />
<br><br />
<br />
== Preparatius i instal·lació ==<br />
Per desenvolupar amb Django ens serà molt útil (per no dir imprescindible) utilitzar [[Virtualenv]].<br />
<br />
Abans de començar, [[Virtualenv|configura el teu entorn com s'explica en aquest article]].<br />
<br />
<br><br />
<br />
== Exemple: botiga ==<br />
Podeu agafar aquest projecte d'exemple per clarificar les funcions bàsiques de Django:<br />
https://github.com/emieza/django-botiga<br />
<br />
<br><br />
<br />
== Backend ==<br />
El ''backend'' de Django o panell d'administració.<br />
<br />
Per treballar el ''backend'' podem fer ús del TUTORIAL oficial de Django, que està molt ben documentat:<br />
https://www.djangoproject.com/start/<br />
<br />
Per poder dominar mínimament les possibilitats del ''backend'' segueix al menys aquestes parts del tutorial:<br />
* Part 1: creació de projecte i primera ''view''<br />
* Part 2: model, BD, admin backend<br />
* Part 7: customize admin i ''inlines''<br />
* Investiga la propietat '''list_editable''' del ModelAdmin. Per a què serveix?<br />
<br />
A partir d'aquí podrem plantejar un projecte que implementi tot el CRUD en el ''backend''.<br />
# Planteja el projecte al professor. Que et doni el vist-i-plau abans de començar. El projecte hauria d'incloure usuaris i permisos diversos.<br />
# Implementa el model amb Django. Imprescindible posar adequadament les FK (Foreign Keys).<br />
# Mira si pots incloure ''inlines'' en alguna de les entitats del model (Ref. tutorial 7)<br />
# Planteja't si la interfície que tens ara mateix et serveix com a ''backend'' o si necessita alguna restricció.<br />
#* Per restringir i personalitzar les dades visualitzades en el backend pots personalitzar-ho a admin.py seguint la [https://docs.djangoproject.com/en/2.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_queryset doc oficial de Django Admin Site].<br />
#* Si vols [https://stackoverflow.com/questions/45393989/django-queryset-filter-foreignkey filtrar per FKs mira't aquest post] o bé la [https://docs.djangoproject.com/en/2.0/ref/models/querysets/ doc oficial del Queryset].<br />
#* Mira si algun dels camps dels formularis de detall convé posar-los en read-only.<br />
# Planteja la lògica de negoci.<br />
# Implementa restriccions del backend perquè s'adapti a la lògica de negoci.<br />
<br />
<br><br />
<br />
== Django Auth i User model ==<br />
Per utilitzar el model ''User'' de Django dins del teu projecte (per exemple, per fer una Foreign Key) només cal importar-lo i utilitzar ForeignKey.<br />
<br />
Per Django 1.x:<br />
from django.contrib.auth import User<br />
class MyModel(models.Model):<br />
...<br />
usuari = models.ForeignKey(User)<br />
...<br />
<br />
Per [https://docs.djangoproject.com/en/2.0/topics/auth/customizing/#referencing-the-user-model referenciar el User] en Django 2.x:<br />
from django.conf import settings<br />
from django.db import models<br />
<br />
class Article(models.Model):<br />
author = models.ForeignKey(<br />
settings.AUTH_USER_MODEL,<br />
on_delete=models.CASCADE,<br />
)<br />
<br />
Per ampliar el mòdul de ''Auth'' de Django i afegir camps al User, es pot fer de diverses maneres. Aquest article n'explica molt bé 4 d'elles:<br />
https://simpleisbetterthancomplex.com/tutorial/2016/07/22/how-to-extend-django-user-model.html#onetoone<br />
<br />
<br><br />
<br />
== Bases de dades ==<br />
<br />
=== Migracions ===<br />
Hauràs vist que en el moment de fer "migration" Django crea la base de dades. Si canviem el nostre model (a models.py), per exemple afegint camps nous, està clar que el contingut de la BD hauria de canviar també. A aquest procés en diem migració, tot i que el context de migració està més associat a traslladar les dades d'un SGBD a un altre.<br />
<br />
En versions anteriors de Django teniem el problema que si canviàvem el model havíem de refer tota la base de dades de nou. La eina "South" va permetre migrar les dades, i finalment s'ha integrat dins de Django.<br />
<br />
Un cop fet un canvi en el model, caldrà executar:<br />
$ python manage makemigrations <opcional:nom_app><br />
$ python manage migrate<br />
<br />
=== SQLite vs MySQL ===<br />
Per defecte Django utilitza SQLite ja que és més senzilla de configurar i guarda les dades en un arxiu db.sqlite a l'arrel del projecte.<br />
<br />
Per diversos motius ens pot interessar canviar el motor de la BD a un de més sofisticat, com pot ser MySQL. Alguns d'aquests motius son:<br />
* Eficiència<br />
* Multithreading<br />
* Ús de tipus de dades més sofisticats com la Geolocalització<br />
<br />
'''Per canviar a MySQL hem de fer les següents passes:'''<br />
<br />
Instal·lar els següents paquets del sistema:<br />
$ sudo apt-get install libmysqlclient-dev python3-dev gdal-bin python3-mysql.connector python3-mysqldb libssl-dev<br />
<br />
Instal·lar els següents paquets del [[Virtualenv]]:<br />
* Per python 2.x:<pre>(env) $ pip install mysql-python</pre><br />
* Per python 3.x:<pre>(env) $ pip install mysql-connector-python mysqlclient</pre><br />
<br />
Canviar el ''backend'' de BD de ''settings.py'':<br />
DATABASES = {<br />
'default': {<br />
'ENGINE': 'django.db.backends.mysql',<br />
#'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),<br />
'PASSWORD': 'lalalaxxx',<br />
'HOST': 'localhost',<br />
'PORT': '3306',<br />
'NAME': 'twitter',<br />
'USER': 'projectex',<br />
}<br />
}<br />
<br />
Per [https://ruddra.com/posts/install-mysqlclient-macos/#step-four-install-xcode-select instal·lar MySQL connector en Mac OS] és un pèl mes complicat que en Linux.<br />
<br />
<br><br />
<br />
== Frontend ==<br />
<br />
Pots practicar alguns [https://bytes.cat/doku.php/django_frontend elements previs al tutorial de frontend en aquest mini tutorial].<br />
<br />
Tutorials:<br />
* https://www.tutorialspoint.com/django/index.htm<br />
* Oficials de Django:<br />
** [https://docs.djangoproject.com/en/1.11/intro/tutorial03/ Django Tutorial Part 3: views, templates]<br />
** [https://docs.djangoproject.com/en/1.11/intro/tutorial04/ Django Tutorial Part 4: forms]<br />
** [https://docs.djangoproject.com/en/1.11/intro/tutorial06/ Django Tutorial Part 6: fitxers estàtics i CSS]<br />
<br />
Documentació rellevant:<br />
* Class-based views i generic views:<br />
** https://docs.djangoproject.com/en/1.11/topics/class-based-views/<br />
** https://docs.djangoproject.com/en/1.11/ref/class-based-views/generic-display/<br />
** https://docs.djangoproject.com/en/1.11/ref/class-based-views/generic-editing/<br />
<br />
Plug-ins:<br />
* django-money<br />
* django-richtextfield<br />
* django-oauth-toolkit<br />
<br />
=== Autenticació en el frontend ===<br />
Per fer la autenticació en el front-end podriem fer-nos la nostra pròpia ''view'' seguint les indicacions de la doc oficial:<br />
https://docs.djangoproject.com/en/1.11/topics/auth/default/<br />
<br />
...però és més pràctic utiltizar un seguit de views predefinides que son típiques i ens serviran prou bé:<br />
https://docs.djangoproject.com/en/1.11/topics/auth/default/#using-the-views<br />
<br />
Un cop fet el sistema de login/logout, serà fàcil consultar en tot moment quin user tenim logat mitjançant la ''request'':<br />
def view_tal(request):<br />
usuari = request.user<br />
<br />
Per augmentar les possibilitats d'autorització, és interessant tenir en compte els següents plugins i hacks:<br />
* [https://stackoverflow.com/questions/37332190/django-login-with-email Canviar el username per l'email]<br />
* Gestionar accessos a les views amb Decorators:<br />
** [https://docs.djangoproject.com/en/1.11/topics/auth/default/#the-permission-required-decorator @permission_required]<br />
** @login_required<br />
** [https://docs.djangoproject.com/en/1.11/topics/auth/default/#the-loginrequired-mixin LoginRequiredMixin]<br />
** ...<br />
<br />
=== Ampliar el model del User ===<br />
Sovint ens fa falta ampliar els atributs o comportament del User de Django. Hi ha diverses de fer-ho. Aquest article ens dona diverses opcions i ens explica quan utiltizar-les:<br />
https://simpleisbetterthancomplex.com/tutorial/2016/07/22/how-to-extend-django-user-model.html<br />
<br />
Resumint:<br />
* Utilitzant un Proxy Model<br />
* Creant un Profile relacionat amb el User amb un One-to-One relationship<br />
* Derivant un CustomUser de AbstractBaseUser<br />
* Derivant un CustomUser de AbstractUser<br />
<br />
<br />
=== OAuth ===<br />
OAuth es mereix comentaris a part, ja que és molt útil per les xarxes socials i cada dia esdevé més important:<br />
* Primer, una mica d'[http://www.thegameofcode.com/2012/07/conceptos-basicos-de-oauth2.html explicacions sobre OAuth] : imprescindible lectura!!<br />
* [https://fosstack.com/how-to-add-google-authentication-in-django/ Tutorial per utilitzar social-auth-app-django] : el típic plugin per poder logar-nos a la nostra app via Facebook o Google.<br />
** Si et dona algun error quan et loguis, pensa a activar Google+ a les apis de Google.<br />
* [https://django-oauth-toolkit.readthedocs.io/en/latest/index.html Django-OAuth-Toolkit]: per fer nosaltres de servidor OAuth (cas poc habitual)<br />
* Un cop t'hagis familiaritzat amb aquestes llibreries, pots ampliar com treballar amb Oauth2 per accedir als recursos de Google API com contactes, calendaris, etc. És complexe, però [https://developers.google.com/people/quickstart/python pots començar pel Google APIs Quickstart]<br />
<br />
<br><br />
<br />
== Projecte amb Django ==<br />
Seguidament proposem una guia per realitzar un projecte amb Django, un cop hagis finalitzat els tutorials anteriorment esmentats.<br />
<br />
Comentarem les diferents passes amb aquest projecte d'exemple, es tracta d'una llista de karaoke per demanar torn, penjar el vídeo i votar els temes:<br />
https://github.com/emieza/karaokelist<br />
<br />
Guia:<br />
# '''Preparació''':<br />
## Clarificar la funcionalitat del projecte.<br />
## Crear entorn [[Virtualenv]]<pre>$ virtualenv env</pre><br />
##* Activar entorn<pre>$ source env/bin/activate</pre><br />
##* Instal·lar Django<pre>(env) $ pip3 install django</pre><br />
## Crear projecte Django<pre>(env) $ django-admin startproject</pre><br />
##* Crear app dintre del projecte<pre>(env) $ python manage startapp</pre><br />
## Crear [[Git: comandes|repositori de GIT]] per gestionar l'equip de treball .<br />
# '''Model i backend''':<br />
## Clarificar els objectes i taules de la BD, en particular les FK. Les implementarem al [https://github.com/emieza/karaokelist/blob/master/karaoke/models.py '''models.py''' , com podem veure a l'exemple]:<br />
##* Items: temes a cantar (nom del cantant, URL del vídeo, etc.)<br />
##* Vots: (likes) vots emesos per al tema seleccionat. Es limita a un vot per IP emissora i tema (item).<br />
## Afegir la app de Django a la variable [https://docs.djangoproject.com/es/2.1/ref/settings/#std:setting-INSTALLED_APPS INSTALLED_APPS] de <code>settings.py</code> (si no ho fem, no s'inclouran els seus models a les migracions).<br />
## Crear migració del model: <pre>(env) $ python manage.py makemigrations</pre><br />
## Crear DB: <pre>(env) $ python manage.py migrate</pre><br />
## [https://github.com/emieza/karaokelist/blob/master/karaoke/admin.py Registrar models i personalitzar interfície d'administrador a '''admin.py'''].<br />
## Crear superuser (admin): <pre>(env) $ python manage.py createsuperuser</pre><br />
## Arrencar app: <pre>(env) $ python manage.py runserver</pre><br />
## Testejar el ''backend'' a través de la URL<pre>http://localhost:8000/admin/</pre><br />
# Ampliació del ''backend'':<br />
## Personalitzar els mètodes __str__ de cada model, per mostrar-los de forma més amigable.<br />
## Personalitzar la visualització dels models en <code>admin.py</code> : list_display , list_editable, list_filter<br />
## Afegir models relacionats amb ''inlines''<br />
# '''Frontend''':<br />
## Clarificar les rutes necessàries.<br />
## [https://github.com/emieza/karaokelist/blob/master/karaokelist/urls.py Implementar les rutes decidides a '''urls.py'''].<br />
## Crea les views (controladors) pertinents a [https://github.com/emieza/karaokelist/blob/master/karaoke/views.py '''views.py'''].<br />
## Crea les [https://github.com/emieza/karaokelist/tree/master/karaoke/templates/karaoke plantilles pertinents a la '''carpeta ''templates'''''].<br />
## Recorda crear una [https://github.com/emieza/karaokelist/blob/master/karaoke/templates/karaoke/base.html plantilla base] i estendre les altres plantilles ([https://github.com/emieza/karaokelist/blob/master/karaoke/templates/karaoke/create_item.html per exemple aquesta de crear_item]) utilitzant les sentències <nowiki>{% block %} i {% extends %}</nowiki><br />
<br />
<br><br />
<br />
== Desplegament ==<br />
Desplegament:<br />
* En servidor web mitjançant WSGI en Apache i Nginx<br />
* En servidor d'aplicacions: Heroku, Openshift<br />
<br />
Podeu llegir l'article [[Django en producció]] per veure diverses opcions.<br />
<br />
<br><br />
<br />
== Possibles ampliacions ==<br />
* Investiga com utilitzar els Users de Django i com ampliar els camps dels què disposa.<br />
* Amplia els coneixements del ''backend'':<br />
** Funcionalitat dels usuaris i grups de Django, i permisos.<br />
** Filtrar els resultats de l'admin segons l'usuari registrat. Per exemple, en una botiga, els usuaris podrien veure només les seves comandes. El superadmin podria veure-les, en canvi, totes.<br />
* Cerca com recuperar contrasenya en el admin de Django.<br />
* Cerca com enviar emails amb Django.<br />
* Investiga les capacitats multillenguatge de les plantilles de Django.<br />
* Cerca com ampliar les comandes de manage.py, per exemple per importar usuaris d'un arxiu .CSV<br />
* Cerca com canviar les plantilles per defecte de l'admin de Django.<br />
<br />
<br></div>Enrichttps://cacauet.org/wiki/index.php?title=Git:_comandes&diff=4207Git: comandes2020-04-17T23:09:12Z<p>Enric: /* Introducció */</p>
<hr />
<div><nowiki>#FpInfor #DawMp08 #DawMp08Uf04 #DawMp08Uf4</nowiki><br />
<br />
GIT és un sistema de control de versionat semblant a SVN (Subversion). Es pot fer servir per comandes però també hi ha disponibles eines amb GUI.<br />
<br />
== Introducció ==<br />
* Conceptes previs: [[Control de versions]]<br />
* Llibre de referència (en espanyol) http://git-scm.com/book/es<br />
* Interfície gràfica per GIT:<br />
** http://www.rabbitvcs.org/<br />
** http://askubuntu.com/questions/4788/nautilus-git-integration<br />
* Una bona xuleta de totes les funcions de GIT: https://ndpsoftware.com/git-cheatsheet.html<br />
<br />
<br />
Un dels principals atractius és el repositori públic https://github.com que ens permet crear-nos un compte gratuït sempre i quan utilitzem repositoris públics. Pels repositoris privats cal pagar.<br />
<br />
En qualsevol moment podem demanar ajuda sobre una comanda mitjançant:<br />
$ man git-<comanda><br />
Per exemple:<br />
$ man git-status<br />
<br />
== Exemple: clonar un projecte ==<br />
Pots provar de clonar un parell de projectes:<br />
* [https://github.com/emieza/pyges Pyges]: un CMS basat en Pyramid per Google App Engine (GAE).<br />
* [https://github.com/emieza/egipcis Egipcis]: senzill exemple d'autenticació amb Pyramid.<br />
<br />
Instal·la el git al teu PC:<br />
$ sudo apt-get install git<br />
<br />
Clona el projecte Faceschool:<br />
$ git clone https://github.com/lacetans/faceschool.git<br />
<br />
Se't descarregarà a la teva màquina. Activa el virtualenv i posa'l en marxa:<br />
$ source ~/env/bin/activate<br />
$ python manage.py runserver<br />
<br />
Prova-ho també amb el projecte "Egipcis" (és més senzill i triga menys a descarregar).<br />
https://github.com/emieza/egipcis.git<br />
<br />
== Crear un projecte nou ==<br />
# Crea el teu compte a http://github.com<br />
# Crea el nou repositori des de la web (és més fàcil).<br />
#* També ho pots fer amb comandes: https://help.github.com/articles/create-a-repo<br />
# Abans de fer un commit penseu a fer un [https://help.github.com/articles/set-up-git setup del GIT] a la vostra màquina (no és imprescindible però convenient més que res per deixar el nom d'usuari i email a cada commit que fem).<br />
# Feu un '''clone''' del repositori creat.<br />
# Afegiu l''''arxiu .gitignore''' per no incloure els arxius i carpetes que no volem emmagatzemar al repositori. Com a mínim seran (pel cas dels Pyramid ''scaffolds''):<br />
#* *.pyc<br />
#* <nomdelpaquet>-egg.info<br />
# Copiar els arxius del scaffold (o el projecte que sigui) dins del directori clonat.<br />
# Fer un '''add''' de tots els arxius (git add "*").<br />
# Fer un '''commit''' i un '''push''' per actualitzar.<br />
<br />
=== Nou projecte a GITHUB amb comandes locals ===<br />
Crear nou projecte a Github:<br />
$ curl -u 'USER' https://api.github.com/user/repos -d '{"name":"REPO"}'<br />
...òbviament canviant USER pel teu usuari i REPO pel nom del repositori que vols crear. La URL es queda tal qual.<br />
<br />
Si vols crear un projecte en una organització enlloc de dins d'un compte d'usuari:<br />
$ curl -u 'USER' https://api.github.com/orgs/:org_name/repos -d '{"name":"REPO"}'<br />
<br />
Si volem crear un nou projecte i pujar-lo seguidament:<br />
* Crear un projecte del què sigui (PHP, Python, C++, etc.)<br />
* Inicialitzar la carpeta del projecte:<pre>$ git init</pre><br />
* Afegir .gitignore a l'arrel del projecte per evitar afegir arxius indesitjats (com per exemple els .pyc)<br />
* Afegir tots els arxius:<pre>$ git add .</pre><br />
* Consolidar canvis locals:<pre>$ git commit -am "primer commit"</pre><br />
* Afegir remot del Github:<pre>$ git remote add origin https://github.com/USER/REPO.git</pre><br />
* Pujar els arxius al repo:<pre>$ git push origin master</pre><br />
<br />
<br><br />
<br />
== Comandes ==<br />
Per crear un projete el més fàcil és fer-ho des de la interfície web del github.<br />
<br />
Per afegir arxius, directoris, etc. al projecte<br />
$ git add <arxiu1> <arxiu2> ...<br />
<br />
Per descarregar un projecte de nou:<br />
$ git clone <url><br />
La "url" del github sol ser https://github.com/username/projecte.git<br />
<br />
<br />
Per conèixer l'estat del projecte (arxius modificats, afegits, esborrats, etc.):<br />
$ git status<br />
<br />
Per "gravar" tots els canvis fets durant la sessió:<br />
$ git commit -a<br />
Per "gravar" els canvis d'un sol arxiu:<br />
$ git commit <arxiu1> <arxiu2> ...<br />
<br />
Per carregar els canvis al repositori:<br />
$ git push<br />
<br />
Per descarregar els canvis del repositori:<br />
$ git pull<br />
<br />
<br><br />
<br />
== Branch ==<br />
Per fer "branques" al nostre repositori, primer l'heu d'haver clonat, per exemple el projecte Pyges anteriorment citat.<br />
<br />
Abans de res, serà més fàcil si creem la branca des de la web de GitHub. Això és important abans de fer el PUSH.<br />
<br />
Crear una branca en el nostre repositori local:<br />
$ git branch <nom_branca><br />
<br />
I després pujar-la al nostre repositori:<br />
$ git push <nom_branca><br />
<br />
Per exemple:<br />
$ git branch auth<br />
$ git push auth<br />
<br />
<br />
Per veure quines branques estan disponibles i quina tenim activa (*):<br />
$ git branch -a<br />
<br />
Per canviar-nos de branca:<br />
$ git checkout <nom_branca><br />
<br />
<code>...editem el nostre codi...</code><br />
<br />
En aquest punt, cal que creem la branca en el remot a través de la web del projecte en GitHub.com (si no ho hem fet ja).<br />
<br />
Finalment carreguem els canvis:<br />
$ git push<br />
(ens demanarà ususari i contrasenya, i òbviament hem de tenir permsisos d'escriptura en el projecte)<br />
<br />
<br><br />
<br />
== Merge ==<br />
Una bona referència: http://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging<br />
<br />
En realitat cal 1r fer un checkout de la branca principal i després unir-li la que vols fusionar (que desapareixerà):<br />
<pre><br />
$ git checkout master<br />
$ git merge hotfix<br />
Updating f42c576..3a0874c<br />
Fast-forward<br />
index.html | 2 ++<br />
1 file changed, 2 insertions(+)<br />
</pre><br />
<br />
<br><br />
<br />
== Creant un repo accessible per SSH ==<br />
Aquí veurem com crear un repositori en un servidor on tenim accés per SSH.<br />
<br />
Al '''servidor''' podem crear un repositori remot amb:<br />
$ git init --bare <nom_carpeta><br />
<br />
Al '''client''' podem crear un repositori local entrant a la carpeta i fent (ull, carpeta remota amb path absolut):<br />
$ git init<br />
$ git remote add origin <usuari>@<servidor>:<carpeta_remota><br />
$ touch README<br />
$ git add .<br />
$ git commit -a<br />
$ git push origin master<br />
<br />
...i ja el tenim.<br />
<br />
Podem clonar des de qualsevol lloc amb:<br />
$ git clone <usuari>@<servidor>:<carpeta_remota><br />
<br />
<br><br />
<br />
== Creant una versió Release ==<br />
Ens solem referir a una ''Release'' a una versió concreta d'un programari que "lliurem" al públic o a un client. La traducció literal de ''release'' és exactament "lliurar".<br />
<br />
Quan parlem de ''releases'' parlem de publicar-les a una web, com Github o Gitlab.<br />
<br />
El sistema de versionat GIT només pot etiquetar un commit concret del nostre repositori. Per poder fer una ''release'' a Github, caldrà que abans etiqueteu (tag) el vostre commit de la vostra branca desitjada, i posteriorment creeu la ''release'' amb la interfície de Github.<br />
<br />
Aquí teniu la doc oficial:<br />
<br />
* Git tagging (etiquetado): https://git-scm.com/book/es/v1/Fundamentos-de-Git-Creando-etiquetas<br />
* Github relases: https://help.github.com/articles/creating-releases/</div>Enric