Framework: Laravel ================== .. image:: /logos/logo-laravel.png :scale: 30% :alt: Logo Django :align: center .. |date| date:: .. |time| date:: %H:%M Documentación básica para trabajar con Laravel 5 .. contents:: Índice Configuraciones ############### Creación del proyecto ********************* - Instalar laravel vía composer: ``composer create-project laravel/laravel proyecto-laravel "5.6.*" --prefer-dist`` - Probar que está funcionando: ``php -S localhost:8000 -t public/`` .. note:: Dentro de Public se encuentra el archivo principal de la aplicación, es donde debe apuntar el servidor. .. attention:: Es necesario tener Composer instalado: https://getcomposer.org/download/ .. attention:: Es importante tener instalado PHP o en su defecto un servidor Lamp o Xamp .. attention:: Es posible que no se ejecute el proyecto correctamente en el servidor, si es así ejecutamos ``composer install`` para solventar dependencias. También pueden faltar paquetes de php en linux, se instalan ``sudo apt install php-mbstring`` y ``sudo apt install php-xml``. Se vuelve a ejecutar ``composer install`` y no debería de dar errores. Estructura de Laravel ********************* En la estructura de un proyecto Laravel estas son las partes más importantes: - app: directorio con el contenido principal de Laravel y la aplicación. - http: contiene los modelos por ejemplo. - bootstrap: Contiene un archivo que inicia el framework y la caché. - config: contiene archivos de configuración de la aplicación. - database: contiene lo relacionado con las migraciones de la base de datos. - public: contiene archivos públicos como los assets o el index - resources: es donde se encuentran las vistas de la aplicación. - routes: contiene las rutas de la aplicación. - storage: almacenará archivos a subir. - tests: carpeta con los test de la explicación. - vendor: guarda todos los paquetes y librerías instalados con composer. - artisan: permite ejecutar comandos cli de Laravel. - .env: es donde se configura la conexión a la base de datos entre otros. Comandos Artisan **************** Laravel tiene una lista de comandos con Artisan los cuales se destacan: - Listar rutas: ``php artisan route:list`` - Crear controlador: ``php artisan make:controller NuevoController`` - Crear controlador con CRUD: ``php artisan make:controller UserController --resource`` - Crear una migración: ``php artisan make:migration create_consolas_table --table=lista_consolas`` - Desplegar migración: ``php artisan migrate`` - Refrescar migraciones: ``php artisan migrate:refresh`` - Crear un seeder: ``php artisan make:seed lista_consolas_seed`` - Lanzar un seeder: ``php artisan db:seed --class=lista_consolas_seed`` Configurar conexión a base de datos *********************************** Para configurar la base de datos se edita el archivo **.env** y se añade los datos de configuración de nuestra base de datos: .. code-block:: :linenos: DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=consolas DB_USERNAME=guillermo DB_PASSWORD=1234 .. note:: El archivo de configuración también puede configurar correos y bases de datos redis. Rutas en Laravel ################ Las rutas en Laravel las podemos encontrar dentro de la carpetas **routes** en el archivo **web.php** Ejemplo de ruta: .. code-block:: php :linenos: $saludo )); }); Route::get('/prueba', function(){ // variables que se pueden asignar al callback: $saludo = "Hola con Laravel"; // otro modo de cargar valores a la vista es con with: return view('prueba') ->with('saludo', $saludo); // pueden haber tantos with como hagan falta. }); Rutas con parámetros ******************** .. code-block:: php :linenos: Hola " . $nombre . ""; }); // con ? se define parametro opcional pero hay que definir valor por defecto en el parámetro del callback: Route::get('/edad/{edad?}', function($edad = "desconocida"){ return "

Hola, tu edad es: " . $edad . "

"; }); Condiciones en las rutas ************************ Las rutas en Laravel pueden recibir condiciones gracias a la función where: .. code-block:: php :linenos: Hola, tu edad es: " . $edad . ""; })->where(array( // con expresiones regulares se pueden filtrar los parámetros: 'edad' => '[0-9]+' )); .. attention:: Si se añade más condiciones y son parámetros obligatorios estos deberán cumplirse. Cargar metodo de controlador en rutas ************************************* Lo lógico y más común es devolver un controlador que ya se encargará de toda la lógica que va a llevar la vista: .. code-block:: php :linenos: // La ruta recibe como segundo parámetro el controlador y tras la @ el método que ejecutar: Route::get('/consolas', 'ConsolaController@index'); Colecciones de rutas ******************** Se pueden crear prefijos para ordenar las rutas que van dentro de un CRUD: .. code-block:: PHP :linenos: Route::group(['prefix'=>'consolas'], function(){ Route::get('index', 'ConsolasController@index'); Route::get('listar', 'ConsolasController@listar'); }); Middlewares ########### Los middlewares son filtros en Laravel, existen ya algunos definidos por defecto: - Crear middleware: ``php artisan make:middleware CheckConsola`` - El middelware se puede editar dentro de **Http/middleware**: .. code-block:: php :linenos: route('modelo'); // si el modelo no es el que tenemos disponible: if(is_null($modelo) || $modelo != 'playstation'){ // redirecciona al listado: return redirect()->action('ConsolaController@index'); } return $next($request); } } - Hay que dar de alta el middleware en **Http/kernel.php** añadidendo una nueva línea dentro del array **$routeMiddleware**: ``'checkconsola' => \App\Http\Middleware\CheckConsola::class,`` - Ahora en las rutas de **webs.php** se define el middelware: .. code-block:: php :linenos: // añadir el middleware: Route::get('/consola/{modelo?}', array( 'middleware' => 'checkconsola', 'uses' => 'ConsolaController@consola' )); De este modo, el middleware cuando reciba por parámetros una consola que no sea playstation hará un redireccionamiento al listado. Vistas en Laravel (plantillas Blade) #################################### Las vistas están en formato blade y las podemos encontrar en **resources/views/**. Su nomenclatura se define por terminar en **.blade.php** para hacer referencia que son plantillas blade. A la hora de trabajar con vistas es bueno crear una carpeta dentro de **views** llamada **consolas**, dentro de esta carpeta se pueden crear todas las vistas relacionadas con las consolas, por ejemplo **listar-consolas.blade.php**: .. code-block:: php :linenos:

Listado de consolas

La ruta para cargar esta vista que se encuentra dentro de una carpeta sería la siguiente: .. code-block:: php :linenos: Route::get('/consolas', function(){ // con el . se indica una ruta de carpetas en views: return view('consolas.listar-consolas'); }); Uso de variables **************** Las variables se pueden cargar desde el controlador con el uso de dobles llaves **{{ $variable }}**: .. code-block:: php :linenos:

{{ $titulo }}

.. note:: Para añadir comentarios en Blade se usa la sintaxis: **{! Comentario !}**, a diferencia de los comentarios html, los comentarios blade no se muestran en el código HTML ya que queda a nivel backend. Condicional if ************** Las condiciones if se ejecutan con el tag **@if, @else, @endif**: .. code-block:: php :linenos:

{{ $titulo }}

{! Se crea la condición que se valida entre paréntesis igual que un if corriente !} @if($consolas) @else

No hay consolas disponibles

@endif .. note se puede añadir un **@elseif($valor)** para validar otra condición adicional. Bucle foreach ************* Los bucles for se ejecutan con el tag **@foreach**: .. code-block:: php :linenos:

{{ $titulo }}

.. note:: Se puede ejecutar el foreach clave => valor de un mismo modo que en PHP. .. note:: Existe del mismo modo el bucle for sencillo y el bucle while, sin embargo este tipo de estructuras es mejor utilizarlas en los controladores. Plantilla Base ************** Las plantillas base como en otros frameworks se utilizan para establecer las partes que serán genéricas en todas o la gran mayoría de páginas del proyecto, estas plantillas se suelen guardar en la carpeta **layouts** la cual habrá que crear dentro de **views**. La plantilla base suele tener el nombre **base.blade.php**: .. code-block:: php :linenos: {{-- es muy útil el uso de Yield para sustituir partes estratégicas: --}} @yield('title') {{-- Cada section muestra un bloque de contenido: --}} @section('header')

Listado de consolas

@show
{{-- con yield se define el contenido a sustituir --}} @yield('content')
@section('footer') Laravel en Fullcoder @show - Lo siguiente será cargar la base en una plantilla como **listar-consolas.blade.php**: .. code-block:: php :linenos: {{-- Ahora se extiende la plantilla base: --}} @extends('layouts.base') {{-- Se reemplaza el title del sitio: --}} @section('title', 'Listado de consolas:') {{-- Se carga el section para sustituir el yield content con el listado de consolas: --}} @section('content') @stop {{-- se puede añadir o cambiar el comportamiento de un bloque: --}} @section('footer')

Parte exclusiva en el footer de Listado de consolas

{{-- si se añade parent heredará el contenido original, sino sustituye el bloque completo --}} @parent @stop Includes ******** Se puede cargar otras vistas por ejemplo creando en la carpeta views una carpeta llamada **includes** y dentro se puede crear por ejemplo **header.blade.php**: .. code-block:: php :linenos:

Soy una cabezera


Para cargar dicho header se accede a una plantilla blade como **consolas.blade.php**: .. code-block:: php :linenos: {! esta cabezera se puede añadir tantas veces como haga falta: !} @include('includes.header')

Listado de consolas

Enlaces a otras rutas ********************* .. code-block:: php :linenos: {{-- Con action se llama al metodo del controlador para crear el enlace: --}} Listado de consolas .. note:: Existe también el método **route()** pero para ello hay que definir un alias a la ruta. Mostrar notificaciones ********************** - Tenemos el caso en el que se elimina un registro: .. code-block:: php :linenos: public function borrarConsola($id){ $consola = DB::table('lista_consolas')->where('id', $id)->delete(); // se utiliza with para guardar datos en una sesión flash, osea que solo aparecerá 1 vez ideal para notificaciones: return redirect()->action('ConsolaController@index')->with('status', 'Consola eliminada con éxito'); } - En la vista se puede utilizar las sesiones para cargar el status que hemos creado: .. code-block:: php :linenos: @extends('layouts.base') @section('title', 'Listado de consolas:') @section('content') @stop @section('footer')

Parte exclusiva en el footer de Listado de consolas

@parent @stop {{-- Con blade se muestran los datos almacenados en sesión via with: --}} @if(session('status'))

{{ session('status') }}

@endif Controladores en Laravel ######################## - Crear controlador: ``php artisan make:controller ConsolaController`` - Acceder al archivo del controlador en **Http/Controllers**: .. code-block:: php :linenos: $consolas )); } } - Ahora se llama al controlador desde las rutas: .. code-block:: :linenos: // La ruta recibe como segundo parámetro el controlador y tras la @ el método que ejecutar: Route::get('/consolas', 'ConsolaController@index'); .. note:: La vista ahora se puede recorrer el valor con foreach para cargar las consolas en un listado. Manejar parámetros en el controlador ************************************ .. code-block:: php :linenos: array( 'marca' => 'Sony', 'modelo' => 'Playstation', 'lanzamiento' => 1994 ) ]; // dudoso modo de validar el índice: $modelo = $modelo ? $consolasDetalle[$modelo] : Null; // respuesta: return view('consolas.consola', array( 'consola' => $modelo )); } } Redirección a otra ruta *********************** .. code-block:: php :linenos: public function volver(){ // se le pasa el método redirect y el método del controlador que va a disparar la acción: return redirect()->action('ConsolaController@index') } Crear Crud y enrutamiento automático ************************************ Con Artisan se puede crear un CRUD completo y recuperar todas sus rutas de manera automática: 1. Crear controlador con CRUD: ``php artisan make:controller UserController --resource`` 2. Crear ruta con método **resources()**: .. code-block:: php :linenos: // ruta de un CRUD completo: Route::resource('user', 'UserController'); 3. Comprobar que existen las rutas nuevas: ``php artisan routes:list`` Y con esto ya existen todos los métodos de un CRUD. Muy útil para crear servicios REST. Formularios ########### - Crear un formulario en blade: .. code-block:: php :linenos:

Formulario registro consola

{{-- es imprescindible enviar el csrf para evitar fallos: --}} {{ csrf_field() }}
- Crear las rutas que muestran el formulario y la que recibe los datos: .. code-block:: :linenos: // rutas para el formulario: Route::get('/consolas/nueva', 'ConsolaController@nuevaConsola'); Route::post('/consolas/nueva', 'ConsolaController@nuevaConsola'); - Crear un nuevo método en el controlador **ConsolaController** para mostrar formulario: .. code-block:: php :linenos: public function nuevaConsola(Request $request){ $response = view('consolas.nuevaConsola'); $marca = $request->input('marca'); $modelo = $request->input('modelo'); $lanzamiento = $request->input('lanzamiento'); if($request->input('marca') && $request->input('modelo') && $request->input('lanzamiento')){ $response = $marca . " " . $modelo . " fue lanzada en " . $lanzamiento; } return $response; } Con este controlador se ha establecido la validación cuando reciba todos los datos mostrará una respuesta. Bases de datos ############## Migraciones *********** - Crear una nueva migración: ``php artisan make:migration create_consolas_table --table=lista_consolas`` - Las migraciones se encuentra en **database/migrations/** ahí se puede ver el archivo **create_consolas_table**: .. code-block:: PHP :linenos: increments('id'); // el tipo increments será autoincremental y por defecto primary key. $table->string('marca', 255); $table->string('modelo', 255); $table->integer('lanzamiento'); // buena practica es crear un timestamps para registrar cambios en los datos: $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() // borra la tabla { // se define el drop para eliminar la tabla: Schema::drop('lista_consolas'); } } - Lanzar todas la migraciones: ``php artisan migrate`` - Refrescar los cambios en las migraciones: ``php artisan migrate:refresh`` .. attention:: Es necesario tener configurado el archivo **.env** para conectarse a la base de datos. .. attention:: Al refrescar las tablas se borran los registros. Generar Seeders *************** Los seeders se utilizan para rellenar datos de prueba en una aplicación: - Lo primero es ejecutar el comando: ``php artisan make:seed lista_consolas_seed`` - En la carpeta **database/seeds/** se ha creado el archivo **lista_consolas_seed.php**: .. code-block:: php :linenos: 'Sega', 'modelo' => 'Dreamcast', 'lanzamiento' => 1998, 'n_ventas' => 2000000 ), array( 'marca' => 'Nintendo', 'modelo' => 'WiiU', 'lanzamiento' => 2015, 'n_ventas' => 11000 ) ]; // aquí se ejecuta la consulta que va a introducir en la base de datos una vez ejecutemos el seed: DB::table('lista_consolas')->insert($consolas); // lanzamos un mensaje por consola: $this->command->info('Se ha rellenado la tabla de lista_consolas'); } } - Ahora para lanzar el seed y que guarde los registros: ``php artisan db:seed --class=lista_consolas_seed`` .. attention:: En caso de que indique un error de tipo **no se encuentra la clase lista_consolas_seed.php** habrá que ejecutar el comando ``composer dump-autoload`` para solucionar el problema. Relaciones de tablas y tablas ya existentes ******************************************* Aparte de las relaciones entre tablas veremos como tener un modelo que trabaja con una tabla que se creó desde mysql: * Tabla con relación de uno a muchos (Category): .. code-block:: php :linenos: hasMany('App\Post'); } } * Tabla con relación inversa (Post): .. code-block:: php :linenos: belongsTo('App\Models\User', 'user_id'); } public function category(){ return $this->belongsTo('App\Models\Category', 'category_id'); } } Query Builder Laravel ********************* Consultar datos +++++++++++++++ .. code-block:: php :linenos: public function index(){ // consulta para listar datos: $consolas = DB::table('lista_consolas')->get(); // recuperar solo registros concretos: $consolas = DB::table('lista_consolas')->where('marca', '=', 'Sega')->get(); // ordenar registros: $consolas = DB::table('lista_consolas')->orderBy('modelo', 'desc')->get(); return view('consolas.listar-consolas', array( 'consolas' => $consolas )); } public function consola($id){ // buscar un registro: $consola = DB::table('lista_consolas')->where('id', '=', $id)->first(); // respuesta: return view('consolas.consola', array( 'consola' => $consola )); } Insertar datos ++++++++++++++ .. code-block:: php :linenos: public function nuevaConsola(Request $request){ $response = view('consolas.nuevaConsola'); $marca = $request->input('marca'); $modelo = $request->input('modelo'); $lanzamiento = $request->input('lanzamiento'); $ventas = 0; if($marca && $modelo && $lanzamiento){ // guardar registro: $consola = DB::table('lista_consolas')->insert(array( 'marca' => $marca, 'modelo' => $modelo, 'lanzamiento' => $lanzamiento, 'n_ventas' => $ventas )); $response = redirect()->action('ConsolaController@index'); } return $response; } Borrar registros ++++++++++++++++ .. code-block:: php :linenos: public function borrarConsola($id){ // consulta para borrar registro: $consola = DB::table('lista_consolas')->where('id', $id)->delete(); return redirect()->action('ConsolaController@index')->with('status', 'Consola eliminada con éxito'); } - En la vista se puede utilizar las sesiones para cargar el status que hemos creado: .. code-block:: php :linenos: @extends('layouts.base') @section('title', 'Listado de consolas:') @section('content') @stop @section('footer')

Parte exclusiva en el footer de Listado de consolas

@parent @stop {{-- Con blade se muestran los datos almacenados en sesión via with: --}} @if(session('status'))

{{ session('status') }}

@endif Actualizar registros ++++++++++++++++++++ .. code-block:: php :linenos: public function editarConsola($id, Request $request){ // primero se recupera el registro: if ($request->isMethod('post')) { $consola = DB::table('lista_consolas')->where('id', $id)->update(array( 'marca' => $request->input('marca'), 'modelo' => $request->input('modelo'), 'lanzamiento' => $request->input('lanzamiento'), 'n_ventas' => 0 )); $response = redirect()->action('ConsolaController@consola', $id); }else{ $consola = DB::table('lista_consolas')->where('id', $id)->first(); $response = view('consolas.nuevaConsola', array( 'consola' => $consola )); } return $response; } - Se puede readaptar el formulario para que muestre los datos y alterne la respuesta: .. code-block:: php :linenos:

Formulario registro consola

{{ csrf_field() }}
API Restful ###########