PHP Modelo - Vista - Controlador

De MediaWiki
Saltar a: navegación, buscar

Introdución

  • Existen moitos frameworks PHP que nos permiten programar seguindo o patrón de deseño de software Model-View-Controller.


  • Nota: Como editor de texto para manexar os arquivos do proxecto no framework Laravel recomendo instalar Brackets.

Manuais

Instalación

  • Primeiro vídeo: basicamente fala de instalar composer e con el instalar Laravel.
Para instalar Laravel necesitamos:
  • Ter php instalado.
  • Ter composer instalador.
  • Ter git instalado.


  • Os pasos para instalar php os tedes na wiki.
  • Os pasos para instalar composer os tedes na wiki.
  • Os pasos para instalar git os tedes na wiki.
  • Os pasos para instalar Mysql, un xestor de bases de datos, os tedes na wiki.


  • Para instalar e crear un proxecto Laravel, dende consola, sen ser root,escribiremos situados no cartafol onde queiramos crear o proxecto: composer create-project laravel/laravel nome_proxecto "5.1.*"
Sendo 5.1 a versión de Laravel a utilizar
Nota: Se non poñemos a versión, descargará a última versión de Laravel que sexa compatible coa versión de PHP instalada.
  • Para lanzar o servidor web do proxecto creado, estando no cartafol raíz de dito proxecto, escribiremos: php artisan serve
Aparecerá unha mensaxe informando de que o servidor web está levantado e escoitando no porto 8000. Escribiremos na URL do navegador: http://localhost:8000
  • Para saber a versión do framework Laravel que temos instalado podemos escribir a seguinte orde dende o cartafol raíz do proxecto creado:
php artisan --version


  • Artisan é un comando de Laravel. Podedes consultalo neste enlace.
  • Para executar un comando de artisan temos que escribir: php artisan comando dende o raíz do sitio web creado.
  • Se escribimos soamente php artisan aparecen a lista de posibles comandos que podemos executar.
  • Para obter a axuda dun comando específico temos que escribir: php artisan help comando.
Por exemplo: php artisan make:controller

Primeiros pasos

Nesta parte imos usar diferentes 'verbos' do protocolo HTTP.
Instalaremos o complemento de firefox HttpRequester para simular o envío utilizando os verbos (get, post, put,...).
Exercicios: Unha vez lido os puntos anteriores deberedes facer diferentes rutas utilizando diferentes verbos có complemento.
Coidado coa orde das rutas, xa que se temos varias rutas nas que especificamos verbos que coincidan, cargará primeiro as que estean ao final do arquivo (por exemplo, unha con get e outra con match(['get']).
No caso das rutas que veñen na URL, se temos varias entradas no arquivo routes.php que coincidan coa mesma URL, cargará primeiro a que estea antes no arquivo routes.php.
EXEMPLO:
Php laravel 1.jpg
Exemplo de envío utilizando o método POST a url http://localhost:8000/testpost, sendo 'testpost' unha ruta previamente definida:
  1. Route::post('/testpost',function() {
  2.    echo "Isto é un post a /testpost";
  3. });
  • Durante o manual fala de utilizar un controlador para recibir un parámetro.
Se queredes facer a proba teredes que definir un arquivo php no cartafol: /proxecto/app/Http/Controllers/ControladorProba.php
O nome ControladorProba.php é un exemplo.
O código de dito arquivo pode ser algo parecido a isto:
  1. <?php
  2.  
  3. namespace App\Http\Controllers;
  4.  
  5. use App\User;
  6. use App\Http\Controllers\Controller;
  7.  
  8. class ControladorProba extends Controller {
  9.    
  10.     public function funcionControlador($id){
  11.         return "Esta información ven dun controlador especifico. Recibido o dato $id";
  12.     }
  13.    
  14. }


Como se pode ver, o nome da clase é igual ao nome do arquivo php. Deriva da clase Controller.
Leva unha función de nome 'funcionControlador' cun parámetro.
Agora debemos crear a ruta que vai facer uso de esta clase controladora:
Modificamos o arquivo routes.php.
Route::get('controlador/{identificador}','ControladorProba@funcionControlador');
Como vemos, agora en vez de ter unha función anónima, temos o nome da clase controladora (ControladorProba) e o nome da función ao que vai chamar (funcionControlador). Dita función vai levar un parámetro que está definido na parte Get da orde route ({identificador}).
Agora podemos poñer unha URL da forma: http://localhost:8000/controlador/1000
Enviaremos o dato 1000 á clase controladora.


  • Recurso:
  • Páxina web para verificar unha expresión regular: regex101.com.


  • Exercicios:
  • Crea unha ruta con dous parámetros que sexan opcionais. Dalle un valor por defecto a cada un deles.
  • Crea unha ruta que acepte como parámetro unha expresión regular de 5 números do 0 ao 7.
  • Crea outra ruta que acepte como parámetro unha expresión regular que acepta un número-letras (número guión letras)


Solucións:
  1. Route::get('/opcionais/{param1?}/{param2?}',function($par1=1,$par2='valor defecto'){
  2.    echo "O param1 ten valor $par1 e o param2 ten valor $par2";
  3. });
  4.  
  5. Route::get('/rutaNumeros/{numero}',function($numero){
  6.    echo "5 números de 0 ao 7: $numero";    
  7. })->where(array('numero' => '[0-7]{5}'));
  8.  
  9. Route::get('/rutaNumerosCadea/{dato}',function($dato){
  10.    echo "Dato numérico-texto: $dato";    
  11. })->where(array('dato' => '[0-7]+-[a-z|A-Z]+'));



  • Mellora: A validación dos parámetros que enviamos dende a URL para que cumpran unhas determinadas condicións (por exemplo, no caso dun nif, que teña 8 números e unha letra), o podemos implementar da seguinte forma:
  1. Route::pattern('id', '\d+');
  2. Route::pattern('username', '[a-z]{3,16}');
  3.  
  4.  
  5. Route::get('usuarios/{id}', 'UserController@obterInformacion');
  6. Route::get('productos/{id}', 'ProductController@obterInformacion');
No exemplo, ao parámetro {id} estámoslle a indicar que sexa un número.
Establecemos con 'pattern' as condicións que teñen que cumprir os parámetros da URL.
Desta forma, o parámetro {id} terá que cumprir as regras indicadas en todas as rutas onde sexa empregado.
Máis información neste enlace.


  • Para poder ver as rutas que imos creando dispoñemos dun comando artisan:
  1. php artisan route:list
Amosa nunha táboa todas as rutas, métodos e accións. Por cada ruta amosa os filtros asociados (o veremos posteriormente). Este comando vainos servir para comprobar que todas as rutas e filtros definimos estean creados correctamente.


  • Se queremos xestionar calquera ruta que sexa enviada polo usuario temos que facer uso da ruta 'any' desta forma:
Arquivo: /app/Http/routes.php
  1. Route::get('/{any}',function(){
  2.    return 'Páxina non atopada';
  3. })->where('any','.*');

Importante: A ruta debe ir ao final do arquivo routes para que primeiro xestione as que ten definidas.


Vistas

Exemplo 1 do manual anterior. Creación dunha vista

  • Lembrar que as vistas é onde se atopa o código que vai amosarse ao usuario (html,css,javascript).
A vista foi creada previamente no cartafol: /raiz_proxecto/resources/views
Arquivo: algo.blade.php
  1. <!DOCTYPE html>
  2. <html lang="es">
  3. <head>
  4.         <meta charset="UTF-8">
  5.         <title>Isto é unha vista de proba</title>
  6. </head>
  7. <body>
  8.         <h1>Vista "algo"</h1>
  9.         <p>Esta é a miña primeira vista en Laravel</p>
  10. </body>
  11. </html>
Un exemplo de código dunha ruta (routes.php) cun if condicional para preguntar se a vista existe dende .
  1. Route::get('vistas',function(){
  2.    if(view()->exists("algo")){
  3.         return view('algo');
  4.    }else {
  5.        echo "A vista non existe";
  6.    }
  7. });

Exemplo 2 do manual anterior. Creación dunha vista nun cartafol e paso de parámetros á vista dende a ruta

  • Seguindo o exemplo do manual, imos crear unha vista no cartafol /sitio_raiz/resources/views/outro.
Arquivo: index.blade.php
  1. <!DOCTYPE html>
  2. <html lang="es">
  3. <head>
  4.         <meta charset="UTF-8">
  5.         <title>Isto é unha vista de proba dentro dun cartafol</title>
  6. </head>
  7. <body>
  8.         <h1>Vista "algo" dentro dun cartafol</h1>
  9.     <p>Benvido {{$nomeVista}}. Xa vexo que tes {{$idadeVista}} anos :)</p>
  10. </body>
  11. </html>
  • Liña 9: Como vemos imos facer uso de dúas variables que van vir dende a ruta (poderían vir da mesma forma dende o controlador). Como estamos nun arquivo blade.php podemos facer uso da sintaxe das plantillas, no que para 'imprimir as variables' utilizamos {{ }}. Se queremos podemos facer uso da sintaxe 'clásica' de PHP, poñendo <?php echo $variable ?> ou a sintaxe abreviada:<?= $variable ?>.
Como norma xeral imos utilizar a sintaxe 'blade' xa que fai que o código sexa moito mais lexible.
Podedes ver as normas xerais de uso neste enlace.



Arquivo: routes.php
  1. Route::get('vistas',function(){
  2.    if(view()->exists("outro.index")){
  3.        $nome='Angel';
  4.        $idade=45;
  5.        return view('outro.index',[
  6.             'nomeVista' => $nome,
  7.             'idadeVista' => $idade
  8.         ]);
  9.    }else {
  10.        echo "A vista non existe";
  11.    }
  12. });
  • Como vemos no return view enviamos en forma de array as variables que imos utilizar na vista (nomeVista e idadeVista) cos valores das variables definidas na ruta ($nome e $idade).
  • Exercicio proposto: Modifica a ruta anterior para que reciba dous parámetros e sexan os que se envíen á vista (Nota: podemos ter as dúas vistas á vez)



Solución:
  1. Route::get('vistas/{nome}/{idade}',function($nome,$idade){
  2.    if(view()->exists("outro.index")){
  3.        return view('outro.index',[
  4.             'nomeVista' => $nome,
  5.             'idadeVista' => $idade
  6.         ]);
  7.    }else {
  8.        echo "A vista non existe";
  9.    }
  10. });


Exercicio 1

  • Le o seguinte enlace e crea unha vista utilizando unha plantilla. Todo debe ser creado dentro dun cartafol de nome 'exemplo_plantillas'.
Deberás crear primeiro a plantilla cunha estrutura formada por un menú vertical na parte esquerda, cun ancho do 35% do total e un contido ao carón do menú.
Crea dúas vistas que herden esta plantilla e engade algún contido.
Fai que a vista sexa cargada cando na URL poñamos 'vista_plantilla/1' cargará a vista primeira e 'vista_plantilla/2' cargará a vista segunda.
Crea dúas entradas de menú e que cada un 'cargue' unha das vistas.

Solución Exercicio 1

Arquivo: /resources/views/exemplo_plantillas/plantilla.blade.php
  1. <!DOCTYPE html>
  2. <html>
  3.     <head>
  4.         <title>Laravel</title>
  5.  
  6.         <style>
  7.             .menu{
  8.                 float: left;
  9.                 width: 30%;
  10.                 padding-left: 5px;
  11.             }
  12.             .menu a{
  13.                 display: block;
  14.             }
  15.             .contido{
  16.                 float: left;
  17.                 width: 65%;
  18.             }
  19.        
  20.         </style>
  21.     </head>
  22.     <body>
  23.         <div class="menu">
  24.             <a href='/vista_plantilla/1/'>Vista 1</a>
  25.             <a href='/vista_plantilla/2/'>Vista 2</a>
  26.         </div>
  27.          <div class="contido">
  28.             @yield('content')
  29.         </div>
  30.     </body>
  31. </html>


Arquivo: /resources/views/exemplo_plantillas/vista1.blade.php
  1. @extends('exemplo_plantillas.plantilla');
  2.  
  3.  
  4. @section('content')
  5. <p>Este é o contido da vista 1</p>
  6. @endsection
Arquivo: /resources/views/exemplo_plantillas/vista2.blade.php
  1. @extends('exemplo_plantillas.plantilla');
  2.  
  3.  
  4. @section('content')
  5. <h5>Este é o contido da vista 2</h5>
  6. @endsection


Arquivo: /http/routes.php
  1. Route::get('vista_plantilla/{numero}',function($numero){
  2.     return view("exemplo_plantillas.vista$numero");
  3. })->where(['numero'=>'[1-2]']);

Controlador

A diferenza do feito ata o de agora, non imos a chamar á vista directamente dende a páxina 'router.php', se non que imos chamar a unha páxina 'controller' que é a que vai invocar a vista.
Ven ser unha ponte entre o controlador frontal e as vistas, e vai ser dende onde chamemos ao modelo para obter ou enviar datos á base de datos.
  • As páxinas controladoras se atopan no cartafol: app/Http/Controllers

Exercicio 1. Creación dun controlador

  • Para crear unha páxina controlador podemos facer uso do comando php artisan dende o raíz do noso proxecto laravel da forma:
  1. php artisan make:controller CategoriasController
Isto creará unha páxina de nome 'CategoriasController' no cartafol 'app/Http/Controllers'.


  • Para crear un controlador cuns métodos definidos por defecto (por exemplo, se crea o método create onde iría a vista (o formulario) que daría de alta) teríamos que escribir:
  1. php artisan make:controller --resource CategoriasController
Nota: Soamente a partires de Laravel 5.4


  • Nota: Podemos crear clases controladoras dentro de cartafoles da seguinte forma:
  1. php artisan make:controller CARTAFOL/CategoriasController



  • Modifica o exercicio anterior e fai que a vista sexa cargada dende o controlador.
A forma de carga a vista é a mesma (return view) pero agora terás que enviarlle os datos que van chegar á clase controladora en forma de parámetros dende route.php.




Solución:

Arquivo routes.php

  1. Route::get('vistas/{nome}/{idade}','DatosController@amosarVista');


Arquivo DatosController.php

  1. <?php
  2.  
  3. namespace App\Http\Controllers;
  4.  
  5. use Illuminate\Http\Request;
  6.  
  7. use App\Http\Requests;
  8.  
  9. class DatosController extends Controller
  10. {
  11.     // Poñemos $param_ para amosar como non teñen que chamarse igual que os parámetros definidos en router.php
  12.     public function amosarVista($param_nome,$param_idade){
  13.       return view('outro.index',[
  14.             'nomeVista' => $param_nome,
  15.             'idadeVista' => $param_idade
  16.         ]);
  17.     }
  18. }


Nota: Indicar que tamén podemos enviar array de datos á vista da seguinte forma

Arquivo DatosController.php

  1.     public function amosarVista($param_nome,$param_idade){
  2.         $datos = array();
  3.         $datos[]=1;
  4.         $datos[]=2;
  5.         return view('outro.index',[
  6.             'nomeVista' => $param_nome,
  7.             'idadeVista' => $param_idade,
  8.             'datosArray' => $datos
  9.         ]);
  10.     }


Arquivo index.blade.php (a vista)

  1.     ...............
  2.    <p>Volcado dos datos do array como fixemos en PHP:
  3.     <?php
  4.         var_dump($datosArray);
  5.     ?>
  6.     </p>
  7.     <p>
  8.     Forma de percorrer un array en blade (máis lexible)<br />
  9.     @foreach ($datosArray as $n)
  10.         Valor: {{ $n }}
  11.     @endforeach
  12.     </p>    
  13.  
  14.     <p>
  15.         Un dato en PHP:<?= $datosArray[0]?><br />
  16.         Un dato en Blade:{{$datosArray[1]}}
  17.     </p>
  18. </body>

Exercicio 2. Creación dun controlador

  • Crea unha nova ruta que responda a petición get: www.oteusitio.es/buscar/nif/, sendo nif un nif válido (9 díxitos e unha letra).
En caso de que sexa correcto, enviarase a unha vista de nome DatosAlumnos.blade.php, creada no cartafol ALUMNOS/, o nif xunto cun array cos seguintes datos: 'nome'=>'Angel', 'Idade=>45'. Dita vista amosará dentro dun <h5> e en cor vermella os datos enviados, en forma de lista desordenada.
O control de se se carga unha vista ou outra deberase facerse dende unha clase Controller de nome AlumnosController, dentro dun cartafol ALUMNOS/, e unha función de nome 'buscarAlumnos'.



Solución:

Arquivo routes.php

  1. Route::get('buscar/{nif}','ALUMNOS\AlumnosController@buscarAlumnos')->where(['nif' => '[0-9]{8}[A-Z]']);


Arquivo ALUMNOS/AlumnosController.php

  1. <?php
  2.  
  3. namespace App\Http\Controllers\ALUMNOS;
  4.  
  5. use Illuminate\Http\Request;
  6.  
  7. use App\Http\Requests;
  8. use App\Http\Controllers\Controller;
  9.  
  10. class AlumnosController extends Controller
  11. {
  12.     public function buscarAlumnos($nif){
  13.         if (view()->exists('ALUMNOS.DatosAlumnos')){
  14.             $datos=['nome'=>'Angel','idade'=>45];
  15.             return view ('ALUMNOS.DatosAlumnos',[
  16.             'nif' => $nif,
  17.             'datos' => $datos]);
  18.         }
  19.         else{
  20.             return 'Non se pode cargar a páxina...';
  21.         }
  22.        
  23.        
  24.     }
  25. }


Arquivo ALUMNOS/DatosAlumnos.blade.php

  1. <!DOCTYPE html>
  2. <html lang="es">
  3. <head>
  4.         <meta charset="UTF-8">
  5.         <title>Datos do alumno buscado</title>
  6. </head>
  7. <body>
  8.  
  9.     <ul>
  10.         <li>Nif:{{ $nif }}</li>
  11.     @foreach ($datos as $key=>$valor)
  12.         <li>{{ $key }}:{{ $valor }}</li>
  13.     @endforeach
  14.     </ul>
  15.  
  16.  
  17. </body>
  18. </html>



  • Controladores implícitos.
En Laravel podemos definir unha ruta chamando a un controlador no que estean definidos diferentes métodos e automaticamente en función da ruta chamará a un método ou a outros.
Por exemplo:

Arquivo app/Http/routes.php

  1. Route::controller('proba','ControladorProbaController');
Esta ruta 'xestionará' calquera petición que teña na url: http://sitioweb/proba


Se agora definimos no controlador estas entradas:

Arquivo app/Http/Controllers/ControladorProbaController.php

  1.     public function getInicio(){
  2.         return 'Inicio';
  3.     }
  4.     public function getFinal(){
  5.         return 'Final';
  6.     }
  7.     public function postDatos(){
  8.         return 'Enviando datos';
  9.     }
Este controlador responderá a estas peticións:

HTTP Request


Exemplo 1 do manual anterior. Uso de Http request

  • Neste exemplo imos ver como a partires dun formulario no que se pide login-password imos recibir có método 'post' os datos do mesmo noutra vista.
Partimos do formulario.
Arquivo: /proxecto_raiz/resources/views/formulario/Formulario.blade.php
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  2.     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  3. <html xmlns="http://www.w3.org/1999/xhtml" lang="es" xml:lang="es">
  4.     <head>
  5.         <meta charset="utf-8" />
  6.         <title>Formulario</title>
  7.         <style>
  8.             .formularios{
  9.                 width: 30%;
  10.                 margin: 0px auto;
  11.             }
  12.             .etiqueta{
  13.                 float: left;
  14.                 width: 190px;
  15.             }
  16.             .botonesformularios{
  17.                 width: 50%;
  18.                 margin: 30px auto;
  19.                 text-align: center;
  20.             }
  21.             select {
  22.                 width:50%;
  23.             }
  24.         </style>
  25.     </head>
  26.     <body>
  27.         <form id="frmValidacion" class="formularios" method="post" action="/controlador">
  28.             <div>    
  29.                 <div class='etiqueta'>Login:</div>
  30.                 <input type="text" size="15" maxlength="15" name="txtLogin" />
  31.             </div>                
  32.             <div>
  33.                 <div class='etiqueta'>Password:</div>
  34.                 <input type="password" size="15" maxlength="15" name="txtPassword" />
  35.             </div>                
  36.             <div class="botonesformularios">
  37.                 <input type='submit' value="ENVIAR" />
  38.             </div>
  39.         </form>
  40.  
  41.     </body>    
  42. </html>


Liña 27: Como vemos na action do formulario imos invocar un controlador a través dunha ruta definida no arquivo routes.php.
  • Definimos unha ruta para cargar a vista do formulario:
Arquivo: proxecto_raiz/app/Http/routes.php
  1. Route::get('formulario/',function(){
  2.     return view('formulario.Formulario');
  3. });
Nota: Por practicar estamos amosando a vista directamente dende a ruta, cando deberíamos pasar por un controlador.
Se poñemos como url: http://localhost:8000/formulario aparecerá o formulario.
  • Indicamos no arquivo de routes.php que se ten que facer cando reciba unha chamada do formulario. Fixarse como o verbo da ruta é post.
Arquivo: proxecto_raiz/app/Http/routes.php
  1. Route::post('controlador/','ControladorProbaController@mostrarUriUrl');


  • Agora creamos a clase controladora e método mostrarUriUrl dentro dela.
  1. <?php
  2.  
  3. namespace App\Http\Controllers;
  4.  
  5. use App\User;
  6. use App\Http\Controllers\Controller;
  7. use Illuminate\Http\Request;
  8.  
  9. class ControladorProbaController extends Controller {
  10.    
  11.     public function procedementoControlador($id){
  12.         return "Esta información ven dun controlador especifico. Recibido o dato $id";
  13.     }
  14.    
  15.     public function mostrarUriUrl(Request $request){
  16.         echo $request->path();
  17.         echo "<br>";
  18.         echo $request->url();
  19.         echo "<br>";
  20.  
  21.        
  22.         var_dump($request->all());  // ou dd(($request->all())); ou print_r(($request->all()));
  23.        
  24.     }
  25.    
  26. }
Nota:
  • $request->all(): Devolve todos os datos enviados polo formulario.
  • $request->input('txtLogin'): Devolve o texto do campo con name 'login' do formulario.


  • Dará como resultado:
controlador
http://localhost:8000/controlador

/home/angel/laravel/first_steps/app/Http/Controllers/ControladorProbaController.php:22:
array (size=2)
  'txtLogin' => string 'dfsdf' (length=5)
  'txtPassword' => string 'dsfds' (length=5)


Exercicio 1

  • Modifica o código anterior e crea unha vista de nome 'DatosFormulario.blade.php' que se atopa no cartafol 'formulario' dentro das views, que visualice o login e password enviado polo formulario.



  • Solución

Páxina: DatosFormulario.blade.php

  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  2.     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  3. <html xmlns="http://www.w3.org/1999/xhtml" lang="es" xml:lang="es">
  4.     <head>
  5.         <meta charset="utf-8" />
  6.         <title>Formulario</title>
  7.     </head>
  8.     <body>
  9.         LOGIN:{{$datos['txtLogin']}}<br />
  10.         PASSWORD:{{$datos['txtPassword']}}
  11.        
  12.  
  13.     </body>    
  14. </html>


Páxina: ControladorProbaController.blade.php

  1. <?php
  2.     ...................
  3.    
  4.     public function mostrarUriUrl(Request $request){
  5.         return view('formulario/DatosFormulario',['datos'=>$request->all()]);
  6.        
  7.        
  8.     }
  9. }

Reponse

  • Lembrar que xa vimos como enviar información de cabeceira ao navegador utilizando a función header de PHP.
Podedes comprobar o código de retorno da función 'response' có programa HttpRequester:
Php laravel response 1.jpg


  • Tedes neste enlace os diferentes content-type que podedes utilizar para enviar na cabeceira.


Exercicio 1

  • Crea unha ruta que teña unha URL deste tipo: /dato_response/{param} sendo {param} un número.
Fai que no caso de que dito número sexa maior que 100, se informe ao usuario cunha páxina de tipo 'non atopada' e dentro dun <h1> que o número non pode exceder de 100, amosando o número, e fai que o cabo de 3 segundos cargue a páxina /dato_response/1.
A páxina /dato_response/{param} amosará un texto de benvida amosando o número enviado como parámetro.

Solución Exercicio 1

  • Arquivo: proxecto_raiz/app/Http/routes.php
  1. Route::get('/dato_response/{numero}','ControladorProbaController@controlarDatoResponse')->where(['numero' => '[0-9]+']);


  • Arquivo: proxecto_raiz/app/Http/Controlllers/ControladorProbaController.php
  1. ..............
  2.     public function controlarDatoResponse($num){
  3.         if ($num>100) {
  4.             return response("<h1>O número enviado non é válido:$num</h1>")
  5.                 ->header('Content-Type', 'text/html')
  6.                 ->header('status', 404)
  7.                 ->header('Refresh', '3; url=/dato_response/1');            
  8.         }
  9.         else{
  10.             return view('DatoResponse',['numero' => $num]);
  11.         }
  12.            
  13.     }
  14. ..............


  • Arquivo: proxecto_raiz/resources/views/DatosResponse.blade.php
  1. <!DOCTYPE html>
  2. <html>
  3.     <head>
  4.         <title>Laravel</title>
  5.     </head>
  6.     <body>
  7.         <div class="container">
  8.             <h1>Benvido. O teu número é {{$numero}}</h1>
  9.         </div>
  10.     </body>
  11. </html>

Validación de formularios


  • No manual fala de que é posible instalar os arquivos necesarios para que en caso de erro de validación, as mensaxes do array $errors saian no noso idioma.
Para iso tedes que ir a este enlace
Nel indica o seguinte:
  • Descargar por composer (no enlace tedes outros métodos) os arquivos de tradución.
  1. composer require caouecs/laravel-lang:~3.0
Nota: A orde anterior é para versión de Laravel 5.* . Se tedes outra visitade o enlace.
  • Copiamos o cartafol da linguaxe de idioma (neste caso é o español)
  1. cp -r vendor/caouecs/laravel-lang/src/es/ resources/lang/
Estando situados no cartafol onde temos o proxecto laravel.


  • Modifica o arquivo config/app.php e substitúe as liñas de 'locale' polo idioma español:
  1.    ......
  2.  
  3.   'locale' => 'es',
  4.  
  5.    ..........


Exercicio 1

  • Crea unha táboa de nome AUTORES coas columnas: id_autor PK AU, apelido varchar(100), nome varchar(50)


  • Crea unha vista dentro do cartafol autores, de nome form_alta_autores.blade.php que teña un formulario para dar de alta a un novo autor, enviando como datos o nome e os apelidos.
Utiliza o método post no formulario e que o action apunte á páxina '/autores/alta
  • Modifica o arquivo de rutas para que recolla este tipo de solicitude:
  • http://sitioweb/autores/form/alta: Chamará ao controlador AutoresController e método create. Cargará a vista form_alta_autores.blade.php
  • http://sitioweb/autores/alta: Chamará ao controlador AutoresController e método store para gardar os datos do novo autor. Como aínda non vimos o acceso a datos, amosaremos unha cadea de texto indicando que foi dado de alta correctamente e cargaremos a vista do formulario de alta ao cabo de 5 segundos.
  • Valida os datos para que sexan obrigatorios e que a lonxitude do campo nome non sexa superior a 50 caracteres e a lonxitude do campo apelido non sexa superior a 100 caracteres. Os dous deberán ter a lo menos 5 caracteres. En caso de non cumprir os criterios, volver a cargar a páxina do formulario indicando os erros atopados e que os campos do formulario estean cubertos cos datos enviados.


Solución Exercicio 1

Arquivo: app/Http/routes.php

  1. Route::get('/autores/form/alta','AutoresController@create');
  2. Route::post('/autores/alta','AutoresController@store');


Arquivo: app/Http/Controllers/AutoresController.php

  1.     public function create()
  2.     {
  3.         return view('autores.form_alta_autores');
  4.     }
  5.  
  6.     public function store(Request $request)
  7.     {
  8.         $this->validate($request,[
  9.             'txtNome' => 'required|max:50|min:5',
  10.             'txtApelidos' => 'required|max:100|min:5',
  11.         ]);
  12.  
  13.         return response("<h1>Autor dado de alta correctamente</h1>")
  14.                 ->header('Content-Type', 'text/html')
  15.                 ->header('status', 200)
  16.                 ->header('Refresh', '3; url=/autores/form/alta');
  17.     }


Arquivo: resources/views/autores/form_alta_autores.blade.php

  1. <!DOCTYPE html>
  2. <html lang="es">
  3. <head>
  4.         <meta charset="UTF-8">
  5.         <title>Alta de autores</title>
  6. </head>
  7. <body>
  8.  
  9.   <form action="/autores/alta" method="post">
  10.     <div>
  11.         Apelidos: <input type="text" maxlength="100" size="60" name="txtApelidos" value="{{old('txtApelidos')}}"/>
  12.     </div>
  13.     <div>
  14.         Nome: <input type="text" maxlength="50" size="30" name="txtNome" value="{{old('txtNome')}}" />
  15.     </div>
  16.     <div>
  17.         <input type="submit" value="Enviar" />
  18.         <input type="reset" value="Borrar" />
  19.     </div>  
  20.    
  21.   </form>
  22.  
  23.     @if(count($errors) > 0)
  24.         <div class="errors">
  25.             <ul>
  26.             @foreach($errors->all() as $error)
  27.                 <li>{{ $error }}</li>
  28.             @endforeach
  29.             </ul>
  30.         </div>
  31.     @endif
  32.    
  33. </body>
  34. </html>



  • Nota:
As regras de validación estarían dentro do conxunto de 'regras de negocio'. Se queremos que ditas regras estean definidas no modelo, o podemos implementar da seguinte forma:
Información obtida dende este enlace.
Neste exemplo fai uso do facede Input para obter os datos que veñen do formulario. Nos estamos a utilizar a forma $request->input('campo')
Modificamos a clase do Modelo agregando as regras de validación e a función que vai validar:
  1. <?php
  2.  
  3. use Validator;
  4. class User extends Eloquent {
  5.    public static $rules = array(
  6.       'real_name' => 'required|min:2',
  7.       'email' => 'required|email|unique:users,email,id',
  8.       'password' => 'required',
  9.       'level' => 'required|numeric'
  10.    );
  11.    public static $messages = array(
  12.       'real_name.required' => 'El nombre es obligatorio.',
  13.       'real_name.min' => 'El nombre debe contener al menos dos caracteres.',
  14.       'email.required' => 'El email es obligatorio.',
  15.       'email.email' => 'El email debe contener un formato válido.',
  16.       'email.unique' => 'El email pertenece a otro usuario.',
  17.       'password.required' => 'La contraseña es obligatoria.',
  18.       'level.required' => 'El nivel es obligatorio.',
  19.       'level.numeric' => 'El nivel debe ser numérico.'
  20.    );
  21.    public static function validate($data, $id=null){
  22.       $reglas = self::$rules;
  23.       $reglas['email'] = str_replace('id', $id, self::$rules['email']);  // Se estamos modificando un usuario e temos unha regra que indica que o email debe ser único, debemos de excluír ao propio usuario que fai a modificación da regra de validación
  24.       $messages = self::$messages;
  25.       return Validator::make($data, $reglas, $messages);
  26.    }
  27. }
  28. ?>


Agora para validar dende o controlador:
  1. public function update($id) {
  2.    $user = User::find($id);
  3.    $user->real_name = Input::get('real_name');
  4.    $user->email = Input::get('email');
  5.    $user->level = Input::get('level');
  6.    $validator = User::validate(array(
  7.       'real_name' => Input::get('real_name'),
  8.       'email' => Input::get('email'),
  9.       'password' => $user->password,
  10.       'level' => Input::get('level'),
  11.    ), $user->id);
  12.    if($validator->fails()){
  13.       $errors = $validator->messages()->all();
  14.       $user->password = null;
  15.       return View::make('users.save')->with('user', $user)->with('errors', $errors);
  16.    }else{
  17.       $user->save();
  18.       return Redirect::to('users')->with('notice', 'El usuario ha sido modificado correctamente.');
  19.    }
  20.  }

Modelos en Laravel

Introdución

Exemplo 1 do manual anterior

  • Temos que ter creada unha base de datos Mysql cun usuario e password que teña permiso sobre dita base de datos.
  • Os pasos para instalar Mysql, un xestor de bases de datos, os tedes na wiki.
Unha vez creada debemos editar o arquivo proxecto_raiz/.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_DATABASE=homestead
DB_USERNAME=laravel
DB_PASSWORD=laravel

Unha vez cambiado debemos parar o servidor laravel e volvelo a iniciar coa orde: php artisan serve dende o raíz do proxecto.

  • Partindo que xa temos a táboa e a base de datos seguindo o manual...
  • Imos facer que se amosen os datos nunha vista en forma de lista.
  • Arquivo: proxecto_raiz/resources/views/basedatos/articles.blade.php
  1. <!DOCTYPE html>
  2. <html lang="es">
  3. <head>
  4.         <meta charset="UTF-8">
  5.         <title>Isto é unha vista de proba dunha táboa mysql</title>
  6. </head>
  7. <body>
  8.     <!-- Formato utilizando blade -->
  9.     <ul>
  10.     @foreach ($datos as $fila)
  11.         <li>{{ $fila->id }}---->{{ $fila->name }}</li>
  12.     @endforeach
  13.     </ul>
  14.  
  15.  
  16.     <!-- Formato utilizando php tradicional -->
  17.     <ul>
  18.         <?php
  19.             foreach($datos as $fila){
  20.                 printf("<li>%s--->%s",$fila->id,$fila->name);
  21.             }
  22.  
  23.         ?>
  24.        
  25.     </ul>
  26. </body>
  27. </html>
Liña 10: Nomeamos $datos á variable que vai vir do controlador cos datos da táboa. Segundo o manual isto non é necesario xa que podemos acceder dende calquera parte aos datos do modelo coa orde: \App\Article::all(); Pero desta forma practicamos o paso de datos dende o controlador e ademáis supoño que será a forma correcta :)


  • Arquivo: /proxecto_raiz/app/Http/Controllers/ArticulosController.php
  1. <?php
  2.  
  3. namespace App\Http\Controllers;
  4.  
  5. use App\User;
  6. use App\Http\Controllers\Controller;
  7. use Illuminate\Http\Request;
  8.  
  9. class ArticulosController extends Controller {
  10.    
  11.     public function amosarArticulos(){
  12.         $datos=\App\Article::all();
  13.         return view('basedatos.articles',[
  14.             'datos' => $datos
  15.         ]);
  16.  
  17.     }
  18.    
  19.    
  20. }
Liñas 13,14: Dende este método do controlador enviamos os datos da táboa á vista.
Nota: Se escribimos a orde: use App\Article;
Poderemos poñer: Artille::all()


  • Arquivo: /proxecto_raiz/app/Http/routes.php
  1. Route::get('articulos/','ArticulosController@amosarArticulos');
Cando na url poñamos: http://localhost:8000/articulos chamará ao método amosarArticulos do controlador ArticulosController.


  • Resultado:
    1--->Probando
    2--->Algo
    3--->Lindo

Acceso a base de datos



Tips

  • O que devolve Eloquent cando facemos consultas á base de datos son 'coleccións'.
Podemos ver neste enlace todas as funcións dispoñibles.
Por exemplo, se queremos engadir un rexistro (unha instancia dun modelo) a unha colección (por exemplo a que ven de chamar a Modelo::all()) podemos facer uso da función prepend.


  • Como está comentado no inicio do manual, ao manexar formularios tivemos que desactivar un Middleware (VerifyCsrfToken) para poder utilizalos.
Este Middleware serve para protexer contra ataques CSRF (do inglés Cross-site request forgery ou falsificación de petición en sitios cruzados). Podedes ver en que consiste este tipo de ataque neste enlace.
Para evitalo soamente temos que poñer dentro dos 'form' que fagamos e tendo unha plantilla blade o seguinte código:
  1. {{ csrf_field() }}


  • Cando buscamos un rexistro podemos usar a función find do Model ou tamén findOrFail que a diferenza da anterior en caso de non atopar o modelo lanzará unha excepción Illuminate\Database\Eloquent\ModelNotFoundException.


  • Cando enviamos información dende o controlador á vista temos que ter en conta que:
  • Se facemos un return view('vista')->with['variable' => 'dato'], o que lle chega á vista é a variable $variable có valor 'dato'.
  • Se facemos un return redirect('/ruta')->->with['variable' => 'dato'], o que lle chega á vista é a variable de sesión session('variable') que ten o valor 'dato'.


  • Se vos fixades, cando creamos un controlador coa opción --resource (a partires de Laravel 5.4) aparecen unha serie de funcións por defecto. Vexamos un exemplo dunha delas:
  1.     /**
  2.      * Update the specified resource in storage.
  3.      *
  4.      * @param  \Illuminate\Http\Request  $request
  5.      * @param  int  $id
  6.      * @return \Illuminate\Http\Response
  7.      */
  8.     public function update(Request $request, $id)
  9.     {
  10.         //
  11.     }
Como vedes esta función debería realizar a actualización dun rexistro na base de datos. Espera recibir como parámetro o $id (clave) do rexistro a actualizar e os datos deberían vir no obxecto $request.
Pero a pregunta é como facemos para enviar o id na url da forma www.meustio.es/actualizar/12 sendo 12 un exemplo do id a actualizar ?
Se supón que o que imos ter vai ser un formulario no que imos amosar os datos dun rexistro concreto, cun action a /actualizar (por exemplo) e o id debería estar cun campo oculto dentro do formulario...Isto sería a forma 'tradicional' de facelo.
Resulta que Laravel permite enviar o dato a URL dunha forma moi sinxela:
  1.         <form method="post" name="form_datos" action="{{ URL::to('/actualizar', $dato->id) }}"
  2.               onsubmit="if(confirm('Estas seguro de Modifcar ?')) { return true } else {return false };">
Agora o arquivo 'routes.php' terá este aspecto:
  1. Route::post('/actualizar/{id}',"ProbaController@update");
Como vemos estamos a recibir o id como parámetro e estamos chamando ao método update do controlador que vai recibir ese id máis os datos que veñan do formulario e que serán os datos que imos poder modificar.
Con URL::to facemos referencia a unha ruta do arquivo routes.php, pero tamén podemos utilizar 'alias' e darlle un nome a unha ruta da forma:
  1. Route::post('/actualizar/{id}',array('as' => 'actualizar.dato',"ProbaController@update"));
Agora podemos facer referencia a esta ruta dende o formulario coa orde: action="{{ URL::route('actualizar.dato', $dato->id) }}"
Máis información neste enlace.


  • Se queremos ver que sentenza SQL se executa 'detrás' das ordes Eloquent de acceso e manexo de datos temos que poñer o seguinte no arquivo routes.php:
  1. // Display all SQL executed in Eloquent
  2. Event::listen('illuminate.query', function($query)
  3. {
  4.     var_dump($query);
  5. });
Información obtida deste enlace.

Exercicio 1: Xestión dunha única táboa

  • Imos desenvolver a xestión dunha táboa PERFUMES.
Teremos as operacións de alta, baixa e modificación.
  • Veremos como 'formatear' un tipo de dato DATE de Mysql. De tal forma que en Mysql gardaremos a data có formato yyyy-mm-dd e no formulario do usuario terá o formato dd/mm/yyyy.
  • Veremos como 'formatear' un campo decimal de Mysql. De tal forma que en Mysql gardaremos o valor có formato XXX.YY e no formulario do usuario terá o formato XXX,YY.
  • Veremos como tratar os campos optativos, que poden vir con valores baleiros dende o formulario do usuario.


  • IMPORTANTE: Neste exercicio, o uso de formularios se fai utilizando as etiquetas habituais. En Laravel se poden empregar unhas 'etiquetas' específicas que van estar relacionadas cos Modelos e van permitir facer de forma inmediata 'cargar' os datos do modelo sobre os campos que conforman o formulario.
Tedes neste enlace como facelo.


Pasos previos

  • Modificar o arquivo env para indicar a base de datos, login e password de acceso á mesma.
  • Crear a táboa en Mysql:
  1. CREATE TABLE `PERFUMES` (
  2.   `id_perfume` int(11) NOT NULL AUTO_INCREMENT,
  3.   `descripcion` varchar(45) COLLATE utf8_spanish2_ci NOT NULL,
  4.   `prezo` decimal(8,2) NOT NULL,
  5.   `data_compra` date DEFAULT NULL,
  6.   PRIMARY KEY (`id_perfume`)
  7. ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_spanish2_ci;


  • Creamos o modelo para poder utilizar Eloquent:
Comando artisan no cartafol do proxecto: php artisan make:model Perfume
Arquivo App/Pefume:
  1. <?php
  2.  
  3. namespace App;
  4.  
  5. use Illuminate\Database\Eloquent\Model;
  6.  
  7. class Perfume extends Model
  8. {
  9.     protected $table ='PERFUMES';
  10.     protected $primaryKey='id_perfume';
  11.    
  12.     public $timestamps = false;
  13.    
  14.     protected $dates = ['data_compra'];
  15.    
  16.     protected $fillable =   [
  17.                                 'descipcion',
  18.                                 'prezo',
  19.                                 'data_compra'
  20.                             ];
  21.  
  22. }
  • Liña 14: Como vemos a táboa ten un campo de tipo date.
  • Se queremos formatear dito campo para visualizalo na forma que queiramos (por exemplo, dd/mm/yyyy) Laravel permite converter dito campo a un obxecto da clase Carbon. Dita clase xa dispón de métodos para formatear a data (máis información neste enlace.
  • Para facer que unha data poida facer uso destes métodos só temos que engadilo a un array na propiedade $dates do modelo.
  • Cando obteñamos un obxecto que represente unha fila da táboa utilizando Eloquent, poderemos formatear a data desta forma: $perfume->data_compra->format('d/M/Y').
  • Máis información neste enlace.


  • Usaremos o sistema de plantillas de Laravel:

Arquivo /resources/views/plantilla.blade.php

  1. <!DOCTYPE html>
  2. <html>
  3.     <head>
  4.         <title>@yield('pageTitle')</title>
  5.  
  6.         <style>
  7.             .menu{
  8.                 float: left;
  9.                 width: 30%;
  10.                 padding-left: 5px;
  11.             }
  12.             .menu a{
  13.                 display: block;
  14.             }
  15.             .contido{
  16.                 float: left;
  17.                 width: 65%;
  18.             }
  19.        
  20.         </style>
  21.     </head>
  22.     <body>
  23.         <div class="menu">
  24.             <a href='/perfumes'>Operacións Perfumes</a>
  25.         </div>
  26.          <div class="contido">
  27.             @yield('content')
  28.         </div>
  29.     </body>
  30. </html>


Listado de perfumes

  • Dende unha vista imos listar todos os perfumes que teña a base de datos e dentro da mesma imos ter as opcións de alta, baixa e modificación de novos perfumes.
A pantalla terá este aspecto:
Php laravel acceso datos ex1 1.jpg
Como podemos observar dispoñemos:
  • Na parte esquerda dun menú coa opción 'Operacións Perfumes' que carga a páxina que se ve na imaxe.
  • Na parte dos datos, temos un enlace que permite crear un novo perfume e despois na lista de perfumes, a carón de cada un deles, temos a opción de modificar ou eliminar un perfume.


Arquivo: /app/Http/routes.php
  1. Route::get('/perfumes','PerfumeController@index');


  • Creamos un controlador coa orde: php artisan make:controller PerfumeController.
  • Modificamos o controlador:
Arquivo: /app/Http/Controller/PerfumeController.php
  1. <?php
  2.  
  3. namespace App\Http\Controllers;
  4.  
  5. use Illuminate\Http\Request;
  6.  
  7. use App\Http\Requests;
  8. use App\Perfume;
  9.  
  10. class PerfumeController extends Controller
  11. {
  12.    .......
  13.  
  14.     public function index()
  15.     {
  16.         $perfumes = Perfume::orderBy('descripcion')->get();
  17.         return view('perfumes.operacions_perfumes')
  18.                 ->with(['perfumes'=>$perfumes]);
  19.     }
  20.  
  21.  
  22. }
Como vemos, estamos chamando á vista operacions_perfumes dentro dun cartafol 'perfumes' creado en views. Mandamos como parámetro a lista de perfumes da base de datos ordenados polo campo descripción.


  • Creamos a vista:

Arquivo /resource/views/perfumes/operacions_perfumes.blade.php

Nota: Creamos un cartafol dentro de /resources/views/perfumes
  1. @extends('plantilla')
  2.  
  3. @section('pageTitle', 'Lista de Perfumes')
  4. @section('content')
  5.  
  6. <div>
  7. <a href="/perfumes/alta" >NOVO PERFUME</a>    
  8. </div>
  9.  
  10. <h5>Hai {{$perfumes->count()}} perfumes en la base de datos.</h5>
  11.  
  12. <table>
  13.     <tr>
  14.         <th>Descripción</th>
  15.         <th>Prezo</th>
  16.         <th>Data compra</th>
  17.         <th>Operaciones</th>
  18.     </tr>
  19.     @foreach($perfumes as $perfume)
  20.         <tr>
  21.             <td>{{$perfume->descripcion}}</td>
  22.             <td>{{number_format($perfume->prezo,2,',','')}}</td>
  23.             <td>{{$perfume->data_compra ? $perfume->data_compra->format('d/m/Y'): ''}}</td>
  24.             <td><a href="/perfumes/{{$perfume->id_perfume}}/edit" >Modificar</a> <a onclick="return confirm('Estás seguro de eliminar o perfume {{$perfume->descripcion}} ?');" href="/perfumes/{{$perfume->id_perfume}}/delete" >Eliminar</a></td>
  25.         </tr>
  26.     @endforeach
  27.  
  28. </table>
  29.  
  30.  
  31. @if(session()->has('msg'))
  32.     <h3>{{session('msg')}}</h3>
  33. @endif
  34.  
  35. @endsection
  • Liña 7: Facemos un enlace á ruta /perfumes/alta a cal cargará a vista que amosa o formulario de alta dun novo perfume.
  • Liña 10: Chamamos a función count() da clase Collect para amosar o número de rexistros atopados na base de datos.
  • Liña 19: Percorremos cada un dos perfumes da colección.
  • Liña 22: O prezo é un decimal en Mysql e se garda có punto como separación dos números decimais. O que facemos é substituír o punto por unha coma.
  • Liña 23: O data de compra é un campo opcional, polo que pode vir cun valor nulo. Nese caso, a chamada á función format provocaría unha excepción polo que preguntamos utilizando o operador ternario se ten dato. En caso de que non teña amosamos a cadea baleira.
  • Liña 24: Temos dous enlaces para as operacións de actualización e baixa: /perfumes/id_perfume/edit => cargará a vista que actualiza e /perfumes/id_perfume/delete => borra o perfume.



Alta de perfume

  • A pantalla de alta de novos perfumes terá este aspecto:
Php laravel acceso datos ex1 2.jpg
  • Vimos coa ruta de tipo 'get' e valor /perfumes/alta (é o indicado no enlace da vista de listado de perfumes do punto anterior)
Arquivo: /app/Http/routes.php
  1. Route::get('/perfumes/alta','PerfumeController@create');
  2. Route::post('/perfumes/alta','PerfumeController@store');
Temos dúas rutas, unha para amosar a vista e a outra (método post) para cando engadimos un novo rexistro (perfume).


  • Modificamos o controlador:
Arquivo: /app/Http/Controller/PerfumeController.php
  1.      ................
  2.  
  3.     // Formato dd/mm/YYYY => devuelve YYYY-mm-dd
  4.     function cambiaf_a_mysql($fecha){
  5.         $numeroDia = substr($fecha,0,2);
  6.         $mes = substr($fecha,3,2);
  7.         $anio = substr($fecha,6,4);
  8.         return $anio . '-' . $mes . '-' . $numeroDia;
  9.     }
  10.  
  11.  
  12.     public function create()
  13.     {
  14.         return view('perfumes.form_alta_perfumes');
  15.     }
  16.  
  17.     public function store(Request $request)
  18.     {
  19.         $this->validate($request,[
  20.             'txtDescripcion' => 'required|max:45',
  21.             'txtPrezo' => 'required|regex:/[0-9]{1,3},[0-9]{2}/',
  22.             'txtDataCompra' => 'date_format:"d/m/Y"'
  23.         ]);    
  24.  
  25.         $perfume = new Perfume;
  26.         $perfume->descripcion = $request->input('txtDescripcion');
  27.         $perfume->prezo = str_replace(',','.',$request->input('txtPrezo'));
  28.         $perfume->data_compra = $request->has('txtDataCompra') ? $this->cambiaf_a_mysql($request->input('txtDataCompra')) : null;
  29.         $perfume->save();
  30.        
  31.         // Existe unha forma de crear e gardar o rexistro ao mesmo tempo: $novoPerfume = Perfume::create($request->all()) pero como neste caso imo manipular a data non o usaremos.
  32.        
  33.         return redirect('/perfumes/alta')->with(['idPerfume' => $perfume->id_perfume]);
  • Liñas 12-15: Función que se chama para amosar o formulario de alta.
  • Liñas 19-23: Facemos que os campos cumpran as seguintes regras:
  • txtDescripcion: Obrigatorio, con 45 caracteres como máximo (igual ao tamaño do campo na base de datos)
  • txtPrexo: Campo obrigatorio có formato XXX,YY sendo obrigatorio poñer a coma e dous números decimais. Lembrar que en Mysql o formato debe ser XXX.YY
  • txtDataCompra: Data de compra có formato dd/mm/YYYY. Lembrar que en Mysql o formato debe ser YYYY-mm-dd.
  • Liñas 25-29: Cremos un novo rexistro na base de datos.
  • Liña 27: Cambiamos a coma por un punto no prezo
  • Liña 28: Preguntamos se temos data de compra (é optativo) cun operador ternario. Se non temos gardamos null na base de datos. Se temos cambiamos o formato da data a yyyy-mm-dd chamando a unha función de nome cambiaf_a_mysql.
  • Liña 33: Rediriximos á ruta que carga o formulario de alta e enviamos como dato na variable session('idPerfume') o id do perfume xerado por Mysql.


  • Nota: Para o problema das datas tamén podemos empregar os Accesor/Mutators. Son funcións que definimos no modelo e que se aplican sobre os datos antes de envialos á vista cando os queremos amosar ou antes de envialos á base de datos cando os imos gardar. Facendo uso destas funcións xa non temos que estar 'formateando' os datos e podemos recuperalos desta forma:
Arquivo /app/Perfume.php:
  1.     public function getFechaAttribute($value)
  2.     {
  3.         return $this->cambiaf_desde_mysql($value);
  4.     }
Tendo definida a función cambiaf_desde_mysql no propio modelo.



  • Como os campos do formulario para a alta e modificación son os mesmos, imos definilos nun arquivo externo e os reutilizaremos nas dúas vistas:
Arquivo: /resources/views/perfumes/campos_perfume.blade.php
  1.     <div>
  2.         Descipción:<input type="text" maxlength="45" size="45" value="{{!empty($perfume) ? $perfume->descripcion : old('txtDescripcion')}}" name="txtDescripcion" />
  3.     </div>
  4.     <div>
  5.         Prezo (xxx,yy):<input type="text" value="{{!empty($perfume) ? str_replace('.',',',$perfume->prezo) : old('txtPrezo')}}" maxlength="6" size="6" name="txtPrezo" />
  6.     </div>
  7.     <div>
  8.         Data (dd/mm/yyyy):<input type="text" value="{{!empty($perfume) ? (empty($perfume->data_compra) ? '' : $perfume->data_compra->format('d/m/Y')) : old('txtDataCompra')}}" maxlength="10" size="10" name="txtDataCompra" />
  9.     </div>
Como vemos, o value de cada campo pode vir de dúas fontes diferentes:
  • Se estamos no formulario de alta de perfumes e non cumpre os criterios de validación, volverá a cargar o formulario e teremos que amosar os valores que tiña o formulario. Nese caso os valores estará no array global old.
  • Se estamos no formulario de modificación, viremos da pantalla de listado de perfumes no que premeremos no enlace de modificar asociado a un perfume concreto. Isto levará consigo chamar a unha función do controlador que busque os datos do perfume (utilizando Eloquent) e envíe á vista os datos do perfume atopado. Ditos datos van chegar na variable $perfume.
O que facemos preguntando por !empty($perfume) é para saber se temos que cargar os datos dun perfume seleccionado na vista de listado de perfumes ou se temos que amosar os datos antigos por non cumprir os criterios de validación ao intentar dar de alta ou modificar os datos. Isto o facemos có operador ternario.
Ademais, no caso da data, ao igual que pasaba na vista de lista de perfumes, temos que preguntar se ven baleiro ou non (outro operador ternario).


Arquivo: /resources/views/perfumes/form_alta_perfumes.blade.php
  1. @extends('plantilla');
  2.  
  3. @section('pageTitle', 'Alta de perfumes')
  4.  
  5. @section('content')
  6. <h2>Alta de novos perfumes</h2>
  7.  
  8.  
  9. <form method="post" action="{{htmlentities($_SERVER['PHP_SELF'])}}" name="formulario_perfumes">
  10.  
  11.     @include('perfumes.campos_perfume')
  12.     <div>
  13.         <input type="submit" name="btnAlta" value="Alta" onClick="return confirm('Estás seguro de dar de alta o novo perfume ');"/>
  14.         <input type="reset" name="btnBorrar" value="Limpar" />
  15.  
  16.     </div>
  17.    
  18.  
  19. </form>
  20.  
  21. @if (session()->has('idPerfume'))
  22.     <h4>Creado un novo rexistro co id: {{session('idPerfume')}}</h4>
  23. @endif
  24.  
  25. @if(count($errors) > 0)
  26.         <div class="errors">
  27.                 <ul>
  28.                 @foreach($errors->all() as $error)
  29.                         <li>{{ $error }}</li>
  30.                 @endforeach
  31.                 </ul>
  32.         </div>
  33. @endif
  34.  
  35. @endsection
  • Liña 9: Utilizamos a función htmlentities para evitar un ataque de tipo CSS.
  • Liña 11: Incluímos os campos do formulario.
  • Liña 21-23: Isto non sería necesario xa que a un usuario non se lle vai amosar o id autonumérico que conforma a clave primaria dunha táboa. Está posto para amosar como se pode enviar un dato dende o controlador á vista e concretamente o id xerado por Mysql cando engadimos un rexistro.
Lembrar (está comentado anteriormente) que cando fagamos unha operación o controlador vai facer un redirect e nese caso, o paso de datos coa orde ->with van chegar á vista en forma de variables de sesión.

Modificar perfume

  • A pantalla de modificación dun perfume terá este aspecto:
Php laravel acceso datos ex1 3.jpg


  • Arquivo /app/Http/routes.php
  1. Route::get('/perfumes/{id}/edit','PerfumeController@edit')->where(['id' => '[0-9]{1,12}']);
  2. Route::post('/perfumes/{id}/edit','PerfumeController@update')->where(['id' => '[0-9]{1,12}']);
Temos dúas rutas. A primeira carga o formulario cos datos e a segundo modifica os datos.
Á primeira ruta chegamos dende a vista de listado de perfumes, premendo no enlace que ten o href có formato /perfumes/id_perfume/edit


  • Arquivo /app/Http/Controller/PerfumeController.php
  1.     ..................
  2.  
  3.     public function edit($id)
  4.     {
  5.         $perfume = Perfume::findOrFail($id);
  6.         return view('perfumes.perfume_edit')
  7.                 ->with(['perfume' => $perfume]);
  8.     }
  9.  
  10.     public function update(Request $request, $id)
  11.     {
  12.         $this->validate($request,[
  13.             'txtDescripcion' => 'required|max:45',
  14.             'txtPrezo' => 'required|regex:/[0-9]{1,3},[0-9]{2}/',
  15.             'txtDataCompra' => 'date_format:"d/m/Y"'
  16.         ]);        
  17.  
  18.         $perfume = Perfume::findorFail($id);
  19.         $perfume->descripcion=$request->input('txtDescripcion');
  20.         $perfume->prezo=str_replace(',','.',$request->input('txtPrezo'));
  21.         $perfume->data_compra= !empty($request->input('txtDataCompra')) ? $this->cambiaf_a_mysql($request->input('txtDataCompra')) : null;
  22.         $perfume->save();
  23.  
  24.         return redirect()->back()->with(['msg' => 'Perfume modificado correctamente']);
  25.        
  26.      
  27.     }
  • Liñas 3-8: Buscamos o id do perfume que ven na URL. En caso de non atopalo lanzaría unha excepción (neste código está sen controlar con try-catch). Se o atopa o envía á vista 'perfume_edit' na variable $perfume.
  • Liña 11-27: Recibimos os datos modificados dun perfume da vista cargada pola ruta anterior.
  • Liñas 12-16: Volvemos a validar os datos enviados. Lembrar que poderíamos utilizar un obxecto da clase Requests creada por nos ou ben levar a validación de datos ao modelo (regras de negocio) como está indicado anteriormente.
  • Liñas 18-22: Recuperamos os datos enviados polo formulario e actualizamos o rexistro do perfume.
  • Liña 24: Cargamos a mesma páxina (o formulario cos datos da modificación) enviando unha mensaxe de que todo foi ben.


  • Arquivo /resource/views/perfumes/perfume_edit.blade.php
  1. @extends('plantilla')
  2.  
  3. @section('pageTitle', 'Editar Perfume')
  4. @section('content')
  5.  
  6. <h5>Datos do perfume <b>{{$perfume->descripcion}}</b></h5>
  7.  
  8. <form method="post" name="form_datos_perfume" action="{{htmlentities(Request::fullUrl())}}" >
  9.  
  10.     {{ csrf_field() }}    
  11.  
  12.     @include('perfumes.campos_perfume')
  13.     <div>
  14.         <input type="submit" name="btnModificar" value="Modificar" onClick="return confirm('Estás seguro de modificar o perfume {{$perfume->descripcion}}');"/>
  15.         <input type="reset" name="btnBorrar" value="Limpar" />
  16.  
  17.     </div>
  18. </form>
  19.  
  20. @if(session()->has('msg'))
  21.     <h3>{{session('msg')}}</h3>
  22. @endif
  23.  
  24.  
  25. @if(count($errors) > 0)
  26.         <div>
  27.                 <ul>
  28.                 @foreach($errors->all() as $error)
  29.                         <li>{{ $error }}</li>
  30.                 @endforeach
  31.                 </ul>
  32.         </div>
  33. @endif
  34.  
  35. @endsection
  • Liña 8: Non aloxamento real, facer que apunte á mesma páxina con $_SERVER['PHP_SELF'] non me funcionou. Apuntaba á principal. Para solucionalo podemos facer uso de: Request::fullUrl()

Baixa de perfume

Arquivo /app/Http/routes.php

  1. Route::get('/perfumes/alta','PerfumeController@create');
  2. Route::post('/perfumes/alta','PerfumeController@store');
  3.  
  4. Route::get('/perfumes/{id}/edit','PerfumeController@edit')->where(['id' => '[0-9]{1,12}']);
  5. Route::post('/perfumes/{id}/edit','PerfumeController@update')->where(['id' => '[0-9]{1,12}']);
  6. Route::get('/perfumes/{id}/delete','PerfumeController@destroy')->where(['id' => '[0-9]{1,12}']);
  7. Route::get('/perfumes','PerfumeController@index');
Amosamos todas as rutas xa que é importante o orde.
A ruta que xestiona a baixa dun perfume é /perfume/id_perfume/delete e lembrar que dita ruta ven de premer o enlace 'eliminar' da vista listado de perfumes.



  • Arquivo: /app/Http/Controller/PerfumeController.php
  1.   ................
  2.     public function destroy($id)
  3.     {
  4.         $perfume = Perfume::findorFail($id);
  5.         $perfume->delete();
  6.        
  7.         return redirect('/perfumes');
  8.     }
Borramos o perfume có id enviado e cargamos a vista do listado de perfumes.


Paxinación

  • Temos neste enlace todo o necesario para paxinar os resultados.
Php laravel acceso datos ex1 4.jpg


Os pasos a seguir son:

  • Modificar o controlador para que os datos que se envían á vista estean paxinados:
Arquivo: /app/Http/Controller/PerfumeController.php
  1.     public function index()
  2.     {
  3.         $perfumes = Perfume::orderBy('descripcion')->paginate(5);
  4.         return view('perfumes.operacions_perfumes')
  5.                 ->with(['perfumes'=>$perfumes]);
  6.     }


  • Modificamos a vista para que amose unha lista coas páxinas de datos.
Como a lista se amosa cunha etiqueta <ul> engadimos un style para quitar os puntos e que estean en horizontal (isto o faríamos na parte head da páxina. Aquí está na propia vista para que vexades o código:
Arquivo: /resources/views/perfumes/operacions_perfumes.blade.php
  1. ....................
  2. </table>
  3. <style>
  4.     .paxinado ul{
  5.          list-style-type: none;
  6.     }
  7.     .paxinado ul li {
  8.         float:left;
  9.         margin-left:10px;
  10.     }
  11. </style>
  12. <div class="paxinado">
  13.     {!! $perfumes->render() !!}
  14. </div>
  15.  
  16. @if(session()->has('msg'))
  17.     <h3>{{session('msg')}}</h3>
  18. @endif
  19.  
  20. @endsection


  • TRUCO:
Cando temos relacións establecidas entre diferentes modelos, pode darse o caso que queiramos paxinar o resultado dunha relación.
Imaxinade que tedes unha relación 1-N entre Profesores (1) e Alumnos (n).
Cando vexades o punto de relacións 1-N podedes comprobar que con esta orde: $alumnos = Profesor::findOrFaul($id)-> alumnos obteríamos unha colección dos alumnos aos que o profesor da clase.
Se quixeramos paxinar o resultado non poderíamos.
Para facelo temos que poñer parénteses despois da función que recupera os alumnos da forma: $alumnos = Profesor::findOrFail($id)-> alumnos()->orderBy('nombre')->paginate(25);

Middleware

  • Son 'programas' ou anacos de código que se executan antes de chamar a un controlador.
Atópanse entre o controlador frontal que recibe as peticións dos usuarios e a chamada aos controladores por parte deste controlador frontal.
Poden ir enlazados varios middlewares un detrás doutro.


  • Lembrar que para crear un middleware podemos facer uso do comando artisan:
  1. php artisan make:middleware nome_middleware
  • Normalmente os imos utilizar cando teñamos implementado un sistema de autenticación de usuarios, no que en función do rol do mesmo redireccionaremos a unha páxina ou outra.
Outro exemplo de código podería ser este código, obtido de este enlace, no que se verifica se o país de procedencia da petición é de Estados Unidos...
  1. class AdMiddleware
  2. {
  3.     /**
  4.      * Handle an incoming request.
  5.      *
  6.      * @param  \Illuminate\Http\Request  $request
  7.      * @param  \Closure  $next
  8.      * @return mixed
  9.      */
  10.     public function handle($request, Closure $next)
  11.     {
  12.         // Test to see if the requesters have an ip address.
  13.         if($request->ip() == null){
  14.             throw new \Exception("IP ADDRESS NOT SET");  
  15.         }
  16.         $country=file_get_contents('http://api.hostip.info/get_html.php?ip=' . $request->ip());
  17.         echo $country;
  18.         if(strpos($country, "UNITED STATES")){
  19.            throw new \Exception("NOT FOR YOUR EYES, NSA");  
  20.         } else {
  21.             return redirect("index");  
  22.         }
  23.        
  24.         return $next($request);
  25.     }
  26. }



Exercicio 1

  • Crea unha vista que pida introducir a idade a un usuario.
Fai que se a idade do usuario é menor de 18 volva á vista do formulario.
Fai que se a idade do usuario é maior de 18 cargue outra vista no que se da a benvida ao usuario amosando a súa idade.
  • Utiliza un middleware para facelo e que soamente se execute cando enviemos a idade dende o formulario.


Solución Exercicio 1

  • Arquivo: /proxecto_raiz/app/Http/Router.php
  1. Route::get('getIdade/',function(){
  2.     return view('idade');
  3. });
  4.  
  5. Route::post('amosaridade/','IdadeController@amosarIdade')->middleware('idade_middleware');
  • Liña 6: Fixarse como o verbo debe ser 'post' para capturar o evento do formulario cando introducimos a idade.


  • Arquivo: /proxecto_raiz/app/Http/Kernel.php
  1. .......
  2.  
  3. 'idade_middleware' => \App\Http\Middleware\IdadeMiddleware::class,
  4.  
  5. .......


  • Arquivo: /proxecto_raiz/app/Http/Middleware/IdadeMiddleware.php
  1. <?php
  2.  
  3. namespace App\Http\Middleware;
  4.  
  5. use Closure;
  6.  
  7. class IdadeMiddleware
  8. {
  9.     public function handle($request, Closure $next)
  10.     {
  11.       if(!empty($request->input('txtIdade')) &&
  12.           $request->input('txtIdade')<18){
  13.             return redirect('getIdade/')->withInput()->withErrors(['msg'=>'A idade non pode ser menor que 18']);
  14.         }
  15.        
  16.       return $next($request);
  17. }
  • Liña 13: En caso de que non cumpra as condicións, enviamos nunha 'variable' especial de nome $errors (withErrors) a mensaxe que queremos que se amose na pantalla do formulario. Tamén enviamos de volta o dato introducido (withInput) que será posto outra vez no value da caixa de texto.
Para comprobar se ven a idade podemos facer uso da función 'has' da clase Request desta forma: if(!$request->has('txtIdade')).
Fixarse que poderíamos poñer dúas condicións distintas, unha para cando non recibe datos e outra para cando a idade é menor que 18, e enviar á paxina do formulario dous erros diferentes.
Neste exemplo deixamos introducir unha idade baleira e a mensaxe de erro será amosada na pantalla que visualiza a idade.
  • Arquivo: /proxecto_raiz/app/Http/Controller/IdadeController.php
  1. <?php
  2.  
  3. namespace App\Http\Controllers;
  4.  
  5. use Illuminate\Http\Request;
  6.  
  7. use App\Http\Requests;
  8. use App\Http\Controllers\Controller;
  9.  
  10. class IdadeController extends Controller
  11. {
  12.  
  13.     public function amosarIdade(Request $request){
  14.        
  15.         $datos_form=$request->all();
  16.        
  17.         return view('amosaridade',[
  18.             'datos' => $datos_form
  19.         ]);
  20.        
  21.     }
  22. }


  • Arquivo: /proxecto_raiz/Resource/Views/idade.blade.php
  1. <!DOCTYPE html>
  2. <html>
  3.     <head>
  4.         <title>Laravel</title>
  5.  
  6.         <link href="https://fonts.googleapis.com/css?family=Lato:100" rel="stylesheet" type="text/css">
  7.  
  8.     </head>
  9.     <body>
  10.         <div class="container">
  11.             <div class="content">
  12.                 <form name='frmIdade' action="/amosaridade" method="post">
  13.                     Idade: <input type="text" name="txtIdade" maxlength="3" size="3" value="{{old('txtIdade')}}"/>
  14.                     <div><input type="submit" value="ENVIAR" /></div>
  15.                 </form>
  16.             </div>
  17.             @if ($errors->any())
  18.                 <h4>{{$errors->first('msg')}}</h4>
  19.             @endif
  20.         </div>
  21.     </body>
  22. </html>

Cookies en Laravel


Aspectos varios

Formularios coa extensión Collective

Así podemos abrir e pechar formularios con etiquetas Laravel. A particularidade de facelo desta forma é que ampliamos a funcionalidade. Así, podo definir unha apertura dun formulario que se vai basear nun modelo. Cando envíe como dato á vista un obxecto de dito modelo, se teño definidos os names das caixas de texto igual ao nome das columnas, ditas caixas énchense automaticamente cos datos do modelo.
  • Paquete Styde\Html: Mellora a Extensión Collective/Html (incorpora melloras para o manexo de formularios)
Guía.
Instalación.

Aclaración das listas 'select'

  • Cando usemos este paquete, poderemos encher listas cos datos que veñan do controlador, mandados como parámetros dende o mesmo.
O problema é que a forma de cargar os datos nesta extensión para as listas, espera recibir un array con dous datos (clave e texto a amosar).
Para facelo teremos que (se estamos a usar Eloquent ou QueryBuilde) facer uso da función plunk desta forma:
  1. $datos=Modelo::select('id','texto')
  2.             ->orderBy('texto')
  3.             ->get()
  4.             ->pluck('banco','id')
  • Nota: Se queremos engadir un elemento baleiro antes do primeiro dato da táboa teremos que facer uso da función prepend, despois de facer o pluck.
Agora xa podemos enviar os datos á vista e cargalos da forma (as class son postas por usar bootstrap):
  1. <div class="form-group">
  2.  {!! Form::label('idtipo', 'Texto do label:', ['class' => 'col-sm-2 control-label']) !!}
  3.     <div class="col-sm-10">
  4.         {!! Form::select('nomecontrol', $datos, null, ['class' => 'form-control']); !!}
  5.     </div>
  6. </div>
  • 'nomecontrol' é o name do control select, que se queremos facer un insert/update 'automático' (Modelo->create($request->all())) debería ter o mesmo nome que a columna da táboa onde vai a engadirse/actualizarse.

Breadcrumbs

  • Breadcrumbs: Recurso gráfico para que o usuario saiba en que sección da aplicación se atopa.


Paxinación de resultados

  • Para paxinar o resultado dunha consulta a unha base de datos:
Fixarse que a través dun modelo podemos obter unha colección en base a unha relación do modelo con outra táboa. Nese caso teríamos que empregar a segunda opción.


  • TRUCO:
Cando temos relacións establecidas entre diferentes modelos, pode darse o caso que queiramos paxinar o resultado dunha relación.
Imaxinade que tedes unha relación 1-N entre Profesores (1) e Alumnos (n).
Cando vexades o punto de relacións 1-N podedes comprobar que con esta orde: $alumnos = Profesor::findOrFaul($id)-> alumnos obteríamos unha colección dos alumnos aos que o profesor da clase.
Se quixeramos paxinar o resultado non poderíamos.
Para facelo temos que poñer parénteses despois da función que recupera os alumnos da forma: $alumnos = Profesor::findOrFail($id)-> alumnos()->orderBy('nombre')->paginate(25);

Accessors e Mutators

  • Os accesors son método que definimos no modelo para recuperar os datos da base de datos, pero aplicando algún tipo de formateo ou filtro. Por exemplo, pode recuperar todos os datos dun modelo en maiúsculas (aplicaría a función strtoupper aó atributo que queira).
  • Os mutators son iguais os accesors pero se aplican ós atributos antes de que sexan gardados na base de datos.



Migracións e Seeders

  • Migracións: Laravel dispón dun sistema para crear as táboas que van conformar a nosa base de datos. Basicamente é o conxunto de ordes que fan os create table colocadas nun arquivo e que Laravel executa automaticamente cando nos digamos. A maiores permite ter 'diferentes versións' da base de datos (creación de novas táboas, modificacións sobre a estructura) e permite volver atrás,a algunha das versións gardadas.
  • Seeders: Unha vez temos as táboas creadas, Laravel permite encher de datos de proba mediante o uso de seeders.


Autenticación

  • Laravel incorpora un sistema que nos permite facer que o noso sitio web teña unha seguridade baseada na autentificación de usuarios.
Incorpora de forma automática as táboas e vistas necesarias para pedir unha autentificación.
Máis información neste enlace.

Regresar a dúas páxinas anteriores

  • Como sabemos, facendo dende o controlador un return redirect()->back() regresamos á vista anterior.
Isto o usamos cando damos de alta un rexistro para que volva á vista do formulario de alta.
  • Pero tamén pode suceder que necesitemos volver dúas páxinas anteriores á actual.
Por exemplo, cando temos a clásica páxina na que aparecen un conxunto de resultados coas opcións de 'Modificar' e 'Eliminar' asociadas a cada un deles.
Se prememos o botón 'Modificar' iremos á vista que enche os datos do elemento seleccionado para poder modificalos. Cando prememos o botón 'Modificar' iremos normalmente ao método 'update' do controlador.
Se nese método facemos un back() regresaremos á vista do formulario e nos queremos ir á vista anterior a esa (a do listado).
Para solucionalo teremos que gardar nun campo oculto na vista do formulario a url anterior e recuperar o seu valor no método update.
Vexamos un exemplo:

Arquivo que amosa o formulario para modificar un elemento seleccionado:

  1. {!! Form::model($tipoproducto,['url' => htmlentities($_SERVER['PHP_SELF']), 'class' => 'form-horizontal']) !!}
  2. {!! Form::hidden('redirects_to', URL::previous()) !!}
  3.  
  4.  {{ csrf_field() }}


Arquivo controlador método update:

  1.         ..................
  2.         $url = $request->only('redirects_to');
  3.         return redirect()->to($url['redirects_to'])->with(['aviso'=>'Tipo de producto actualizado correctamente']);


Posta en marcha nun servidor web Apache real

  • O pasos para a posta en marcha os tedes na documentación oficial. Fixarse na versión de Laravel arriba á dereita da páxina.
  • Importante: Desactivade o debugger se a aplicación vai ir a produción.
Isto o facedes no arquivo .env:
  • APP_DEBUG=false
  • APP_ENV=production
  • No arquivo config/app.php podedes cambiar os parámetros: timezone e locale.
  • Esencialmente, necesitaredes que o servidor web Apache teña instalado e activo o módulo mod_rewrite.
Dende consola:
  1. sudo a2enmod rewrite
  2. sudo service apache2 restart
  • Despois teredes que ter un DNS 'apuntando' á vosa máquina e configurar o Apache para que dito DNS cargue a páxina index.php do cartafol 'public' do proxecto Laravel:
  • Se non tedes un DNS podedes, para facer probas, podedes modificar o arquivo /etc/hosts para engadir o dns que ides utilizar:
  1. 127.0.1.1       angel-VirtualBox www.meusitio.es
  • Copiamos ou movemos o proxecto Laravel ao cartafol /var/www/
  • Editamos o arquivo de configuración de sitios de apache que se atopa en /etc/apache2/sites-enabled/000-default.conf e engadimos o noso dominio:
  • Para versión Apache 2.2:
  1. <VirtualHost *:80>
  2.         Options Indexes FollowSymLinks MultiViews
  3.  
  4.         ServerAdmin webmaster@localhost
  5.         DocumentRoot /var/www/meuproxecto/public
  6.         ServerName www.meusitio.es
  7.  
  8.  
  9.         ErrorLog ${APACHE_LOG_DIR}/error.log
  10.         CustomLog ${APACHE_LOG_DIR}/access.log combined
  11.  
  12. </VirtualHost>
  13.  
  14. <Directory "/var/www/meuproxecto/public">
  15.         AllowOverride All
  16.         Order allow,deny
  17.         Allow from all
  18. </Directory>
  • Liña 5: Indicamos o cartafol public do proxecto Laravel.
  • Liña 6: Indicamos o nome DNS que imos utilizar (o que puxemos no arquivo hosts)
  • Para versión Apache 2.4 ou superior:
  1. <VirtualHost *:80>
  2.         #ServerName www.example.com
  3.         Options +Indexes +FollowSymLinks +MultiViews
  4.  
  5.         ServerAdmin webmaster@localhost
  6.         DocumentRoot /var/www/meuproxecto/public
  7.         ServerName www.asufinprobas.es
  8.  
  9.  
  10.         ErrorLog ${APACHE_LOG_DIR}/error.log
  11.         CustomLog ${APACHE_LOG_DIR}/access.log combined
  12.  
  13. </VirtualHost>
  14.  
  15. <Directory "/var/www/meuproxecto/public">
  16.         AllowOverride All
  17.         Require all granted
  18. </Directory>
Nota: Para saber a versión do servidor apache instalada executade nunha consola a orde: apache2 -v
Máis información sobre o servidor web Apache neste enlace.
  • Reiniciamos o servidor Apache:
Dende consola:
  1. sudo service apache2 restart
  • Debemos dar permiso de escritura ao usuario/grupo utilizado polo servidor web Apache (normalmente www-data, pero podedes sabelo mirando este enlace) a os cartafoles storage e vendor.
  1. sudo setfacl -R -m g:www-data:rwx /var/www/meuproxecto/storage/
  2. sudo setfacl -R -m g:www-data:rwx /var/www/meuproxecto/vendor/
  3. sudo setfacl -R -m u:www-data:rwx /var/www/meuproxecto/storage/
  4. sudo setfacl -R -m u:www-data:rwx /var/www/meuproxecto/vendor/

Bootstrap 3

  • BootStrap é un framework para o deseño de sitios web utilizando javascript e CSS.
A principal vantaxe é que permite a adaptación do contido ao tipo de dispositivo que vai visualizar o sitio web. É o que se coñece como Deseño adaptativo ou Design Adapter.
  • Na web bootswatch.com podemos ver diferentes deseños para un sitio web utilizando bootstrap.



  • Un dos conceptos máis importantes consiste en dividir o contido da páxina en filas e columnas. O número máximo de columnas que podemos ter é de 12. A cada contido podemos indicarlle cantas columnas vai ocupar, axustándose o espazo total ao espazo de cada elemento.


Instalando Bootstrap con Laravel 5

  • Primeiro debemos instalar o paquete Laravel / Colletive.
Para iso seguiredes os pasos indicados na web https://laravelcollective.com escollendo na parte superior a versión de Laravel que teñades instalada ata o punto Opening form (non facelo).


Chega con descargar a 'Compiled and minified CSS, JavaScript, and fonts. No docs or original source files are included.' (a opción da esquerda).
Unha vez baixada e descomprimida, teredes tres cartafoles (css,fonts e js). Imos mover ditos cartafoles ao cartafol 'public/assets' do voso proxecto Laravel. O cartafol 'assets' teredes que crealo.
  • Agora imos crear unha 'plantilla' para todas as vistas (información obtida desde enlace).


Arquivo: resources/views/layout.blade.php

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.  <meta charset="utf-8">
  5.  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6.  <meta name="viewport" content="width=device-width, initial-scale=1">
  7.  <title>Laravel</title>
  8.  
  9.  {!! Html::style('assets/css/bootstrap.css') !!}
  10.  
  11.  <!-- Fonts -->
  12.  <link href='//fonts.googleapis.com/css?family=Roboto:400,300' rel='stylesheet' type='text/css'>
  13.  
  14.  <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
  15.  <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
  16. <!--[if lt IE 9]>
  17. <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
  18. <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
  19. <![endif]-->
  20. </head>
  21. <body>
  22. <nav class="navbar navbar-default">
  23. <div class="container-fluid">
  24. <div class="navbar-header">
  25. <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
  26. <span class="sr-only">Toggle Navigation</span>
  27. <span class="icon-bar"></span>
  28. <span class="icon-bar"></span>
  29. <span class="icon-bar"></span>
  30. </button>
  31. <a class="navbar-brand" href="#">Laravel</a>
  32. </div>
  33.  
  34.  
  35. </div>
  36. </nav>
  37.  
  38. @yield('content')
  39.  
  40.  
  41. <!-- Scripts -->
  42. <script src="http://code.jquery.com/jquery.js"></script>
  43. {!! Html::script('assets/js/bootstrap.min.js') !!}
  44. </body>
  45. </html>
  • Liñas 9 e 43: Estamos a cargar o arquivo CSS e Javascript necesarios para bootstrap. Fixarse como na ruta vai o cartafol 'assets' (parte do cartafol 'public', cando a páxina se carga).
  • Liña 38: Definimos unha etiqueta que vai ser o contido que van utilizar as vistas do noso sitio web.
Neste caso estamos poñendo 'en común' a todas as páxinas a cabeceira e a barra de navegación. Nada impide crear etiquetas para cada un delas e ter un contido diferente para cada vista do noso sitio web.
  • Liña 42: A librería jquery é necesaria para executar os scripts de javascript. Podería descargarse a local.
  • Como a esta vista dámoslle o nome de 'layout.blade.php', as vistas que cremos que teñan como base esta, deberán 'extender' dese nome:

Arquivo: resources/views/inicio.blade.php

  1. @extends('layout')
  2.  
  3. @section('content')
  4. <div class="container">
  5.  <div class="row">
  6.  <div class="col-md-10 col-md-offset-1">
  7.  <div class="panel panel-default">
  8.  <div class="panel-heading">Inicio</div>
  9.  
  10.  <div class="panel-body">
  11. Usando bootstrap
  12.  </div>
  13.  </div>
  14.  </div>
  15.  </div>
  16. </div>
  17. @endsection
Como vemos estamos a substituír o 'content' do layout.blade.php.


  • Temos neste enlace un exemplo para facer unha vista para o rexistro e validación de usuarios tendo ao final de todo a versión para Laravel utilizando 'Blade'.
Neste enlace incorpora dunha forma diferente o framework bootstrap, xa que o carga dende Internet utilizando Content Delivery Network (CDN). Todas as clases, CSS e código javascript está aloxado en servidores de Internet, de tal forma que todo o código para incorporar bootstrap ao teu proxecto non se carga dende o teu sitio web, se non que está repartido en diferentes servidores en Internet, reducindo a carga de traballo do teu servidor.

Modificando o theme (aspecto)

Existen multitude de sitios onde podedes atopar outros themes.
  • Para modificar o theme, temos dúas opcións:
  • Se estamos a utilizar CDN, soamente debemos cambiar a URL a cargar.
Podemos ver nesta web as diferentes 'rutas' CDN en función do theme escollido.
  • Se estamos a utilizar bootstrap copiado 'localmente' deberemos substituír o arquivo 'bootstrap.css' que se atopa (se seguíchedes o exemplo) en 'public/assets/css', polo do theme seleccionado.
Despois teremos que descubrir como se chaman as clases de cada un dos controis para que se visualicen de acordo ao theme seleccionado.
Vexamos un exemplo:


Integrando bootstrap 3 con extensión Collective de Laravel

Enlace.




-- Ángel D. Fernández González -- (2016).