Diferència entre revisions de la pàgina «NF2 - Framework Laravel»

De wikiserver
Dreceres ràpides: navegació, cerca
(CRUD)
(CRUD)
 
(Hi ha 228 revisions intermèdies del mateix usuari que no es mostren)
Línia 1: Línia 1:
 
'''ESTRUCTURA DIRECTORIOS'''
 
'''ESTRUCTURA DIRECTORIOS'''
  
===CREAR PROYECTO LARAVEL ===
+
===COMANDOS INDISPENSABLES LARAVEL ===
  
 
<source lang="php">
 
<source lang="php">
 +
 +
/*CREAR PROYECTOS*/
 +
 
composer create-project --prefer-dist laravel/laravel proyecto
 
composer create-project --prefer-dist laravel/laravel proyecto
  
Línia 9: Línia 12:
  
 
composer require facade/ignition  //instalar nueva página errores
 
composer require facade/ignition  //instalar nueva página errores
 +
 +
 +
/*CONTROLADORES*/
 +
 +
php artisan make:controller PeliculasController //añadir CONTROLADOR vacio
 +
 +
php artisan make:model Trainer -m  //crea el modelo Trainer y además hace la migracion
 +
 +
php artisan make:model Task -mcr  //modelo migracion controlador
 +
 +
/*MODELO*/
 +
 +
php artisan make:model Categoria
 +
 +
/*MIGRACIONES*/
 +
 +
php artisan make:migration create_categorias_table --create="categorias"  //creamos la migración (la tabla en la base de datos es en plural y el modelo en singular)
 +
 +
php artisan make:migration anadir_telefono_tabla_cate --table="categorias" //editar tabla (podemos crear otra migración con otro atributo)
 +
 +
php artisan migrate:rollback  //deshacer la última migración ejecutada y registrada en la base de datos.
 +
 +
php artisan migrate:fresh  //borra la base de datos y la carga de nuevo.
 +
 +
/*RUTAS*/
 +
 +
php artisan routes //genera todas las rutas get,put,post de un crud... Route::resource() 
 +
 +
 +
php artisan route:list -v    ////Para listar las rutas, en terminal
 
</source>
 
</source>
 +
 +
===Estructura Laravel 6===
 +
 +
:[[Estructura Laravel]]
  
 
===RUTAS BÁSICAS===
 
===RUTAS BÁSICAS===
Línia 21: Línia 58:
 
</source>
 
</source>
  
Creamos un controlador vacio, App->http->Controller->
+
Le pasamos a la ruta un identificador que tendrá un valor por defecto y esa ruta tendrá un nombre
  
 
<source lang="php">
 
<source lang="php">
php artisan make:controller MoviesController --plain
+
//dentro de la misma vista, asignamos valor por defecto
 +
Route::get('/show/{id?}',function($id="122"){
  
//en route
+
    return $id;
Route::get('/ejemplo', 'PeliculasController@index');
+
   
 +
    })->name('show');
 +
</source>
 +
 
 +
Otra forma de ruta y utilizando un pattern númerico (sólo pueden introducir números)
  
//en controlador
+
<source lang="php">
public function index(){
+
Route::get('/par-o-impar-{numero}',function($numero){   // no hace falta usar '/'
  
echo "hola Julio";
+
return $numero;
  
}
+
//return redirect()->to('/show/3');  -> te redirije a la ruta que le indicas
 +
//return redirect()->route('show')  -> te redirije a la ruta que tiene el nombre asignado en el name.
 +
//return redirect()->route('show',['id' => '222'])  -> en caso de pasarle algun parámetro
 +
} )->where(['number' => '[\d]+']);    // de esta forma añadimos una expresion regular para que solo puedan introducir numeros
  
 
</source>
 
</source>
  
  
 +
'''Restricciones con Expresiones Regulares'''
 
<source lang="php">
 
<source lang="php">
 +
Route::get('user/{name}', function ($name) {
 +
    //
 +
})->where('name', '[A-Za-z]+');  //nomes poden passar lletres miníscules o Majúscules como mínim una volta
  
//verbos HTTP múltiples
+
Route::get('user/{id}', function ($id) {
Route::match(['get', 'post'], '/', function () {
 
 
     //
 
     //
});
+
})->where('id', '[0-9]+');   //com a mínim, a soles podem passar com a mínim un nombre.
  
//verbos HTTP cualquiera
+
Route::get('user/{id}/{name}', function ($id, $name) {
Route::any('/', function () {
 
 
     //
 
     //
});
+
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);   //le pasamos un array en caso de más de un elemento.
 
</source>
 
</source>
  
  
 +
'''Ruta en función del ROLE'''
 
<source lang="php">
 
<source lang="php">
//dentro de la misma vista, asignamos valor por defecto
 
Route::get('/show/{id?}',function($id="122"){
 
  
    return $id;
+
// en el navegador puedes poner /admin/modificar-usuario  o  /admin/insertar-usuario
 +
Route::group(['prefix'=>'admin'],function(){
 
      
 
      
     })->name('show');
+
     Route::get('modificar-usuario',function(){
</source>
 
  
 +
    return "modifica usuario";
  
<source lang="php">
+
    });
Route::get('/par-o-impar-{numero}',function($numero){    // no hace falta usar '/'
 
  
return $numero;
 
  
//return redirect()->to('/show/3');  -> te redirije a la ruta que le indicas
+
    Route::get('insertar-usuario',function(){
//return redirect()->route('show')  -> te redirije a la ruta que tiene el nombre asignado en el name.
 
//return redirect()->route('show',['id' => '222'])  -> en caso de pasarle algun parámetro
 
} )->where(['number' => '[\d]+']);    // de esta forma añadimos una expresion regular para que solo puedan introducir numeros
 
  
</source>
+
    return "insertar usuario";
  
 +
    });
  
<source lang="php">
 
Route::get('user/{name?}', function ($name = 'John') {  //$name=null
 
    return $name;
 
 
});
 
});
 
</source>
 
</source>
  
'''Restricciones con Expresiones Regulares'''
+
 
 +
Ruta que nos lleva directamente a una vista e incluso pasarle un argumento.
 
<source lang="php">
 
<source lang="php">
Route::get('user/{name}', function ($name) {
+
Route::view('/welcome', 'welcome'); //en el caso que sólo queramos enviar a una vista sin pasar por el controlador
    //
 
})->where('name', '[A-Za-z]+');   //nomes poden passar lletres miníscules o Majúscules como mínim una volta
 
  
Route::get('user/{id}', function ($id) {
+
Route::view('/welcome', 'welcome', ['name' => 'Taylor']);
 +
</source>
 +
 
 +
 
 +
Especificamos que podemos usar GET y POST para una ruta
 +
 
 +
<source lang="php">
 +
 
 +
//verbos HTTP múltiples
 +
Route::match(['get', 'post'], '/', function () {
 
     //
 
     //
})->where('id', '[0-9]+');   //com a mínim, a soles podem passar com a mínim un nombre.
+
});
  
Route::get('user/{id}/{name}', function ($id, $name) {
+
//verbos HTTP cualquiera
 +
Route::any('/', function () {
 
     //
 
     //
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);   //le pasamos un array en caso de más de un elemento.
+
});
 
</source>
 
</source>
  
 +
Creamos un controlador vacio, App->http->Controller->
  
'''Ruta en función del ROLE'''
 
 
<source lang="php">
 
<source lang="php">
 +
php artisan make:controller MoviesController --plain
  
// en el navegador puedes poner /admin/modificar-usuario  o  /admin/insertar-usuario
+
//en route
Route::group(['prefix'=>'admin'],function(){
+
Route::get('/ejemplo', 'PeliculasController@index');
   
 
    Route::get('modificar-usuario',function(){
 
  
    return "modifica usuario";
+
//en controlador
 +
public function index(){
  
    });
+
echo "hola Julio";
  
 +
}
  
    Route::get('insertar-usuario',function(){
 
 
    return "insertar usuario";
 
 
    });
 
 
});
 
 
</source>
 
</source>
 
  
 
https://github.com/dbushell/Nestable
 
https://github.com/dbushell/Nestable
Línia 129: Línia 171:
 
https://pablomonteserin.com/curso/laravel/
 
https://pablomonteserin.com/curso/laravel/
  
===RELACIONES===
+
===VISTA===
 +
Podemos aprovechar herencia en las vistas, por ello, vamos a crear.
  
Se puede crear primero el Modelo(Entidad) y luego generar la migración, el problema es que si diseñamos el modelo Escritor(Entidad) generará automáticamente la migración Escritors, habría que definir la tabla en la entidad.
+
También podemos crear una carpeta que contiene vistas "menú" y dentro las páginas, para acceder a ellos, habría que poner "menu.pagina"
  
Por tanto, la otra opción es diseñar primero la migración (tablas) y luego los modelos (entidades)
+
'''Vista Padre LAYOUT.blade.php'''
  
===RELACIÓN UNO A MUCHOS (1XM)===
+
<source lang="php">
 +
<!DOCTYPE html>
 +
<head>
 +
    <title>
 +
        @yield('titulo')
 +
    </title>
 +
</head>
 +
<body>
  
Una categoria tiene muchos artículos.
+
<ul>
Creamos primero las migraciones (bases datos) y luego el modelo (Entidades), también tenemos la opción de crear el modelo y luego automaticamente las migraciones pero hay que tener cuidado ya que genera el nombre de las tablas de la migración en inglés.
+
  <li><a href="#home">Home</a></li>
 +
  <li><a href="#news">News</a></li>
 +
  <li><a href="#contact">Contact</a></li>
 +
  <li><a href="#about">About</a></li>
 +
</ul>
 +
 
 +
@yield('contenido')
 +
 
 +
</body>
 +
</html>
 +
</source>
  
<source lang="script">
+
'''Vista Layout Hija hija.blade.php'''
php artisan make:migration create_categorias_table --create="categorias"
+
<source lang="php">
 +
@extends('layout')
  
 +
@section('titulo','Página Heredada')
  
php artisan make:migration create_articulos_table --create="articulos"
+
@section('contenido')
 +
    <h1>Página Hija</h1>
 +
@endsection
 
</source>
 
</source>
  
  
 +
===SESIONES===
 +
https://laravel.com/docs/6.x/session
 +
<source lang="php">
 +
/*diferentes formas de crear variables de sesión en el CONTROLADOR*/
  
Tablas migraciones
+
$request->session()->put(['Julio'=>'Administrador']); //crea variable sesión con clave Julio y valor Administrador
<source lang="php">
 
//tabla Categories
 
  Schema::create('categorias', function (Blueprint $table) {
 
            $table->increments('id')->unsigned();
 
            $table->text('nombre');
 
            $table->mediumText('masInfo');
 
            $table->timestamps();
 
        });
 
  
//tabla Posts
+
session(['nombre'=>'Julio']); //otra forma de crear variables sesión
  
 +
$nombre= session('nombre') 
  
    Schema::create('articulos', function (Blueprint $table) {
+
$request->session()->forget('Juan'); //Borra Juan
            $table->increments('id')->unsigned();
 
            $table->integer('categoria_id')->unsigned();  //si hubieramos puesto categorias_id tambien hubiera cogido la relación
 
            $table->text('titulo');
 
            $table->mediumText('descripcion');
 
            $table->timestamps();
 
            //relaciones
 
            $table->foreign('categoria_id')->references('id')->on('categorias')->onDelete('cascade')->onUpdate('cascade');
 
            //category_id hace referencia a la tabla categories y el borrado y la actualización es en cascada.
 
        });
 
  
 +
$request->session()->flush(); //borra todo
  
</source>
+
return $request->session()->all();  //muestra todas las variables de sesión
 +
dd(session()->all()) //muestra todas las variables de sesión
  
Creamos los modelos
+
/*mostrar variables sesión en blade VISTA*/
  
php artisan make:model Categoria
+
{{session('julio')}}
 +
</source>
  
 +
===MENSAJES FLASH===
 
<source lang="php">
 
<source lang="php">
//Modelo Categoria
+
//cuando en una página queremos enviar un mensaje flahs podemos poner
class Categoria extends Model
+
 
{
+
return back()->with('status','hemos recibido el mensaje'); //guardamos un mensaje flash
    protected $table = 'categorias';
 
    //protected $primary_key = 'categoria_id';
 
    //public $timestamps = true;  //especificamos si queremos crear created_at y updated_at en la base de datos
 
    protected $fillable = ['nombre', 'masInfo'];
 
  
    public function articulos()
+
//luego en la misma pagina (back) ponemos una condicion en blade si hay mensaje de sesion muestra sino formulario.
    {
+
@if(session('status'))
        return $this->hasMany('App\Articulo');
+
{{session('status')}}
    }
+
@else
}
+
formulario
 +
@endif
  
 +
//como vamos a repetir este codigo en muchos lados, podemos ponerlo en un fichero partial (resources-views-partial) y luego en el codigo lo sustituimos por @include en el editar.blade.php
  
//Modelo Artículos
+
</source>
  
class Articulo extends Model
+
===ALERT SWEET===
{
+
https://sweetalert.js.org/guides/
    protected $table = 'articulos';
+
 
    protected $fillable = ['titulo', 'descripcion'];
+
<source lang="php">
 +
<script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
 +
 
 +
//ponerlo debajo del DOM en la vista
 +
<script>
 +
@if (session('success'))
 +
swal("Buen Trabajo!", "{{ session('success') }}", "success");
 +
@endif
 +
</script>
 +
 
 +
 
 +
//en el controlador
 +
return back()->with('success','Hemos recibido el mensaje');
  
    public function categoria()
 
    {
 
        return $this->belongsTo('Categoria');
 
    }
 
}
 
 
</source>
 
</source>
  
En el controlador
+
===TOASTR===
 +
 
 +
En la página siguiente podemos hacer las modificaciones del script como más nos guste y sustituirlo en vez "toastr.info(....);"
 +
 
 +
https://codeseven.github.io/toastr/demo.html
 +
 
 +
https://github.com/CodeSeven/toastr
 +
 
  
 
<source lang="php">
 
<source lang="php">
  public function insertar()
+
/*En la VISTA*/
    {
+
<!--Añadir librerias BOOTSTRAP-->
        $categoria = Categoria::find(3);   //buscamos que ya tenemos almacenada o la creamos.
+
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
 +
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
 +
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
 +
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
 +
 
 +
<!--Añadir librerias TOASTR-->
 +
  <link href="//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/css/toastr.min.css" rel="stylesheet">
 +
   <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/js/toastr.min.js"></script>
 +
 
 +
.......
 +
 
 +
<script>
 +
    @if(Session::has('info'))
 +
        toastr.info("{{ session('info') }}");
 +
    @endif
 +
</script>
  
        $articulo = new Articulo(['titulo' => 'Pedazo Artículo', 'descripcion' => 'toda la descripción']);  //creamos artículo.
 
        $categoria->articulos()->save($articulo);  //guardamos dentro de categoria un artículo.
 
     
 
      //en caso que tengamos varios artículos
 
      /* $categoria->articulos()->saveMany([
 
            new Articulo(['titulo' => 'A new comment.', 'descripcion' => 'hola']),
 
            new Articulo(['titulo' => 'Another comment.',  'descripcion' => 'hola']),
 
        ]);*/
 
       
 
    }
 
</source>
 
http://documentacion-laravel.com/eloquent-relationships.html#insertando-y-actualizando-modelos-relacionados
 
  
'''mostrar artículos'''
+
/*En el CONTROLADOR*/
 +
return back()->with('info','Hemos recibido el mensaje');
  
<source lang="php">
+
</script>
//Métodos de relación
 
  
$categoria = Categoria::find(3);  //debe existir categoria y artículos
+
</source>
return $categoria->articulos()->where('descripcion', "hola")->get();
 
  
 +
===BASES DE DATOS - ORM===
  
//Propiedades dinámicas
+
Para crear una base de datos empezaremos con una tabla, es recomendable primero crear la migracion que corresponde con la tabla en la base de datos "articulos" y a continuación crearemos el modelo que corresponde con la entidad "Articulo". Es preferible crearlo en ese orden, también hay que tener cuidado a la hora de crear la migración en plural y la entidad en singular.
  
$categoria = Categoria::find(3);
+
'''php artisan make:migration create_articulos_table --create="articulos"'''
  
foreach ($categoria->articulos as $articulo) {
+
<source lang="php">
    print_r($articulo->titulo);
+
//Tabla articulos
    }
+
Schema::create('articulos', function (Blueprint $table) {
 +
            $table->increments('id')->unsigned();
 +
            $table->text('titulo');
 +
            $table->mediumText('descripcion');
 +
            $table->timestamps();
 +
          });
 
</source>
 
</source>
  
'''Borrado'''
+
'''IMPORTANTE -  TIPOS DE COLUMNAS'''
<source lang="php">
 
//borra la categoria 9 y todos los articulos relacionados (cascada)
 
$Categoria = Categoria::find(9);
 
$Categoria->delete();
 
  
//borra artículo
+
https://laravel.com/docs/6.x/migrations#creating-columns
$articulo = Articulo::find(2);       
 
$articulo->delete();
 
</source>
 
  
  
 +
'''php artisan make:model Articulo'''
  
https://medium.com/@hemnys25/de-0-a-100-con-eloquent-de-laravel-parte-0-d5347c060ad7
+
<source lang="php">
 +
//Modelo Articulo
 +
class Articulo extends Model
 +
{
 +
    protected $table = 'articulos';  //hacemos referencia a la tabla artículos
 +
    protected $fillable = ['titulo', 'descripcion'];  //fillable para proteger los campos que desea que permitan la actualización a la hora de insertar en la base de datos por asignación masiva
  
<source lang="php">
+
}
 
</source>
 
</source>
  
===RELACION DE MUCHOS A MUCHOS (NXM)===
+
===SEEDER (SEMILLAS)===
  
Un post puede tener muchas Etiquetas y una etiqueta puede tener muchos Posts, por tanto habrá que crear una tabla auxiliar.
+
'''SEEDER normal'''
  
 +
1. Ejecutamos en terminal '''php artisan make:seeder NombreSeeder'''
  
php artisan make:migration create_etiquetas_table --create="etiquetas"
+
2. podemos ver que dentro de '''database->seeds''' se genera la nueva semilla e introducimos los siguientes datos.
  
php artisan make:migration create_posts_table --create="posts"
+
<source lang="php">
  
php artisan make:migration create_etiqueta_post_table --create="etiqueta_post"
+
//y en la clase NombreSeeder:
  
 +
use Illuminate\Support\Facades\DB;
 +
use Illuminate\Support\Facades\Hash;
 +
use Illuminate\Support\Str;
  
Dentro de la tabla de migraciones
+
......
<source lang="php">
 
  
//ETIQUETAS
+
  for ($i=0; $i<10; $i++) {
Schema::create('etiquetas', function (Blueprint $table) {
+
        DB::table('projects')->insert([
             $table->increments('id');
+
            'title' => Str::random(10),
 
+
            'description' => Str::random(10).'@gmail.com',
             $table->string('nombre',128);
+
             'created_at' => date('Y-m-d'),
            $table->string('slug',128);
+
             'updated_at' => date('Y-m-d')        ]);
 +
    }
 +
</source>
 +
 
 +
3. luego en la clase '''DataBaseSeeder''' (otro fichero que ya está creado) activamos dentro de la clase '''$this->call(NombreSeeder::class);'''
  
            $table->timestamps();
+
<source lang="php">
        });
+
.....
 +
  public function run()
 +
    {
 +
      $this->call(NombreSeeder::class);
 +
    }
 +
</source>
  
//POSTS
+
4. Para generar los datos insertarmos en terminal  '''php artisan db:seed'''
  Schema::create('posts', function (Blueprint $table) {
 
            $table->increments('id');
 
  
            $table->string('nombre',128)->unique();
+
https://laravel.com/docs/6.x/seeding
            $table->string('slug',128);
 
            $table->text('cuerpo');
 
            $table->enum('status',['PUBLISHED','DRAFT'])->default('DRAFT');
 
            $table->string('file', 128)->nullable();
 
 
            $table->timestamps();
 
           
 
        });
 
  
//ETIQUETA_POST
 
Schema::create('etiqueta_post', function (Blueprint $table) {
 
            $table->increments('id');
 
  
            $table->integer('post_id')->unsigned();
+
'''CLASE FAKER'''
            $table->integer('etiqueta_id')->unsigned();
+
 
 +
Para utilizar la clase FAKER, viene a ser igual que la Seeder que trae por defecto Laravel. Página oficial https://github.com/fzaninotto/Faker#formatters
  
            $table->timestamps();
+
1. Instalamos la libreria en terminal '''composer require fzaninotto/faker'''
  
            //relaciones
+
2.  Ejecutamos en terminal '''php artisan make:seeder NombreSeeder'''
            $table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade')->onUpdate('cascade');
 
            $table->foreign('etiqueta_id')->references('id')->on('etiquetas')->onDelete('cascade')->onUpdate('cascade');
 
        });
 
</source>
 
  
 +
3. podemos ver que dentro de '''database->seeds''' se genera la nueva semilla e introducimos los siguientes datos.
  
Dentro de los modelos
 
 
<source lang="php">
 
<source lang="php">
//Modelo POST
+
//si queremos utilizar la clase FAKER
class Post extends Model
+
 
 +
use Illuminate\Database\Seeder;
 +
use Illuminate\Support\Facades\DB;
 +
use Faker\Factory as Faker;
 +
 
 +
class ContactosSeeder extends Seeder
 
{
 
{
    protected $table = 'posts';
+
  public function run(){
     //protected $primary_key = 'categoria_id';
+
     // puntero para recorrer Faker
     protected $fillable = ['nombre', 'cuerpo','status'];
+
     $handle = Faker::create();
  
     public function etiquetas()
+
     for ($i=0; $i<10; $i++) {
    {
+
      DB::table('contactos')->insert([
         return $this->belongsToMany('App\Etiqueta');
+
        'nombre' => $handle->firstName,
 +
        'apellidos' => $handle->lastName,
 +
        'created_at' => $handle->dateTime($max = 'now', $timezone = null),
 +
         'updated_at' => $handle->dateTime($max = 'now', $timezone = null)
 +
      ]);
 
     }
 
     }
 +
  }
 
}
 
}
 +
</source>
  
//Modelo ETIQUETA
+
3. luego en la clase '''DataBaseSeeder''' (otro fichero que ya está creado) activamos dentro de la clase '''$this->call(NombreSeeder::class);'''
  
class Etiqueta extends Model
+
<source lang="php">
{
+
.....
    protected $table = 'etiquetas';
+
  public function run()
    //protected $primary_key = 'categoria_id';
 
    protected $fillable = ['nombre', 'slug'];
 
 
 
    public function posts()
 
 
     {
 
     {
        return $this->belongsToMany('App\Post');
+
      $this->call(NombreSeeder::class);
 
     }
 
     }
}
 
 
</source>
 
</source>
  
//INSERTAR Tabla intermedia
+
4. Para generar los datos insertarmos en terminal  '''php artisan db:seed'''
 +
 
 +
===CONSTRUCTOR DE CONSULTAS (Query Builder)===
 +
Cuando estamos usando conexiones múltiple
 
<source lang="php">
 
<source lang="php">
        public function insertarTablaIntermedia(){
+
//añadimos
        $etiqueta=Etiqueta::find(1);
+
use Illuminate\Support\Facades\DB;
        $post = Post::find(2);
+
 
        $post->etiquetas()->attach($etiqueta);
+
....
      }
+
//obtenemos todos los usuarios
</source>
+
$users = DB::table('users')->get();
  
//OBTENER DATOS DE LA otra TABLA RELACIONADA.
+
foreach ($users as $user)
<source lang="php">
+
{
return Post::find(1)->etiquetas()->get();
+
    echo $user->name;
return Post::find(1)->etiquetas()->where('nombre','etiqueta1')->get();
+
}
</source>
 
  
===CRUD===
+
//Más ejemplos de consultas
 +
$user = DB::table('users')->first();
  
Creas la tabla
+
$user = DB::table('users')->where('name', 'julio')->get();
  
php artisan make:migration create_blogs_table --create=blogs
+
$users = DB::table('users')->where('edad', '>', 100)->get();
  
 +
$users = DB::table('users')->where('estado', '<>', 'active')->get();
  
Luego en la migración creas los campos para la base de datos
+
$users = DB::table('users')->where('name', 'like', 'J%')->get();
  
<source lang="php">
+
//insertar
Schema::create('blogs', function (Blueprint $table) {
+
DB::table('Articulos')->insert(
$table->bigIncrements('id');
+
        ['titulo'=>"pepe",'descripcion'=>"nuevadescripcion"]
$table->string('blog_title');
+
    );
$table->text('blog_content');
 
$table->timestamps();
 
});
 
 
 
</source>
 
  
Generas las rutas insertando el fichero Web
+
//update
  
<source lang="php">
+
DB::table('datos')
 +
              ->where('id', 1)
 +
              ->update(['nombre' => 'Estefania']);
  
Route::resource('blogs','blogController');
+
//delete
 +
DB::table('datos')->delete();
 +
DB::table('datos')->where('votes', '>', 100)->delete();
 +
</source>
  
//Para listar las rutas, en terminal
+
https://laravel.com/docs/6.x/queries
  
php artisan route:list -v
+
===CONSULTAS SQL NATIVAS===
</source>
 
  
Creamos el modelo
 
 
<source lang="php">
 
<source lang="php">
php artisan make:model Blog
+
//seleccionar
 +
$results = DB::select('select * from users where id = :id', ['id' => 1]);
  
//dentro del modelo
+
//insertar en la Base users
class Blog extends Model
+
DB::insert('insert into users (id, name) values (?, ?)', [1, 'Dayle']);
{
 
protected $fillable = ['blog_title', 'blog_content'];
 
  
//¿Qué atributos deberías incluir en dicho array?
+
//actualizar
 +
$affected = DB::update('update users set votes = 100 where name = ?', ['John']);
  
//Aquellos que consideres sensibles y que no deberían modificarse o asignarse en cierta forma, el más típico es el id, el cual normalmente no se modifica ni se asigna de forma manual.
+
//borrar
}
+
$deleted = DB::delete('delete from users');
 +
 
 +
//Ejecutando una instrucción general que no devuelve ningún valor
 +
DB::statement('drop table users');
  
 
</source>
 
</source>
 +
http://documentacion-laravel.com/database.html#ejecutando-consultas-sql-nativas
 +
 +
===ELOQUENT===
  
Creamos Controlador
 
  
 
<source lang="php">
 
<source lang="php">
php artisan make:controller blogController --resource
 
1.index()
 
  
2.create()
+
$escritores=Escritor::all();  //$escritores=Escritor::get();
 +
 
 +
$escritoresOrdenados=Escritor::orderBy('nombre','DESC')->get();
  
3.store()
+
$escritor= App\Escritor::findOrFail(1);
  
4.show()
+
$escritor= App\Escritor::where('edad', '>', 100)->firstOrFail();
  
5.edit()
+
$escritor= App\Escritor::whereEdad(100)->get();  //es más eficiente especificar las columnas Escritor::select('id','name')->whereEdad(100)->get()
  
6.update()
+
$EscritoresUlti=Escritor::latest('created_at')->get();  //muestra los últimos que se han añadido
  
7.destroy()
 
 
</source>
 
</source>
https://www.expertsphp.com/laravel-6-crud-create-read-update-delete-generator-for-beginners-with-example/
 
<source lang="php">
 
  
</source>
 
  
 
<source lang="php">
 
<source lang="php">
//creamos la migracion que es la tabla en la base de datos "datos"
+
//insertar
 +
        $escritor = new Escritor(); 
 +
        $escritor->nombre = 'Julio';   
 +
        $escritor->save();
  
Schema::create('datos', function (Blueprint $table) {
+
//actualizar
            $table->bigIncrements('id');
+
        $escritor = Escritor::find(1);  //$escritor = App/Escritor::find(1);
            $table->string('nombre');
+
        $escritor->nombre = 'Pepe';    //$request->name;
            $table->text('descripcion');
+
        $escritor->save();
            $table->timestamps();
+
//borrar
        });
+
        $escritor= App\Escritor::find(1);
 +
        $escritor->delete();
 +
 
 +
</source>
  
//creamos el modelo "Dato" que es la Entidad que vamos a trabajar y dentro ponemos los datos que queremos proteger.
+
*'''all()''' devuelve todos los elementos de una tabla.
  
protected $fillable = ['nombre', 'descripcion'];
+
*'''find($id)''' coge una id y devuelve un sólo modelo. Si no existe un modelo coincidente, devuelve '''null'''.
  
añadimos las rutas
+
*'''findOrFail($id)''' toma una idy devuelve un sólo modelo. Si no existe un modelo coincidente, arroja un error1 404.
  
</source>
+
*'''first()''' devuelve el primer registro encontrado en la base de datos. Si no existe un modelo coincidente, devuelve '''null'''.
  
<source lang="php">
+
*'''firstOrFail()''' devuelve el primer registro encontrado en la base de datos. Si no existe un modelo coincidente, arroja un error1 404.
  
public function index(){
+
*'''get()''' devuelve una colección de modelos que coinciden con la consulta.
  
    $datos=Dato::all();
+
*'''findOrCreate()''' en el caso que no existe en la BD, lo crea.
  
    return view('index',['datos'=>$datos]);  //view('index',compact('datos');
+
<source lang="php">
  }
+
$dato=Escritor::firstOrCreate(['nombre'=>'Estefania','edad'=>'32']);
 +
</source>
 +
https://laravel-news.com/firstornew-firstorcreate-firstor-updateorcreate
  
//en la vista
+
*'''toArray()''' convierte el modelo / colección en una matriz PHP simple.
@forelse ($datos as $item)
 
<li> {{$item->nombre}} {{$item->descripcion}} <a href="{{ route('editar', $item->id)}}" >Edit</a>
 
  <form action="{{ route('borrar', $item->id)}}" method="post">
 
        @csrf
 
        @method('DELETE')
 
        <button type="submit">borrar</button>
 
    </form>
 
</li>
 
@empty
 
<li>NO HAY NADA </li>
 
@endforelse
 
  
 +
*'''Pluck()''' en caso de obtener una colección y filtrar la parte que nos interesa.
  
 +
<source lang="php">
 +
$users = User::all(); // Devuelve una colección de usuarios, por ejemplo, ['name' => 'John', 'age' => 55],['name' => 'Melissa', 'age' => 18],['name' => 'Bob', 'age' => 43]
 +
$usernames = $users->pluck('name'); // tenemos una colección de ['John', 'Melissa', 'Bob', 'Sara']
 
</source>
 
</source>
  
  
<source lang="php">
+
'''¿Cúal forma es mejor o más óptima? ¿SQL NATIVE o QUERY BUILDER o ELOQUENT?'''
  
public function almacenar(Request $request){
+
https://www.laraveltip.com/que-es-mejor-eloquent-query-builder-o-sql/
  
//LA MEJOR FORMA DE INSERTAR DATOS ya que se hace la comprobación de los campos obligatorios para que no hagan inyeccion y luego inserta.
+
===PAGINAR===
    $datos=request()->validate([
+
<source lang="php">
        'nombre'=>'required|max:25',
+
/*en CONTROLADOR de index*/
        'descripcion'=>'required']
+
        $datos=Dato::latest()->paginate(3);
    );
+
</source>
  
    Dato::create($datos);
 
  
    return redirect()->route('index');
+
<source lang="php">
//return back(); //te redirecciona a la misma página
 
  }
 
  
//en la vista
+
/*en la VISTA debajo de forelse */
 +
//en el momento que insertamos datos dentro de la tabla y queremos mostrar los datos de forma más humana.
 +
<ul>
 +
  @forelse ($datos as $item)
 +
              <li>  {{$item->title}}  {{$item->created_at->diffForHumans() }} </li> 
 +
            @empty
 +
                <li>NO HAY NADA </li>
 +
            @endforelse
 +
</ul>
  
 +
{{$datos->links()}}  //DEBAJO DEL FORELSE
 +
</source>
  
@if ($errors->any())  //esto muestra todos los errores seguidos
+
===CRUD===
    <ul>
+
 
        @foreach ($errors->all() as $error)
+
Creas la tabla
        <li>{{ $error }}</li>
 
        @endforeach
 
    </ul>
 
<br/>
 
@endif
 
<form method="post" action="{{ route('almacenar') }}">
 
    <div>
 
        @csrf
 
        <label for="name">Nombre:</label>
 
        <input type="text" name="nombre" value="{{old('nombre')}}"/>  //ponemos old porque en el caso que carguemos el formulario y diera error habría que volver a introducir todos los campos, así recuerda o guarda los campos que están bien
 
    <!-- {!! $errors->first('name', '<small>:message</small><br>' )!!}  --> // así especificamos los errores debajo
 
    </div>
 
    <div>
 
        <label for="price">Descripcion:</label>
 
        <input type="text" name="descripcion" value="{{old('descripcion')}}"/>
 
    <!--{!! $errors->first('descripcion', '<small>:message</small><br>' )!!}  -->
 
    </div>
 
  
    <button type="submit">Crear</button>
+
'''php artisan make:migration create_blogs_table --create=blogs'''
</form>
 
  
</source>
 
  
 +
Luego en la migración creas los campos para la base de datos
  
 
<source lang="php">
 
<source lang="php">
public function editar($id){
+
Schema::create('blogs', function (Blueprint $table) {
 +
$table->bigIncrements('id');
 +
$table->string('blog_title');
 +
$table->text('blog_content');
 +
$table->timestamps();
 +
});
  
    $dato = Dato::findOrFail($id);  //como no está el dato si nos equivocamos de id nos muestra la página de error 404, podemos crear uno personalizado en la view->errors->404.blade.php , creamos carpeta "errors"
+
</source>
 +
 
 +
Para generar las rutas podemos hacer dos cosas:
 +
 
 +
'''1)Generarlas automáticamente con el nombre de las rutas en inglés.'''
  
  
    return view('editar', compact('dato'));
+
Generas las rutas insertando el fichero Web
  }
+
 
 +
<source lang="php">
  
 +
Route::resource('blogs','blogController');
  
//en la vista de Editar
+
//Para listar las rutas, en terminal
  
@if ($errors->any())
+
php artisan route:list -v
        <div class="alert alert-danger">
+
</source>
            <strong>Whoops!</strong> There were some problems with your input.<br><br>
 
            <ul>
 
                @foreach ($errors->all() as $error)
 
                    <li>{{ $error }}</li>
 
                @endforeach
 
            </ul>
 
        </div>
 
    @endif
 
  
<form method="post" action="{{ route('actualizar', $dato) }}">  //No es necesario especificar el Id ya que la nueva versión laravel ya busca dentro del Objeto
 
          <div >
 
              @method('PATCH')
 
              @csrf
 
             
 
              <label for="name">nombre:</label>
 
              <input type="text"  name="nombre" value="{{ $dato->nombre }}"/>
 
          </div>
 
          <div >
 
              <label for="descripcion">descripcion</label>
 
              <input type="text"  name="descripcion" value="{{ $dato->descripcion }}"/>
 
          </div>
 
       
 
          <button type="submit" >Actualizar</button>
 
      </form>
 
  </div>
 
</div>
 
  
//hacer el actualizar
+
'''Creamos Controlador'''
  
public function actualizar(Request $request, $id){
+
'''php artisan make:controller blogController --resource'''
 +
<source lang="php">
  
        $validacion=$request->validate([
+
1.index()
        'nombre' => 'required',
 
        'descripcion' => 'required',
 
        ]);
 
     
 
      $datos = Dato::find($id);  //podremos utilizar findOrFail($id) para que en caso de no encontrar no falle
 
        $datos->nombre = $request->get('nombre');  //$request->nombre;    //$request->input('nombre');
 
        $datos->descripcion = $request->get('descripcion');  //$request->descripcion;    //$request->input('descripcion');
 
  
        $datos->update();
+
2.create()
       
 
       
 
        // Dato::whereId($id)->update($validacion); //otra opción
 
  
      //return redirect()->route('index');
+
3.store()
     
 
    }
 
  
//$request->input() es un array
+
4.show()
  
</source>
+
5.edit()
  
 +
6.update()
  
<source lang="php">
+
7.destroy()
 +
</source>
  
//en el controlador borrar
 
  
    public function borrar($id){
+
https://www.expertsphp.com/laravel-6-crud-create-read-update-delete-generator-for-beginners-with-example/
 
 
        $dato = Dato::findOrFail($id);
 
       
 
        $dato->delete();
 
   
 
        return redirect()->route('index');
 
      }
 
  
</source>
 
  
 +
'''2) Diseñar nuestras rutas y controlador en castellano uno a uno'''
  
 
<source lang="php">
 
<source lang="php">
//rutas en Web
+
//Diseñamos nuestras rutas en Web
 
Route::get('/index', 'DatosController@index')->name('index');
 
Route::get('/index', 'DatosController@index')->name('index');
 
Route::post('/almacenar', 'DatosController@almacenar')->name('almacenar');
 
Route::post('/almacenar', 'DatosController@almacenar')->name('almacenar');
Línia 616: Línia 655:
 
Route::patch('/actualizar/{id}', 'DatosController@actualizar')->name('actualizar');
 
Route::patch('/actualizar/{id}', 'DatosController@actualizar')->name('actualizar');
 
Route::delete('/borrar/{id}', 'DatosController@borrar')->name('borrar');
 
Route::delete('/borrar/{id}', 'DatosController@borrar')->name('borrar');
 +
Route::view('/insertar','insertar')->name('insertar');
  
 
</source>
 
</source>
  
===PAGINAR===
 
<source lang="php">
 
en controlador de index
 
        $datos=Dato::latest()->paginate(3);
 
y en vista debajo de forelse
 
  
{{$datos->links()}}
+
Diseñamos la migración y el modelo, en caso de necesitarlo
</source>
 
  
 +
'''php artisan make:migration create_datos_table --create=datos'''
  
<source lang="php">
 
//en el momento que insertamos datos dentro de la tabla y queremos mostrar los datos de forma más humana.
 
<ul>
 
  @forelse ($datos as $item)
 
              <li>  {{$item->title}}  {{$item->created_at->diffForHumans() }} </li> 
 
            @empty
 
                <li>NO HAY NADA </li>
 
            @endforelse
 
        </ul>
 
</source>
 
  
  
 
<source lang="php">
 
<source lang="php">
//obtener datos.
+
//creamos la migracion que es la tabla en la base de datos "datos"
  
use app\Dato;  
+
Schema::create('datos', function (Blueprint $table) {
 +
            $table->bigIncrements('id');
 +
            $table->string('nombre');
 +
            $table->text('descripcion');
 +
            $table->timestamps();
 +
        });
  
$datos=Dato::get();
 
$datos=Dato::orderBy('nombre','DESC')->get();
 
$datos=Dato::latest('created_at')->get();  //muestra los últimos que se han añadido
 
 
</source>
 
</source>
  
  
===MANEJAR VALIDACIONES===
+
//creamos el modelo "Dato" que es la Entidad que vamos a trabajar y dentro ponemos los datos que queremos proteger.
Para hacer las validaciones hay que evitar ponerlo en el controlador ya que es una mala práctica, por tanto el controlador solo debe tener la responsabilidad de tratar las solicitudes.  
+
 
 +
'''php artisan make:model Dato'''
 +
<source lang="php">
 +
 
 +
protected $table= 'datos';
 +
protected $fillable = ['nombre', 'descripcion']; //¿Qué atributos deberías incluir en dicho array?
 +
 
 +
//Aquellos que consideres sensibles y que no deberían modificarse o asignarse en cierta forma, el más típico es el id, el cual normalmente no se modifica ni se asigna de forma manual.
 +
}
 +
 
 +
</source>
  
https://styde.net/como-trabajar-con-form-requests-en-laravel/
 
  
https://www.laraveltip.com/que-son-como-y-por-que-utilizar-los-form-request-de-laravel/
 
  
 +
'''INDEX-MOSTRAR DATOS'''
 
<source lang="php">
 
<source lang="php">
//Para mantener el código limpio y no tener que poner  app->http->request
 
php artisan make:request CreateDatosRequest  // [Nombre-del-modelo-que-impacta]+[Acción]+Request
 
  
 +
/**********en el CONTROLADOR**********/
 +
public function index(){
  
public function authorize()
+
    $datos=Dato::all();
    {
 
        return true; //cambiar a true
 
    }
 
  
     public function rules()
+
     return view('index',['datos'=>$datos]);  //view('index',compact('datos');
    {
+
  }  
        return [
 
        'nombre' => 'required',
 
        'descripcion' => 'required',
 
        ];
 
    }
 
  
    public function messages()
+
/***********en la VISTA***********/
    {
+
@forelse ($datos as $item)
        return [
+
<li>
        'nombre.required' => 'El :attribute es obligatorio campeón',
+
{{$item->nombre}} {{$item->descripcion}}
        'descripcion.required' => 'El :attribute es obligatorio también',
+
    <a href="{{ route('editar', $item->id)}}" >Edit</a> <!--añadimos también EDITAR-->
         ];
+
    <form action="{{ route('borrar', $item->id)}}" method="post"> <!--añadimos también BORRAR-->
     }
+
        @csrf
 +
        @method('DELETE')
 +
         <button type="submit">borrar</button>
 +
     </form>
 +
</li>
 +
@empty
 +
<li>NO HAY NADA </li>
 +
@endforelse
  
// en el controlador bastará con poner
 
  
 +
</source>
  
public function actualizar(CreateDatosRequest $request){
+
'''INSERTAR -STORE'''
//quitamos la validación
+
<source lang="php">
}
 
  
 +
/***********En el CONTROLADOR***********/
 +
public function almacenar(Request $request){
  
</source>
+
//LA MEJOR FORMA DE INSERTAR DATOS ya que se hace la comprobación de los campos obligatorios para que no hagan inyeccion y luego inserta.
 +
    $datos=request()->validate([
 +
        'nombre'=>'required|max:25',
 +
        'descripcion'=>'required']
 +
    );
  
 +
    Dato::create($datos);
  
===SESIONES===
+
    return redirect()->route('index');
https://laravel.com/docs/6.x/session
+
//return back(); //te redirecciona a la misma página
<source lang="php">
+
  }
$request->session()->put(['Julio'=>'Administrador']); //crea variable sesión con clave Julio y valor Administrador
 
  
  
session(['julio'=>'Estudiante']);
+
/***********En la VISTA***********/
  
$request->session()->forget('Juan'); //Borra Juan
+
@if ($errors->any())  //esto muestra todos los errores seguidos
 +
    <ul>
 +
        @foreach ($errors->all() as $error)
 +
        <li>{{ $error }}</li>
 +
        @endforeach
 +
    </ul>
 +
<br/>
 +
@endif
 +
 
 +
<form method="post" action="{{ route('almacenar') }}">
 +
/* action="{{ action('RelacionController@almacenar') }}"  //con esto vamos directamente al controlador desde la vista */
 +
 
 +
        @csrf
 +
        <label for="name">Nombre:</label>
 +
        <input type="text" name="nombre" value="{{old('nombre')}}"/>  <!--ponemos old porque en el caso que carguemos el formulario y diera error habría que volver a introducir todos los campos, así recuerda o guarda los campos que están bien-->
 +
    {!! $errors->first('name', '<small>:message</small><br>' )!!}  <!-- así especificamos los errores debajo-->
 +
 
 +
        <label for="price">Descripcion:</label>
 +
        <input type="text" name="descripcion" value="{{old('descripcion')}}"/>
 +
    {!! $errors->first('descripcion', '<small>:message</small><br>' )!!} 
 +
 +
 
 +
    <button type="submit">Crear</button>
 +
</form>
  
$request->session()->flush(); //borra todo
 
 
return $request->session()->all();  //muestra todas las variables de sesión
 
 
</source>
 
</source>
  
===MENSAJES FLASH===
+
'''EDITAR'''
 
<source lang="php">
 
<source lang="php">
//cuando en una página queremos enviar un mensaje flahs podemos poner
+
/***********EN EL CONTROLADOR***********/
  
return back()->with('status','hemos recibido el mensaje'); //guardamos un mensaje flash
+
public function editar($id){
  
//luego en la misma pagina (back) ponemos una condicion en blade si hay mensaje de sesion muestra sino formulario.
+
    $dato = Dato::findOrFail($id);  //como no está el dato si nos equivocamos de id nos muestra la página de error 404, podemos crear uno personalizado en la view->errors->404.blade.php , creamos carpeta "errors"
@if(session('status'))
 
{{session('status')}}
 
@else
 
formulario
 
@endif
 
  
//como vamos a repetir este codigo en muchos lados, podemos ponerlo en un fichero partial (resources-views-partial) y luego en el codigo lo sustituimos por @include en el editar.blade.php
 
  
</source>
+
    return view('editar', compact('dato'));
 +
  }
  
===ALERT SWEET===
 
https://sweetalert.js.org/guides/
 
  
<source lang="php">
+
/***********EN LA VISTA para EDITAR***********/
<script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
 
  
//ponerlo debajo del DOM en la vista
+
@if ($errors->any())
<script>
+
        <div class="alert alert-danger">
@if (session('success'))
+
            <strong>Whoops!</strong> There were some problems with your input.<br><br>
swal("Buen Trabajo!", "{{ session('success') }}", "success");
+
            <ul>
@endif
+
                @foreach ($errors->all() as $error)
</script>
+
                    <li>{{ $error }}</li>
 
+
                @endforeach
 
+
            </ul>
//en el controlador
+
        </div>
return back()->with('success','Hemos recibido el mensaje');
+
    @endif
 
 
</source>
 
  
 +
<form method="post" action="{{ route('actualizar', $dato) }}">  //No es necesario especificar el Id ya que la nueva versión laravel ya busca dentro del Objeto
 +
          <div >
 +
              @method('PATCH')
 +
              @csrf
 +
             
 +
              <label for="name">nombre:</label>
 +
              <input type="text"  name="nombre" value="{{ $dato->nombre }}"/>
 +
          </div>
 +
          <div >
 +
              <label for="descripcion">descripcion</label>
 +
              <input type="text"  name="descripcion" value="{{ $dato->descripcion }}"/>
 +
          </div>
 +
       
 +
          <button type="submit" >Actualizar</button>
 +
      </form>
 +
  </div>
 +
</div>
  
===VISTA===
+
/***********En el CONTROLADOR para ALMACENAR DATOS ya MODIFICADOS***********/
Podemos aprovechar herencia en las vistas, por ello, vamos a crear.
+
 
 +
public function actualizar(Request $request, $id){
  
También podemos crear una carpeta que contiene vistas "menú" y dentro las páginas, para acceder a ellos, habría que poner "menu.pagina"
+
        $validacion=$request->validate([
 +
        'nombre' => 'required|min:1|max:10',
 +
        'descripcion' => 'required',
 +
        ]);
 +
     
 +
        Dato::whereId($id)->update($validacion); //otra opción
  
'''Vista Padre LAYOUT.blade.php'''
+
        /*  //otra forma de almacenar
 +
        $datos = Dato::find($id);  //podremos utilizar findOrFail($id) para que en caso de no encontrar no falle
 +
        $datos->nombre = $validacion['nombre'];
 +
        $datos->descripcion = $validacion['descripcion'];
  
<source lang="php">
+
        $datos->update();*/
<!DOCTYPE html>
 
<head>
 
    <title>
 
        @yield('titulo')
 
    </title>
 
</head>
 
<body>
 
  
<ul>
+
        return redirect()->route('index');
  <li><a href="#home">Home</a></li>
+
     
  <li><a href="#news">News</a></li>
+
    }
  <li><a href="#contact">Contact</a></li>
 
  <li><a href="#about">About</a></li>
 
</ul>
 
 
 
@yield('contenido')
 
 
 
</body>
 
</html>
 
</source>
 
  
'''Vista Layout Hija hija.blade.php'''
 
<source lang="php">
 
@extends('layout')
 
  
@section('titulo','Página Heredada')
+
// formar de recuperar datos de un formulario. $request->get('nombre'); $request->nombre;  $request->input('nombre');
  
@section('contenido')
 
    <h1>Página Hija</h1>
 
@endsection
 
 
</source>
 
</source>
  
===AUTENTIFICACIÓN===
 
  
 +
'''BORRAR'''
 
<source lang="php">
 
<source lang="php">
//Crear usuario en versiones anteriores a 6
 
  
php artisan make:auth
+
/***********en el controlador borrar***********/
  
//Laravel 6
+
    public function borrar($id){
  
composer require laravel/ui
+
        $dato = Dato::findOrFail($id);
 
+
       
php artisan ui vue --auth
+
        $dato->delete();
 +
   
 +
        return redirect()->route('index');
 +
      }
  
</source>
 
  
Después podremos ver que en las rutas Web ha creado Auth::routes();
+
/*Otra forma de Borrar*/
 +
use App\Dato; //añadimos el modelo en el controlador
  
Dentro app->http->Auth cambiamos las rutas de register y login cambiando ruta a /
+
....
  
Quitamos la ruta /home dentro de las rutas en web
+
  public function borrar(Dato $dato){
  
"para borrar la sesion podemos borrar el fichero dentro storage->framework->session como  prueba"
+
        $dato->delete();
'''
+
                 
MUESTRA USUARIO'''
+
        return redirect()->route('index');
<source lang="php">
+
        }
@auth    //sirve para mostrar en caso de estar autentificado, estar logeado
 
{{auth()->user()->name}}
 
@endauth
 
//tambien cambiar la ruta de middleware en caso de estar autentificado y volver hacer login peta y te manda a home por tanto cambiar a raiz.
 
 
 
@if(auth()->get()) //si el usuario está autentificado
 
  
@endif
 
 
</source>
 
</source>
  
'''LOGOUT'''
+
===GENERAR CRUD AUTOMÁTICAMENTE===
  
<source lang="php">
+
https://github.com/awais-vteams/laravel-crud-generator
//usar directiva @guest- invitado. en caso de no estar logueado no muestra
 
@guest
 
<a href="{{route('login')}}">Login</a>
 
@else 
 
<a href="{{ route('logout') }}" onclick="event.preventDefault(); document.getElementById('logout-form').submit();"> Logout </a>
 
  
  <form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
+
https://github.com/appzcoder/crud-generator
    {{ csrf_field() }}
 
  </form>
 
@endguest
 
  
</source>
+
===RELACIONES===
  
'''DESHABILITAR REGISTRO'''
+
Se puede crear primero el Modelo(Entidad) y luego generar la migración, el problema es que si diseñamos el modelo Escritor(Entidad) generará automáticamente la migración Escritors, habría que definir la tabla en la entidad.
  
vamos a Web y modificamos ruta
+
Por tanto, la otra opción es diseñar primero la migración (tablas) y luego los modelos (entidades)
<source lang="php">
 
Auth::routes(['register'=>false]);
 
</source>
 
  
'''SABER SI ESTÁ LOGEADO EN EL CONTROLADOR'''
 
  
<source lang="php">
+
https://laravel.com/docs/6.x/eloquent-relationships
use Illuminate\Support\Facades\Auth;
 
  
if(Auth::check()){
 
return "estas logeado";
 
}else {
 
return "no estas logeado";
 
}
 
  
//usuario en controlador
 
use Illuminate\Support\Facades\Auth;
 
  
// Obtiene el objeto del Usuario Autenticado
+
-----------------------------
$user = Auth::user();
 
  
// Obtiene el ID del Usuario Autenticado
+
===RELACIÓN UNO A MUCHOS (1XM)===
$id = Auth::id();
 
$user->name;
 
</source>
 
  
 +
Una categoria tiene muchos artículos.
 +
Creamos primero las migraciones (bases datos) y luego el modelo (Entidades), también tenemos la opción de crear el modelo y luego automaticamente las migraciones pero hay que tener cuidado ya que genera el nombre de las tablas de la migración en inglés.
  
 +
<source lang="script">
 +
php artisan make:migration create_categorias_table --create="categorias"
  
  
''' BLOQUEAR USUARIO, INTENTOS FALLIDOS '''
+
php artisan make:migration create_articulos_table --create="articulos"
 +
</source>
  
En el caso que querramos bloquear al usuario por intentos de ingresos fallidos y penalizar el tiempo a la hora de volver autenficarte, bastará con añadir el controlador por defecto app->http->Controller->auth-> '''LoginController'''
 
  
<source lang="php">
 
class LoginController extends Controller
 
{
 
 
 
    use AuthenticatesUsers;
 
  
    public $maxAttempts = 2;  //número máximo de intentos
+
Tablas migraciones
    public $decayMinutes = 2;  //tiempo que durará el bloqueo
 
</source>
 
 
 
===MIDDLEWARE===
 
filtran las peticiones http, en nuestro caso que compruebe si el usuario está autentificado o no.
 
Son puertas que una peticion de usuario tiene que pasar antes de llegar al controlador que tiene la logica a la que el usuario intenta acceder.
 
dos formas:
 
 
<source lang="php">
 
<source lang="php">
1) añadir a la ruta dentro de Web ->middleware('auth');
 
Route::get('/insertar','MoviesController@insertar')->name('insertar')->middleware('auth');
 
  
2) Dentro del controlador añadimos dentro del constructor
+
//tabla Categories
public __construct(){
+
  Schema::create('categorias', function (Blueprint $table) {
  $this->middleware('auth')->only('create', 'edit'); //y con esto especificamos que redirija a login en caso de entrar a create y no está logeado.
+
            $table->increments('id')->unsigned();
//  $this->middleware('auth')->except('create', 'edit'); // lo contrario, bloquea a todos los metodos/controladores excepto el create y edit que podrán acceder.
+
            $table->text('nombre');
}
+
            $table->mediumText('masInfo');
 +
            $table->timestamps();
 +
        });
  
</source>
+
//tabla articulos
  
  
https://programacionymas.com/blog/restringir-acceso-solo-administradores-laravel-usando-middlewares
+
    Schema::create('articulos', function (Blueprint $table) {
 
+
            $table->increments('id')->unsigned();
===BASES DE DATOS===
+
            $table->integer('categoria_id')->unsigned()//si hubieramos puesto categorias_id tambien hubiera cogido la relación
 
+
            $table->text('titulo');
===CONSTRUCTOR DE CONSULTAS (Query Builder)===
+
            $table->mediumText('descripcion');
Cuando estamos usando conexiones múltiple
+
            $table->timestamps();
<source lang="php">
+
            //relaciones
//añadimos
+
            $table->foreign('categoria_id')->references('id')->on('categorias')->onDelete('cascade')->onUpdate('cascade');
use DB;
+
            //category_id hace referencia a la tabla categories y el borrado y la actualización es en cascada.
 
+
        });
....
 
//obtenemos todos los usuarios
 
$users = DB::table('users')->get();
 
  
foreach ($users as $user)
 
{
 
    echo $user->name;
 
}
 
  
//Más ejemplos de consultas
+
</source>
$user = DB::table('users')->first();
 
  
$user = DB::table('users')->where('name', 'julio')->get();
+
Creamos los modelos
  
$users = DB::table('users')->where('edad', '>', 100)->get();
+
'''php artisan make:model Categoria'''
  
$users = DB::table('users')->where('estado', '<>', 'active')->get();
+
<source lang="php">
 +
//Modelo Categoria
 +
class Categoria extends Model
 +
{
 +
    protected $table = 'categorias';
 +
    //protected $primary_key = 'categoria_id';  //Por defecto id es la clave primaria, podemos definir un campo diferente con la propiedad primaryKey
 +
    //public $timestamps = true;  //especificamos si queremos crear created_at y updated_at en la base de datos
 +
    protected $fillable = ['nombre', 'masInfo'];
  
$users = DB::table('users')->where('name', 'like', 'J%')->get();
+
    public function articulos()
</source>
+
    {
 +
        return $this->hasMany('App\Articulo');
 +
    }
 +
}
  
===CONSULTAS SQL NATIVAS===
 
  
<source lang="php">
+
//Modelo Artículos
//seleccionar
 
$results = DB::select('select * from users where id = :id', ['id' => 1]);
 
  
//insertar en la Base users
+
class Articulo extends Model
DB::insert('insert into users (id, name) values (?, ?)', [1, 'Dayle']);
+
{
 +
    protected $table = 'articulos';
 +
    protected $fillable = ['titulo', 'descripcion'];
  
//actualizar
+
    public function categoria()
$affected = DB::update('update users set votes = 100 where name = ?', ['John']);
+
    {
 +
        return $this->belongsTo('App\Categoria');
 +
    }
 +
}
 +
</source>
  
//borrar
+
En el controlador
$deleted = DB::delete('delete from users');
 
  
//Ejecutando una instrucción general que no devuelve ningún valor
+
<source lang="php">
DB::statement('drop table users');
+
  public function insertar()
 +
    {
 +
        $categoria = Categoria::find(3);   //buscamos que ya tenemos almacenada o la creamos.
  
 +
        $articulo = new Articulo(['titulo' => 'Pedazo Artículo', 'descripcion' => 'toda la descripción']);  //creamos artículo.
 +
        $categoria->articulos()->save($articulo);  //guardamos dentro de categoria un artículo.
 +
     
 +
      //en caso que tengamos varios artículos
 +
      /* $categoria->articulos()->saveMany([
 +
            new Articulo(['titulo' => 'A new comment.', 'descripcion' => 'hola']),
 +
            new Articulo(['titulo' => 'Another comment.',  'descripcion' => 'hola']),
 +
        ]);*/
 +
       
 +
    }
 
</source>
 
</source>
http://documentacion-laravel.com/database.html#ejecutando-consultas-sql-nativas
+
http://documentacion-laravel.com/eloquent-relationships.html#insertando-y-actualizando-modelos-relacionados
  
===ELOQUENT===
 
  
findOrNew
+
'''PROBLEMA N+1 - LAZY LOADING '''
  
withCount
 
 
<source lang="php">
 
<source lang="php">
 +
//muestra el nombre de todas las categorias de todos los artículos. Una consulta para obtener todos los artículos en la tabla, después otra consulta para cada articulos para obtener quien es el autor
  
$escritor= App\Escritor::findOrFail(1);
+
$articulos = Articulo::all();
 
 
$escritor= App\Escritor::where('edad', '>', 100)->firstOrFail();
 
 
 
  
 +
foreach ($articulos as $articulo) {
 +
    dump($articulo->categoria->nombre);
 +
  }
 
</source>
 
</source>
  
 
+
'''SOLUCIÓN - EAGER LOADING'''
 +
//al usar la carga previa o carga impaciente (Eager Loading)  para reducir esta operación a solo 2 consultas
 
<source lang="php">
 
<source lang="php">
//insertar
+
$articulos = Articulo::with('categoria')->get();
        $escritor = Escritor::find(1);  //$escritor = App/Escritor::find(1);
 
        $escritor->nombre = 'Pepe';    //$request->name;
 
        $escritor->save();
 
//borrar
 
        $escritor= App\Escritor::find(1);
 
        $escritor->delete();
 
  
 +
foreach ($articulos as $articulo) {
 +
          echo $articulo->categoria->nombre ."</br>";
 +
        }
 
</source>
 
</source>
  
 +
https://styde.net/lazy-loading-vs-eager-loading/
  
 +
'''Borrado'''
  
 
<source lang="php">
 
<source lang="php">
 +
//borra la categoria 9 y todos los articulos relacionados (cascada)
 +
$Categoria = Categoria::find(9);
 +
$Categoria->delete();
  
//Toda la info de escritor
+
//borra artículo
$escritor = Escritor::find(1);
+
$articulo = Articulo::find(2);      
$escritor->articulo()->get();
+
$articulo->delete();
 +
</source>
  
  
//Muestra todos los articulos del escritor 1.
+
'''Consultas interesantes para 1xN'''
$escritor = Escritor::find(1);
 
foreach ($escritor->articulo as $articulo) {
 
  dump($articulo);
 
}
 
  
 +
<source lang="php">
  
//el artículo 1 devuelve quién es su escritor
+
//Métodos de relación
$articulos = Articulo::find(1);
+
//Toda la info de Categoria
dump($articulos->escritor->nombre);
+
$categoria = Categoria::find(3); //debe existir categoria y artículos
 +
return $categoria->articulos()->where('descripcion', "hola")->get(); //->whereDescripcion('hola')
  
  
//muestra el nombre de todos los escritores de todos los artículos. Una consulta para obtener todos los libros en la tabla, despues otra consulta para cada libro para obtener el autor
+
//Obtenemos del artículo el nombre de la Categoria relacionada
$articulos = Articulo::all();
+
$articulo = Articulo::findOrFail(2);
foreach ($articulos as $articulo) {
+
dump($articulo->categoria->nombre);
    echo $articulo->escritor->nombre;
 
}
 
  
 +
</source>
  
//al usar la carga previa o carga impaciente (Eager Loading)  para reducir esta operación a solo 2 consultas
 
$articulos = Articulo::with('escritor')->get();
 
      foreach ($articulos as $articulo) {
 
          echo $articulo->escritor->nombre ."</br>";
 
        }
 
</source>
 
  
 
https://desarrollowebtutorial.com/laravel-eloquent-orm-query-builder-consultas-sql/
 
https://desarrollowebtutorial.com/laravel-eloquent-orm-query-builder-consultas-sql/
  
 +
'''HAS'''
  
'''¿Cúal forma es mejor o más óptima? ¿SQL NATIVE o QUERY BUILDER o ELOQUENT?'''
+
Es como el WHERE, devuelve las categorias que tiene al menos 1 articulo
  
 +
<source lang="php">
 +
$categorias=Categoria::has('articulos')->get();
 +
</source>
  
https://www.laraveltip.com/que-es-mejor-eloquent-query-builder-o-sql/
 
 
=== PLUCK ===
 
  
En caso de obtener una colección y filtrar la parte que nos interesa.
 
  
 
<source lang="php">
 
<source lang="php">
$users = User::all(); // Devuelve una colección de usuarios, por ejemplo, ['name' => 'John', 'age' => 55],['name' => 'Melissa', 'age' => 18],['name' => 'Bob', 'age' => 43]
+
Categoria::where('descripcion','like','%#'.$etiqueta.'%')->get();
$usernames = $users->pluck('name'); // tenemos una colección de ['John', 'Melissa', 'Bob', 'Sara']
 
 
</source>
 
</source>
  
===ROLE===
 
Añadimos en la tabla de migracion users un nuevo atributo role de tipo enum y luego hacemos la migración
 
<source lang="php">
 
  
$table->enum('role',['user','admin']);
+
https://blog.coffeedevs.com/como-evitar-consultas-de-mas-al-utilizar-eloquent-orm/
  
//hacemos la migración
+
https://medium.com/@hemnys25/de-0-a-100-con-eloquent-de-laravel-parte-0-d5347c060ad7
php artisan migrate
 
</source>
 
  
Añadimos la autentificación de usuarios en este caso para Laravel 6.0
+
https://stackoverflow.com/questions/30231862/laravel-eloquent-has-with-wherehas-what-do-they-mean
  
<source lang="php">
 
  
composer require laravel/ui
 
  
php artisan ui bootstrap --auth
+
-----------------------------
  
</source>
+
===CONSULTAS EN MULTIPLES TABLAS ===
  
Creamos el MiddleWare y dentro introducimos el siguiente código app->http->Middleware
 
  
<source lang="php">
+
Ejemplo// Tablas: a, b, c, d, e, f
//php artisan make:middleware Admin
 
  
  public function handle($request, Closure $next)
+
Quiero traer los datos de todas las tablas relacionadas, los datos de a, b, c, d,e,f.
    {
 
        if (auth()->user()->role == "admin") {
 
  
            return $next($request);
+
    A está relacionado con B (1,n)
        }
+
    B con C (1,n)
        return redirect('home')->with('error', 'You dont have admin access');
+
    C con D (1,n)
     }
+
    D con E (1,n)
</source>
+
     E con F (1,n)
  
Luego registramos dentro del fichero Kernel.php el middleware en $routeMiddleware
+
'''Solución''':
 +
https://es.stackoverflow.com/questions/173727/consultas-en-m%C3%BAltiples-tablas-con-laravel-5-5
 +
 
 +
 
 +
-----------------------------
 +
 
 +
===RELACION DE MUCHOS A MUCHOS (NXM)===
 +
 
 +
Un post puede tener muchas Etiquetas y una etiqueta puede tener muchos Posts, por tanto habrá que crear una tabla auxiliar.
  
<source lang="php">
 
'admin' => \App\Http\Middleware\Admin::class,
 
</source>
 
  
Creamos la ruta nueva
+
'''php artisan make:migration create_etiquetas_table --create="etiquetas"'''
<source lang="php">
 
Route::get('admin/routes', 'HomeController@admin')->middleware('admin');
 
</source>
 
  
En el controlador de HomeController, son las dos rutas que hemos indicado en caso de ser user o admin
+
'''php artisan make:migration create_posts_table --create="posts"'''
<source lang="php">
 
  public function index()
 
    {
 
        return view('home');
 
    }
 
  
    public function admin()
+
'''php artisan make:migration create_etiqueta_post_table --create="etiqueta_post"'''
    {
 
      return view('admin');
 
    }
 
</source>
 
  
Creamos las dos vistas
 
  
home.blade
+
Dentro de la tabla de migraciones
 
<source lang="php">
 
<source lang="php">
@extends('layouts.app')
 
 
@section('content')
 
<div class="container">
 
    <div class="row justify-content-center">
 
        <div class="col-md-8">
 
            <div class="card">
 
                <div class="card-header">USER NORMAL</div>
 
 
                <div class="card-body">
 
                    @if(auth()->user()->is_admin == "admin")
 
                    <a href="{{url('admin/routes')}}">Admin</a>
 
                    @else
 
                    <div class="panel-heading">Normal User</div>
 
                    @endif
 
                </div>
 
            </div>
 
        </div>
 
    </div>
 
</div>
 
@endsection
 
</source>
 
  
 +
//ETIQUETAS
 +
Schema::create('etiquetas', function (Blueprint $table) {
 +
            $table->increments('id');
 +
 +
            $table->string('nombre',128);
 +
            $table->string('slug',128);
  
admin.blade.php
+
            $table->timestamps();
<source lang="php">
+
        });
@extends('layouts.app')
+
 
 +
//POSTS
 +
  Schema::create('posts', function (Blueprint $table) {
 +
            $table->increments('id');
 +
 
 +
            $table->string('nombre',128)->unique();
 +
            $table->string('slug',128);
 +
            $table->text('cuerpo');
 +
            $table->enum('status',['PUBLISHED','DRAFT'])->default('DRAFT');
 +
            $table->string('file', 128)->nullable();
 
   
 
   
@section('content')
+
            $table->timestamps();
<div class="container">
+
           
    <div class="row justify-content-center">
+
         });
         <div class="col-md-8">
+
 
            <div class="card">
+
//ETIQUETA_POST
                <div class="card-header">ADMINISTRADOR</div>
+
  Schema::create('etiqueta_post', function (Blueprint $table) {
   
+
            $table->increments('id');
                <div class="card-body">
 
                    @if(auth()->user()->is_admin == "admin")
 
                    <a href="{{url('admin/routes')}}">Admin</a>
 
                    @else
 
                    <div class="panel-heading">Normal User</div>
 
                    @endif
 
                </div>
 
            </div>
 
        </div>
 
    </div>
 
</div>
 
@endsection
 
</source>
 
//nota: habrá que cambiar la ruta del fichero loginController a la ruta /admin/routes para que haga el middleware
 
  
https://w3path.com/laravel-6-multiple-authentication-system-example-tutorial/
+
            $table->integer('post_id')->unsigned();
https://stackoverflow.com/questions/39555865/laravel-routegroup-for-admins
+
            $table->integer('etiqueta_id')->unsigned();
  
 +
            $table->timestamps();
  
Ejercicio:
+
            //relaciones
Modificar el registro de usuarios para que pueda añadirse el diferente tipo de role con un desplegable (user o Admin)
+
            $table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade')->onUpdate('cascade');
 +
            $table->foreign('etiqueta_id')->references('id')->on('etiquetas')->onDelete('cascade')->onUpdate('cascade');
 +
        });
 +
</source>
  
  
LISTAR RUTAS
+
Dentro de los modelos
php artisan route:list
+
<source lang="php">
 
+
//Modelo POST
BORRAR MODELO O MIGRACION
+
class Post extends Model
 
+
{
Borramos el fichero y luego ejecutamos
+
    protected $table = 'posts';
 +
    //protected $primary_key = 'categoria_id';
 +
    protected $fillable = ['nombre', 'cuerpo','status'];
 +
 
 +
    public function etiquetas()
 +
    {
 +
        return $this->belongsToMany('App\Etiqueta');
 +
    }
 +
}
  
composer dump-autoload
+
//Modelo ETIQUETA
  
<source lang="php">
+
class Etiqueta extends Model
 +
{
 +
    protected $table = 'etiquetas';
 +
    //protected $primary_key = 'categoria_id';
 +
    protected $fillable = ['nombre', 'slug'];
  
 +
    public function posts()
 +
    {
 +
        return $this->belongsToMany('App\Post');
 +
    }
 +
}
 
</source>
 
</source>
  
===RECUPERAR CONTRASEÑA POR CORREO===
+
//INSERTAR Tabla intermedia
https://stackoverflow.com/questions/33939393/failed-to-authenticate-on-smtp-server-error-using-gmail
+
<source lang="php">
 +
        public function insertarTablaIntermedia(){
 +
        $etiqueta=Etiqueta::find(1);
 +
        $post = Post::find(2);
 +
        $post->etiquetas()->attach($etiqueta);
 +
      }
 +
</source>
  
 +
//OBTENER DATOS DE LA otra TABLA RELACIONADA.
 
<source lang="php">
 
<source lang="php">
 
+
return Post::find(1)->etiquetas()->get();  //del Post(1) obtiene todas las etiquetas relacionadas
 +
return Post::find(1)->etiquetas()->where('nombre','futbol')->get();  //del Post(1) obtiene la etiqueta relacionada que tiene nombre = "futbol"
 
</source>
 
</source>
  
https://github.com/facade/ignition-code-editor
+
=== CREAR MODELOS ELOQUENT desde la BASE DATOS ===
  
===SUBIR FICHEROS===
+
Introducimos el comando de instalación del paquete
 
+
<source lang="script">
'''RUTAS'''
+
composer require reliese/laravel --dev
 +
</source>
  
 +
Registrar el provider en app/Providers/AppServiceProvider.php
 
<source lang="php">
 
<source lang="php">
Route::view('/subir','subir')->name('subir');   //va directamente a la vista, no hace falta poner controlador
+
public function register()
 +
{
 +
    if ($this->app->environment() == 'local') {
 +
        $this->app->register(\Reliese\Coders\CodersServiceProvider::class);
 +
    }
 +
}
 +
</source>
  
Route::post('/subidoFichero','PruebasController@subidoFicheroPost')->name('subidoFicheroPost');
+
Publicas el fichero de configuración:
 +
<source lang="script">
 +
php artisan vendor:publish --tag=reliese-models
 
</source>
 
</source>
  
'''VISTA Subir'''
+
Comandos:
<source lang="php">
+
<source lang="script">
@if ($message = Session::get('success'))
+
//Crea todos los MODELOS de las tablas de la BD
<strong>{{ $message }}</strong>  <!-- muestra el mensaje flash en caso de ser cierto-->
+
php artisan code:models
@endif
+
 
 +
//Crea un MODELO de una tabla
 +
php artisan code:models --table=users
 +
</source>
  
@if (count($errors) > 0)
 
<div>
 
    <strong>Uppss!</strong> Hay algunos problemas en la subida.<br><br>
 
    <ul>
 
        @foreach ($errors->all() as $error)
 
        <li>{{ $error }}</li>
 
        @endforeach
 
    </ul>
 
</div>
 
@endif
 
  
 +
https://cristianllanos.medium.com/eloquent-models-from-my-database-5d74c632e03c#.qg7cd4vri
  
<form action="{{ route('subidoFicheroPost')}}" method="post" enctype="multipart/form-data">
+
===SLUG (babosa)===
    @csrf
 
    <div class="form-group">
 
        <input type="file" name="fileToUpload" id="exampleInputFile" aria-describedby="fileHelp">
 
        <small id="fileHelp">El tamaño del fichero no debe ser superior a 2 MB.</small>
 
    </div>
 
    <button type="submit">Subir</button>
 
</form>
 
</div>
 
</div>
 
</div>
 
</div>
 
</source>
 
  
'''CONTROLADOR SubidaFicheroPost'''
+
Para mejorar el posicionamiento SEO de nuestra web en las url hay que evitar poner "/detalle/1" y darle un signficado a nuestras rutas "/detalle/julio-profesor"
<source lang="php">
 
  public function subidoFicheroPost(Request $request){
 
        $request->validate([
 
            'fileToUpload' => 'required|file|max:1024',
 
        ]);
 
  
      // $request->fileToUpload->store('logos');  //almacena el fichero dentro de storage->app->logos
+
Por tanto, podemos añadir a nuestra tabla de la base de datos un nuevo campo, por ello, podemos editar la tabla:
  
      $fileName = "fileName".time().'.'.request()->fileToUpload->getClientOriginalExtension();  //filename+ tiempo desde inicio UNIX + extensión fichero (.pdf...)
+
<source lang="php">
 +
//php artisan make:migration anadir_slug_tabla_tareas --table=tareas
 +
//creará una nueva migración donde añadiremos un nuevo campo, en este caso slug.
  
         $request->fileToUpload->storeAs('logos',$fileName); //almacena el fichero dentro de storage->app->logos
+
class AnadirSlugTablaTareas extends Migration
 +
{
 +
    public function up()
 +
    {
 +
         Schema::table('tareas', function (Blueprint $table) {
 +
            $table->string('slug')->unique;
 +
        });
 +
    }
 +
    public function down()
 +
    {
 +
        Schema::table('tareas', function (Blueprint $table) {
 +
        $table->dropColumn('slug');   //eliminar campo.
 +
        });
 +
    }
 +
}
  
        return back()->with('success','Tu imagen se ha subido satisfactoriamente');  //retorna a la misma página
 
  
    }
 
 
</source>
 
</source>
  
http://documentacion-laravel.com/filesystem.html#introduccion
+
Luego en el campo slug habrá que añadir "julio-profesor"
  
===DESCARGAR FICHEROS .ZIP===
 
 
<source lang="php">
 
<source lang="php">
composer require chumper/zipper
+
//CONTROLADOR
 
+
  public function mostrar()  //muestro todos los campos
//dentro de config/app.php
+
    {
//en providers
+
        $datos = Tarea::all();
Chumper\Zipper\ZipperServiceProvider::class,
+
        return view('datos', ['datos' => $datos]);
//en aliases
+
    }
'Zipper' => Chumper\Zipper\Zipper::class,
 
  
 +
    public function detalle($slug)  //Recibe el campo slug de la base de datos  y busca el resultado en la base de datos.
 +
    {
 +
        $tarea = Tarea::where('slug', $slug)->first();
 +
        return $tarea;
 +
    }
 
</source>
 
</source>
  
'''Controlador'''
 
 
<source lang="php">
 
<source lang="php">
use Zipper;
+
//VISTA
 
+
@forelse ($datos as $item)
class Controller extends BaseController
+
<li> {{$item->nombre}}  <a href="{{ route('detalle', $item->slug)}}" >detalles</a></li>
{
+
@empty
+
<li>NO HAY NADA </li>
 
+
@endforelse
    public function comprimirDescargar()
 
    {
 
        /*Añadimos la ruta donde se encuentran los archivos que queramos comprimir,
 
          en este ejemplo comprimimos todos los que se encuentran en la carpeta
 
          storage/app/public*/
 
        $files = glob(storage_path('app/public/*'));
 
       
 
        /* Le indicamos en que carpeta queremos que se genere el zip y los comprimimos*/
 
        Zipper::make(storage_path('app/public/ejemplo.zip'))->add($files)->close();
 
       
 
        /* Por último, si queremos descarlos, indicaremos la ruta del archiv, su nombre
 
        y lo descargaremos*/
 
        return response()->download(storage_path('app/public/ejemplo.zip'));
 
    }
 
 
 
 
 
}
 
 
 
 
</source>
 
</source>
  
'''RUTA'''
 
 
<source lang="php">
 
<source lang="php">
Route::get('/comprimir', 'Controller@comprimirDescargar')->name('comprimir');
+
//RUTAS
 +
Route::get('/mostrar', 'PruebaController@mostrar')->name('mostrar');
 +
Route::get('/detalle/{slug}', 'PruebaController@detalle')->name('detalle');
 
</source>
 
</source>
  
'''VISTA'''
+
===MANEJAR VALIDACIONES===
<source lang="php">
+
Para hacer las validaciones hay que evitar ponerlo en el controlador ya que es una mala práctica, por tanto el controlador solo debe tener la responsabilidad de tratar las solicitudes.
<a href="{{route('comprimir')}}">Comprimir y descargar</a>
 
</source>
 
  
===AJAX===
+
https://styde.net/como-trabajar-con-form-requests-en-laravel/
https://www.tutsmake.com/laravel-6-install-yajra-datatables-example-tutorial/
 
  
https://laraveles.com/implementacion-datatables-laravel-5-4/
+
https://www.laraveltip.com/que-son-como-y-por-que-utilizar-los-form-request-de-laravel/
  
 
<source lang="php">
 
<source lang="php">
Cambiar -> config/app.php
+
//Para mantener el código limpio y no tener que poner  app->http->request
 +
php artisan make:request CreateDatosRequest  // [Nombre-del-modelo-que-impacta]+[Acción]+Request
  
//instalamos paquete yajra
 
composer require yajra/laravel-datatables-oracle
 
  
añadir en alias
+
public function authorize()
'Datatables' => yajra\Datatables\Datatables::class,
+
    {
 +
        return true;  //cambiar a true
 +
    }
 +
 
 +
    public function rules()
 +
    {
 +
        return [
 +
        'nombre' => 'required',
 +
        'descripcion' => 'required',
 +
        ];
 +
    }
 +
 
 +
    public function messages()
 +
    {
 +
        return [
 +
        'nombre.required' => 'El :attribute es obligatorio campeón',
 +
        'descripcion.required' => 'El :attribute es obligatorio también',
 +
        ];
 +
    }
 +
 
 +
// en el controlador bastará con poner
  
añadir en providers
 
yajra\Datatables\DatatablesServiceProvider::class,
 
  
hacer público el archivo de configuración con el siguiente comando, el cual nos crea el archivo config/datatables.php
+
public function actualizar(CreateDatosRequest $request){
php artisan vendor:publish --tag=datatables
+
//quitamos la validación
 +
}
 +
 
 
</source>
 
</source>
  
 +
===TRY ... CATCH===
 +
<source lang="php">
 +
/*Las Rutas*/
 +
Route::get('/formularioBusqueda', 'ProductController@formulario')->name('formularioBusqueda'); 
 +
Route::post('/product/resultado', 'ProductController@resultado')->name('resultadoBusqueda');
 +
 +
</source>
  
 
<source lang="php">
 
<source lang="php">
//Migración
+
/*En la vista 'formularioBusqueda'*/
Schema::create('tareas', function (Blueprint $table) {
+
@if (session('error'))
            $table->increments('id');
+
<div>{{ session('error') }}</div>  <!--En caso de no encontrar el producto en la BBDD muestra error-->
            $table->string('nombre');
+
@endif
            $table->string('apellido');
+
            $table->string('estado');
+
<form action="{{ route('resultadoBusqueda') }}" method="POST">
            $table->timestamps();
+
@csrf
        });
+
 
 +
<input id="title name="title" type="text" value="{{ old('product') }}" placeholder="Product Title">
 +
 
 +
<input type="submit" value="Search">
 +
</form>
 +
 
 +
</source>
  
//Modelo
+
<source lang="php">
 +
/*En el controlador */
  
class Tarea extends Model
+
public function resultado(Request $request)
 
{
 
{
     protected $table = 'tareas';
+
     try {
     protected $primary_key = 'tareas_id';
+
        $product = Product::where('title',$request->get('title')); //busca el producto en la BBDD
 +
     } catch (ModelNotFoundException $exception) {
 +
        return back()->withError($exception->getMessage())->withInput();  //en caso de no encontrar en la BBDD captura la excepción y envia la info a la misma vista
 +
        //return $exception->getMessage();
 +
 
 +
    }
 +
    return view('resultadoBusqueda', compact('product'));   //en caso de encontrar el producto manda otra vista el resultado
 
}
 
}
 +
 
</source>
 
</source>
 +
https://www.tutsmake.com/laravel-try-catch/
  
 +
===TRADUCCIÓN===
  
<source lang="php">
+
Podemos hacerlo de dos formas:
// web
 
Route::get('/', 'PruebaController@index');
 
Route::get('/tareas', 'PruebaController@getTareas')->name('datatable.tareas');
 
</source>
 
  
 +
1) '''Manualmente:'''
  
<source lang="php">
+
*En el caso que queramos hacer validaciones en Castellano, deberemos ir a la carpeta Resources>Lang y crear una llamada ES. Luego para establecer el lang por defecto hay que cambiarlo en configuración APP>CONFIG>app.php y buscar la linea 'locate'=> 'es'.
//controlador
 
  
<?php
+
2)También podemos '''instalar complemento''':
  
namespace App\Http\Controllers;
+
*'''composer require laraveles/spanish'''
  
use Illuminate\Http\Request;
+
*'''php artisan vendor:publish --tag=lang'''
use Redirect,Response,DB,Config;
 
use Datatables;
 
use App\tarea;
 
 
 
class PruebaController extends Controller
 
{
 
    public function index()
 
    {
 
        return view('vista');
 
    }
 
 
    /**
 
    * @return mixed
 
    */
 
    public function getTareas()
 
    {
 
        $tareas = Tarea::select(['id','nombre','apellido','estado']);
 
 
        return Datatables::of($tareas)->make(true);
 
    }
 
}
 
  
</source>
+
https://github.com/Laraveles/spanish
  
 +
===AUTENTIFICACIÓN===
  
 
<source lang="php">
 
<source lang="php">
//vista
+
//Crear usuario en versiones anteriores a 6
  
 +
php artisan make:auth
  
<!DOCTYPE html>
+
//Laravel 6
+
 
<html lang="en">
+
composer require laravel/ui "^3.0"  //composer require laravel/ui "^1.0" --dev -vvv
<head>
+
 
<title>Laravel DataTable - Tuts Make</title>
+
php artisan ui vue --auth  //php artisan ui bootstrap --auth
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"> 
+
 
<link  href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css" rel="stylesheet">
+
//para visualizar el login y registro con css, habrá que instalar nodejs y usar:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js"></script> 
+
//npm install
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
+
//npm run dev
<script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js"></script>
+
 
</head>
+
 
<body>
+
 
+
</source>
<div class="container">
+
 
    <table id="task" class="table table-hover table-condensed">
+
1. Después si accedemos dentro '''routes->Web''' podemos ver que se ha creado '''Auth::routes()''';
        <thead>
+
 
        <tr>
+
2. Para cambiar la redirección después de Logearnos, tendremos que ir dentro '''app->http->Controller->Auth''' cambiamos las rutas de '''register''' y '''login''' cambiando ruta a '''/'''
            <th>Id</th>
+
 
            <th>Task</th>
+
3. Quitamos la ruta /home dentro de las rutas en web
            <th>Category</th>
+
 
            <th>State</th>
+
"para borrar la sesion podemos borrar el fichero dentro storage->framework->session como  prueba"
        </tr>
+
 
        </thead>
+
'''MUESTRA USUARIO BLADE'''
    </table>
+
<source lang="html">
</div>
+
@auth    <!--sirve para mostrar en caso de estar autentificado, estar logeado-->
+
{{auth()->user()->name}}
<script type="text/javascript">
+
@endauth
    $(document).ready(function() {
+
<!--tambien cambiar la ruta de middleware en caso de estar autentificado y volver hacer login peta y te manda a home por tanto cambiar a raiz.-->
        oTable = $('#task').DataTable({
+
 
            "processing": true,
+
@if(auth()) <!--si el usuario está autentificado-->
            "serverSide": true,
+
 
            "ajax": "{{ route('datatable.tareas') }}",
+
@endif
            "columns": [
+
</source>
                {data: 'id', name: 'id'},
+
 
                {data: 'nombre', name: 'nombre'},
+
 
                {data: 'apellido', name: 'apellido'},
+
'''SABER SI ESTÁ LOGEADO EN EL CONTROLADOR'''
                {data: 'estado', name: 'estado'}
+
 
            ]
+
<source lang="php">
        });
+
use Illuminate\Support\Facades\Auth;
    });
+
 
</script>
+
if(Auth::check()){  
</body>
+
return "estas logeado";
</html>
+
}else {  
 +
return "no estas logeado";
 +
}  
 +
 
 +
// Obtiene el objeto del Usuario Autenticado
 +
$user = Auth::user();
 +
$user->name;
 
</source>
 
</source>
  
===SLUG (babosa)===
+
'''SECURIZAR'''
  
Para mejorar el posicionamiento SEO de nuestra web en las url hay que evitar poner "/detalle/1" y darle un signficado a nuestras rutas "/detalle/julio-profesor"
+
También podemos indicarlo directamente en el constructor de un controlador
 
+
<source lang="php">
Por tanto, podemos añadir a nuestra tabla de la base de datos un nuevo campo, por ello, podemos editar la tabla:
+
public function __construct()
 +
{
 +
$this->middleware('auth');
 +
}
 +
</source>
  
 +
Otra forma es indicándolo en la ruta para protegerla
 
<source lang="php">
 
<source lang="php">
//php artisan make:migration anadir_slug_tabla_tareas --table=tareas
+
Route::get('/resultado', 'PruebasController@ejemplo')->middleware('auth);
//creará una nueva migración donde añadiremos un nuevo campo, en este caso slug.
+
</source>
  
class AnadirSlugTablaTareas extends Migration
+
'''LOGOUT'''
{
 
    public function up()
 
    {
 
        Schema::table('tareas', function (Blueprint $table) {
 
            $table->string('slug')->unique;
 
        });
 
    }
 
    public function down()
 
    {
 
        Schema::table('tareas', function (Blueprint $table) {
 
        $table->dropColumn('slug');    //eliminar campo.
 
        });
 
    }
 
}
 
 
 
 
 
</source>
 
 
 
Luego en el campo slug habrá que añadir "julio-profesor"
 
  
 
<source lang="php">
 
<source lang="php">
//CONTROLADOR
+
//usar directiva @guest- invitado. en caso de no estar logueado no muestra
  public function mostrar()  //muestro todos los campos
+
@guest
    {
+
<a href="{{route('login')}}">Login</a>
        $datos = Tarea::all();
+
@else    
        return view('datos', ['datos' => $datos]);
+
<a href="{{ route('logout') }}" onclick="event.preventDefault(); document.getElementById('logout-form').submit();"> Logout </a>
     }
+
 
 +
  <form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
 +
     {{ csrf_field() }}
 +
  </form>
 +
@endguest
  
    public function detalle($slug)  //Recibe el campo slug de la base de datos  y busca el resultado en la base de datos.
 
    {
 
        $tarea = Tarea::where('slug', $slug)->first();
 
        return $tarea;
 
    }
 
 
</source>
 
</source>
  
 +
'''DESHABILITAR REGISTRO'''
 +
 +
vamos a Web y modificamos ruta
 
<source lang="php">
 
<source lang="php">
//VISTA
+
Auth::routes(['register'=>false]);
@forelse ($datos as $item)
 
<li> {{$item->nombre}}  <a href="{{ route('detalle', $item->slug)}}" >detalles</a></li>
 
@empty
 
<li>NO HAY NADA </li>
 
@endforelse
 
 
</source>
 
</source>
 +
 +
''' BLOQUEAR USUARIO, INTENTOS FALLIDOS '''
 +
 +
En el caso que querramos bloquear al usuario por intentos de ingresos fallidos y penalizar el tiempo a la hora de volver autenficarte, bastará con añadir el controlador por defecto app->http->Controller->auth-> '''LoginController'''
  
 
<source lang="php">
 
<source lang="php">
//RUTAS
+
class LoginController extends Controller
Route::get('/mostrar', 'PruebaController@mostrar')->name('mostrar');
+
{
Route::get('/detalle/{slug}', 'PruebaController@detalle')->name('detalle');
+
 
 +
    use AuthenticatesUsers;
 +
 
 +
    public $maxAttempts = 2;  //número máximo de intentos
 +
    public $decayMinutes = 2; //tiempo que durará el bloqueo
 
</source>
 
</source>
  
===SEEDER (SEMILLAS)===
+
===MIDDLEWARE o FILTRO===
 
+
filtran las peticiones http, en nuestro caso que compruebe si el usuario está autentificado o no.
'''SEEDER normal'''
+
Son puertas que una peticion de usuario tiene que pasar antes de llegar al controlador que tiene la logica a la que el usuario intenta acceder.
  
 +
'''php artisan make:middleware DomingoMiddleware'''
  
  
 
<source lang="php">
 
<source lang="php">
php artisan make:seeder NombreSeeder
+
<?php
  
//dentro de database->seeds se genera la nueva semilla.
+
namespace App\Http\Middleware;
  
//luego en dataBaseSeeder activamos dentro de la clase $this->call(NombreSeeder::class);
+
use Closure;
  
//y en la clase NombreSeeder:
+
class DomingoMiddleware
 +
{
 +
    public function handle($request, Closure $next)
 +
    {
 +
        if(date('w')==='0'){
 +
            //echo "Es domingo!";
 +
          redirect()->route('home');
  
  for ($i=0; $i<10; $i++) {
+
        }else{
        DB::table('projects')->insert([
+
             echo "No es domingo";
             'title' => Str::random(10),
+
        }
            'description' => Str::random(10).'@gmail.com',
+
        return $next($request);   //"continua tu camino"
            'created_at' => date('Y-m-d'),
+
     }
            'updated_at' => date('Y-m-d')        ]);
+
}
     }
 
 
</source>
 
</source>
  
'''CLASE FAKER'''
+
Luego hay dos formas de registrar el MiddleWare
 +
 
 +
1) de Forma GLOBAL en app/Http/Kernel.php
  
 
<source lang="php">
 
<source lang="php">
//si queremos utilizar la clase FAKER
 
  
use Illuminate\Database\Seeder;
+
protected $middleware = [
use Illuminate\Support\Facades\DB;
+
        \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
use Faker\Factory as Faker;
+
        // otros middleware
 +
        // ...
 +
        \App\Http\Middleware\DomingoMiddleware::class,
 +
    ];
 +
</source>
 +
 
 +
2)Una ruta determinada o un controlador en app/Http/Kernel.php
  
class ContactosSeeder extends Seeder
+
<source lang="php">
{
+
protected $routeMiddleware = [
  public function run(){
+
        'auth' => \App\Http\Middleware\Authenticate::class,
    // puntero para recorrer Faker
+
        // otros middleware de rutas...
    $handle = Faker::create();
+
        'domingo' => \App\Http\Middleware\DomingoMiddleware::class,
 +
];
  
    for ($i=0; $i<10; $i++) {
+
//hay que añadir en la ruta web ->middleware('domingo');
      DB::table('contactos')->insert([
 
        'nombre' => $handle->firstName,
 
        'apellidos' => $handle->lastName,
 
        'created_at' => date('Y-m-d'),
 
        'updated_at' => date('Y-m-d')
 
      ]);
 
    }
 
  }
 
}
 
 
</source>
 
</source>
  
===CLASES PERSONALIZADAS===
 
  
//Crear nuestra Clase Personaliza Helper.php dentro de un directorio Helpers dentro de nuestra carpeta app de laravel quedando de la siguiente forma: app/Helpers/Helper.php con la siguientes lineas de codigo,
+
Ahora podemos probar que funciona nuestro middleware
 +
 
 
<source lang="php">
 
<source lang="php">
 +
//pruebas en route web
 +
 +
Route::get('/test', ['middleware' => 'domingo', function(){
 +
    return 'Probando ruta con middleware';
 +
}])
 +
 +
Route::get('/test1','MoviesController@insertar')->name('insertar')->middleware('domingo');
 +
 +
//segunda prueba en route web
 +
 +
Route::group(['middleware' => 'domingo'], function(){
 +
    Route::get('/probando/ruta', function(){
 +
        //código a ejecutar cuando se produzca esa ruta y el verbo
 +
        return 'get';
 +
    });
  
# Ubicacion app\Helpers\Helper.php
+
    Route::post('/probando/ruta', function(){
 +
        //código a ejecutar cuando se produzca esa ruta y el verbo POST
 +
        return 'post';
 +
    });
 +
});
  
namespace App\Helpers;
+
//también se puede llamar desde dentro de un controlador y afectará a todas las acciones de dentro.
  
class Helper
+
class PrimerController extends Controller
 
{
 
{
     public static function strUp(string $string)
+
     public function __construct(){
    {
+
         $this->middleware('domingo');
         return strtoupper($string);
 
 
     }
 
     }
 
}
 
}
 
</source>
 
</source>
  
Crear Alias en nuestra aplicacion
 
  
 +
https://programacionymas.com/blog/restringir-acceso-solo-administradores-laravel-usando-middlewares
 +
 +
https://desarrolloweb.com/articulos/laravel-middleware.html
 +
 +
===ROLE===
 +
Añadimos en la tabla de migracion users un nuevo atributo role de tipo enum y luego hacemos la migración
 
<source lang="php">
 
<source lang="php">
# Ubicacion: config/app.php
 
  
    'aliases' => [
+
$table->enum('role',['user','admin'])->default('user');
    ...
 
        'Helper' => App\Helpers\Helper::class,
 
    ...
 
</source>
 
  
Usarlo en nuestras plantillas Blade
+
//hacemos la migración
 +
php artisan migrate
 +
</source>
 +
 
 +
Añadimos la autentificación de usuarios en este caso para Laravel 6.0
  
 
<source lang="php">
 
<source lang="php">
{{ Helper::strUp('mostrar este texto en mayúsculas!') }}
 
  
 +
composer require laravel/ui
 +
 +
php artisan ui bootstrap --auth
  
 
</source>
 
</source>
  
Usarlos en nuestro controlador
+
Creamos el MiddleWare y dentro introducimos el siguiente código app->http->Middleware
 +
 
 
<source lang="php">
 
<source lang="php">
namespace App\Http\Controllers;
+
//php artisan make:middleware Admin
  
use Helper;
+
  public function handle($request, Closure $next)
//use App\Helpers;
+
    {
 +
        if (auth()->user()->role == "admin") {
  
class TuController extends Controller
+
            return $next($request);
{
+
        }
 
+
         return redirect('home')->with('error', 'You dont have admin access');
    public function metodo()
 
    {
 
         Helper::strUp('mostrar este texto en mayúsculas!');
 
 
     }
 
     }
}
 
 
</source>
 
</source>
  
=== GENERAR PDF ===
+
Luego registramos dentro del fichero Kernel.php el middleware en $routeMiddleware
 +
 
 +
<source lang="php">
 +
'admin' => \App\Http\Middleware\Admin::class,
 +
</source>
 +
 
 +
Creamos la ruta nueva
 +
<source lang="php">
 +
Route::get('admin/routes', 'HomeController@admin')->middleware('admin');
 +
</source>
  
Instalamos libreria
+
En el controlador de HomeController, son las dos rutas que hemos indicado en caso de ser user o admin
 +
<source lang="php">
 +
  public function index()
 +
    {
 +
        return view('home');
 +
    }
  
composer require barryvdh/laravel-dompdf
+
    public function admin()
 +
    {
 +
      return view('admin');
 +
    }
 +
</source>
  
añadimos la siguiente ruta en config/app.php en el array 'provider'
+
Creamos las dos vistas
  
 +
home.blade
 
<source lang="php">
 
<source lang="php">
Barryvdh\DomPDF\ServiceProvider::class,
+
@extends('layouts.app')
 +
 +
@section('content')
 +
<div class="container">
 +
    <div class="row justify-content-center">
 +
        <div class="col-md-8">
 +
            <div class="card">
 +
                <div class="card-header">USER NORMAL</div>
 +
 +
                <div class="card-body">
 +
                    @if(auth()->user()->role== "admin")
 +
                    <a href="{{url('admin/routes')}}">Admin</a>
 +
                    @else
 +
                    <div class="panel-heading">Normal User</div>
 +
                    @endif
 +
                </div>
 +
            </div>
 +
        </div>
 +
    </div>
 +
</div>
 +
@endsection
 +
</source>
 +
 
 +
 
 +
admin.blade.php
 +
<source lang="php">
 +
@extends('layouts.app')
 +
 +
@section('content')
 +
<div class="container">
 +
    <div class="row justify-content-center">
 +
        <div class="col-md-8">
 +
            <div class="card">
 +
                <div class="card-header">ADMINISTRADOR</div>
 +
 +
                <div class="card-body">
 +
                    @if(auth()->user()->role== "admin")
 +
                    <a href="{{url('admin/routes')}}">Admin</a>
 +
                    @else
 +
                    <div class="panel-heading">Normal User</div>
 +
                    @endif
 +
                </div>
 +
            </div>
 +
        </div>
 +
    </div>
 +
</div>
 +
@endsection
 +
</source>
 +
//nota: habrá que cambiar la ruta del fichero loginController a la ruta /admin/routes para que haga el middleware
 +
 
 +
https://w3path.com/laravel-6-multiple-authentication-system-example-tutorial/
 +
https://stackoverflow.com/questions/39555865/laravel-routegroup-for-admins
 +
 
 +
 
 +
Ejercicio:
 +
Modificar el registro de usuarios para que pueda añadirse el diferente tipo de role con un desplegable (user o Admin)
 +
 
 +
composer dump-autoload
 +
 
 +
===RECUPERAR CONTRASEÑA POR CORREO===
 +
https://stackoverflow.com/questions/33939393/failed-to-authenticate-on-smtp-server-error-using-gmail
 +
 
 +
<source lang="php">
 +
 
 +
</source>
 +
 
 +
https://github.com/facade/ignition-code-editor
 +
 
 +
===SUBIR FICHEROS===
 +
 
 +
'''RUTAS'''
 +
 
 +
<source lang="php">
 +
Route::view('/subir','subir')->name('subir');  //va directamente a la vista, no hace falta poner controlador
 +
 
 +
Route::post('/subidoFichero','PruebasController@subidoFicheroPost')->name('subidoFicheroPost');
 +
</source>
 +
 
 +
'''VISTA Subir'''
 +
<source lang="php">
 +
@if ($message = Session::get('success'))
 +
<strong>{{ $message }}</strong>  <!-- muestra el mensaje flash en caso de ser cierto-->
 +
@endif
 +
 
 +
@if (count($errors) > 0)
 +
<div>
 +
    <strong>Uppss!</strong> Hay algunos problemas en la subida.<br><br>
 +
    <ul>
 +
        @foreach ($errors->all() as $error)
 +
        <li>{{ $error }}</li>
 +
        @endforeach
 +
    </ul>
 +
</div>
 +
@endif
 +
 
 +
 
 +
<form action="{{ route('subidoFicheroPost')}}" method="post" enctype="multipart/form-data">
 +
    @csrf
 +
    <div class="form-group">
 +
        <input type="file" name="fileToUpload" id="exampleInputFile" aria-describedby="fileHelp">
 +
        <small id="fileHelp">El tamaño del fichero no debe ser superior a 2 MB.</small>
 +
    </div>
 +
    <button type="submit">Subir</button>
 +
</form>
 +
</div>
 +
</div>
 +
</div>
 +
</div>
 +
</source>
 +
 
 +
'''CONTROLADOR SubidaFicheroPost'''
 +
<source lang="php">
 +
  public function subidoFicheroPost(Request $request){
 +
        $request->validate([
 +
            'fileToUpload' => 'required|file|max:1024',
 +
        ]);
 +
 
 +
      // $request->fileToUpload->store('logos');  //almacena el fichero dentro de storage->app->logos
 +
 
 +
      $fileName = "fileName".time().'.'.request()->fileToUpload->getClientOriginalExtension();  //filename+ tiempo desde inicio UNIX + extensión fichero (.pdf...)
 +
 
 +
        $request->fileToUpload->storeAs('public/logos',$fileName); //almacena el fichero dentro de storage->app->public->logos
 +
 
 +
        return back()->with('success','Tu imagen se ha subido satisfactoriamente');  //retorna a la misma página
 +
 
 +
      //public_path() , storage_path()
 +
 
 +
    }
 +
 
 +
 
 +
</source>
 +
 
 +
Cuando subimos imágenes y queremos mostrarla en la vista, por defecto se almacenan dentro de storage->app->public->logos, el problema es que esa carpeta no es pública para todo el mundo, por tanto, si ejecutamos el comando '''php artisan storage:link''' creará un enlace simbólico creando una nueva carpeta dentro public->storage->logos
 +
 
 +
 
 +
<source lang="php">
 +
//vista  (las imágenes deben estar en la carpeta app/storage/public/logos)
 +
<img src="{{ url('storage/logos/'.$imagen) }}">
 +
<img src="{{ asset('storage/logos') }}/{{$b->imagen}}">
 +
</source>
 +
 
 +
 
 +
http://documentacion-laravel.com/filesystem.html#introduccion
 +
http://documentacion-laravel.com/filesystem.html#configuracion
 +
 
 +
=== DRAG & DROP ===
 +
 
 +
Creamos la vista y luego en el controlador tenemos que guardar al igual que subimos un fichero
 +
    <source lang="script">
 +
 
 +
/*En la VISTA*/
 +
//librerias
 +
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
 +
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
 +
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
 +
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
 +
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.5.0/min/dropzone.min.css">
 +
    <script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.5.0/dropzone.js"></script>
 +
  </head>
 +
 
 +
  <body>
 +
    <div class="container">
 +
        <h2>Laravel 6 Subir multiples imágenes</h2><br/>
 +
     
 +
        <form method="post" action="{{ route('almacenar') }}" enctype="multipart/form-data" class="dropzone" id="dropzone">
 +
        @csrf
 +
        </form>
 +
 
 +
    </div>
 +
 
 +
    <script type="text/javascript">
 +
 
 +
        Dropzone.options.dropzone =
 +
        {
 +
            maxFilesize: 10,
 +
            acceptedFiles: ".jpeg,.jpg,.png,.gif",
 +
            addRemoveLinks: false,
 +
            timeout: 60000,
 +
            success: function (file, response) {
 +
                console.log(response);
 +
            },
 +
            error: function (file, response) {
 +
                return false;
 +
            }
 +
        };
 +
 
 +
    </script>
 +
  </body>
 +
 
 +
</source>
 +
 
 +
<source lang="script">
 +
/*En el CONTROLADOR*/
 +
 
 +
//otra forma de subir fichero en la carpeta Public
 +
public function subidoFicheroPost(Request $request){
 +
 
 +
        $image = $request->file('file');
 +
        $avatarName = $image->getClientOriginalName();
 +
        $image->move(public_path('images'),$avatarName);  //guarda en la ruta ->public->images
 +
        //$image->move(storage_path('\app\public\images'),$avatarName);  //almacena en la ruta storage->app->public->images
 +
 
 +
}
 +
 
 +
 
 +
</source>
 +
 
 +
https://appdividend.com/2018/05/31/laravel-dropzone-image-upload-tutorial-with-example/
 +
 
 +
===DESCARGAR FICHEROS .ZIP===
 +
<source lang="php">
 +
composer require chumper/zipper
 +
 
 +
//dentro de config/app.php
 +
//en providers
 +
Chumper\Zipper\ZipperServiceProvider::class,
 +
//en aliases
 +
'Zipper' => Chumper\Zipper\Zipper::class,
 +
 
 +
</source>
 +
 
 +
'''Controlador'''
 +
<source lang="php">
 +
use Zipper;
 +
 
 +
class Controller extends BaseController
 +
{
 +
 +
 
 +
    public function comprimirDescargar()
 +
    {
 +
        /*Añadimos la ruta donde se encuentran los archivos que queramos comprimir,
 +
          en este ejemplo comprimimos todos los que se encuentran en la carpeta
 +
          storage/app/public*/
 +
        $files = glob(storage_path('app/public/*'));
 +
       
 +
        /* Le indicamos en que carpeta queremos que se genere el zip y los comprimimos*/
 +
        Zipper::make(storage_path('app/public/ejemplo.zip'))->add($files)->close();
 +
       
 +
        /* Por último, si queremos descarlos, indicaremos la ruta del archiv, su nombre
 +
        y lo descargaremos*/
 +
        return response()->download(storage_path('app/public/ejemplo.zip'));
 +
    }
 +
 
 +
 
 +
}
 +
 
 +
</source>
 +
 
 +
'''RUTA'''
 +
<source lang="php">
 +
Route::get('/comprimir', 'Controller@comprimirDescargar')->name('comprimir');
 +
</source>
 +
 
 +
'''VISTA'''
 +
<source lang="php">
 +
<a href="{{route('comprimir')}}">Comprimir y descargar</a>
 +
</source>
 +
 
 +
===AJAX===
 +
https://www.tutsmake.com/laravel-6-install-yajra-datatables-example-tutorial/
 +
 
 +
https://laraveles.com/implementacion-datatables-laravel-5-4/
 +
 
 +
<source lang="php">
 +
 
 +
//instalamos paquete yajra
 +
composer require yajra/laravel-datatables-oracle
 +
 
 +
Cambiar -> config/app.php
 +
 
 +
añadir en alias
 +
'Datatables' => yajra\Datatables\Datatables::class,
 +
 
 +
añadir en providers
 +
yajra\Datatables\DatatablesServiceProvider::class,
 +
 
 +
hacer público el archivo de configuración con el siguiente comando, el cual nos crea el archivo config/datatables.php
 +
php artisan vendor:publish --tag=datatables
 +
</source>
 +
 
 +
 
 +
<source lang="php">
 +
//Migración
 +
Schema::create('tareas', function (Blueprint $table) {
 +
            $table->increments('id');
 +
            $table->string('nombre');
 +
            $table->string('apellido');
 +
            $table->string('estado');
 +
            $table->timestamps();
 +
        });
 +
 
 +
//Modelo
 +
 
 +
class Tarea extends Model
 +
{
 +
    protected $table = 'tareas';
 +
    protected $primary_key = 'tareas_id';
 +
}
 +
</source>
 +
 
 +
 
 +
<source lang="php">
 +
// web
 +
Route::get('/', 'PruebaController@index');
 +
Route::get('/tareas', 'PruebaController@getTareas')->name('datatable.tareas');
 +
</source>
 +
 
 +
 
 +
<source lang="php">
 +
//controlador
 +
 
 +
<?php
 +
 
 +
namespace App\Http\Controllers;
 +
 
 +
use Illuminate\Http\Request;
 +
use Redirect,Response,DB,Config;
 +
use Datatables;
 +
use App\tarea;
 +
 
 +
class PruebaController extends Controller
 +
{
 +
    public function index()
 +
    {
 +
        return view('vista');
 +
    }
 +
 +
    /**
 +
    * @return mixed
 +
    */
 +
    public function getTareas()
 +
    {
 +
        $tareas = Tarea::select(['id','nombre','apellido','estado']);
 +
 +
        return Datatables::of($tareas)->make(true);
 +
    }
 +
}
 +
 
 +
</source>
 +
 
 +
 
 +
<source lang="php">
 +
//vista
 +
 
 +
 
 +
<!DOCTYPE html>
 +
 +
<html lang="en">
 +
<head>
 +
<title>Laravel DataTable - Tuts Make</title>
 +
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"> 
 +
<link  href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css" rel="stylesheet">
 +
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js"></script> 
 +
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
 +
<script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js"></script>
 +
</head>
 +
<body>
 +
 +
<div class="container">
 +
    <table id="task" class="table table-hover table-condensed">
 +
        <thead>
 +
        <tr>
 +
            <th>Id</th>
 +
            <th>Task</th>
 +
            <th>Category</th>
 +
            <th>State</th>
 +
        </tr>
 +
        </thead>
 +
    </table>
 +
</div>
 +
 +
<script type="text/javascript">
 +
    $(document).ready(function() {
 +
        oTable = $('#task').DataTable({
 +
            "processing": true,
 +
            "serverSide": true,
 +
            "ajax": "{{ route('datatable.tareas') }}",
 +
            "columns": [
 +
                {data: 'id', name: 'id'},
 +
                {data: 'nombre', name: 'nombre'},
 +
                {data: 'apellido', name: 'apellido'},
 +
                {data: 'estado', name: 'estado'}
 +
            ]
 +
        });
 +
    });
 +
</script>
 +
</body>
 +
</html>
 +
</source>
 +
 
 +
===CLASES PERSONALIZADAS===
 +
 
 +
//Crear nuestra Clase Personaliza Helper.php dentro de un directorio Helpers dentro de nuestra carpeta app de laravel quedando de la siguiente forma: app/Helpers/Helper.php con la siguientes lineas de codigo,
 +
<source lang="php">
 +
 
 +
# Ubicacion app\Helpers\Helper.php
 +
 
 +
namespace App\Helpers;
 +
 
 +
class Helper
 +
{
 +
    public static function strUp(string $string)
 +
    {
 +
        return strtoupper($string);
 +
    }
 +
}
 +
</source>
 +
 
 +
Crear Alias en nuestra aplicacion
 +
 
 +
<source lang="php">
 +
# Ubicacion: config/app.php
 +
 
 +
    'aliases' => [
 +
    ...
 +
        'Helper' => App\Helpers\Helper::class,
 +
    ...
 +
</source>
 +
 
 +
Usarlo en nuestras plantillas Blade
 +
 
 +
<source lang="php">
 +
{{ Helper::strUp('mostrar este texto en mayúsculas!') }}
 +
 
 +
 
 +
</source>
 +
 
 +
Usarlos en nuestro controlador
 +
<source lang="php">
 +
namespace App\Http\Controllers;
 +
 
 +
//use Helper;
 +
use App\Helpers\Helper;
 +
//use App\Helpers;
 +
 
 +
class TuController extends Controller
 +
{
 +
 
 +
    public function metodo()
 +
    {
 +
        Helper::strUp('mostrar este texto en mayúsculas!');
 +
    }
 +
}
 +
</source>
 +
 
 +
===TRAITS===
 +
 
 +
<source lang="php">
 +
 
 +
/*En el CONTROLADOR*/
 +
 
 +
use App\Http\Traits\Mayusculas;
 +
.....
 +
 
 +
class PeliculasController extends Controller
 +
{
 +
 
 +
  use Mayusculas;
 +
 
 +
  public function ejemplo()
 +
  {
 +
    echo Mayusculas::convertir("Julio Noguera");
 +
  }
 +
 
 +
}
 +
</source>
 +
 
 +
Nos creamos un fichero en app->Http->Traits->Mayusculas.php
 +
<source lang="php">
 +
<?php
 +
 
 +
namespace App\Http\Traits;
 +
 
 +
trait Mayusculas
 +
{
 +
    public static function convertir(string $string)
 +
    {
 +
 
 +
        $mayusculas=strtoupper($string);
 +
 
 +
        return $mayusculas;
 +
    }
 +
}
 +
 
 +
</source>
 +
 
 +
https://diego.com.es/traits-en-php
 +
 
 +
=== GENERAR PDF ===
 +
 
 +
Instalamos libreria
 +
 
 +
composer require barryvdh/laravel-dompdf
 +
 
 +
añadimos la siguiente ruta en config/app.php en el array 'provider'
 +
 
 +
<source lang="php">
 +
Barryvdh\DomPDF\ServiceProvider::class,
 
</source>
 
</source>
 
luego añadimos la siguiente ruta en config/app.php en el array 'aliases'
 
luego añadimos la siguiente ruta en config/app.php en el array 'aliases'
  
<source lang="php">
+
<source lang="php">
'PDF' => Barryvdh\DomPDF\Facade::class,
+
'PDF' => Barryvdh\DomPDF\Facade::class,
</source>
+
</source>
crearmos ruta en Web
+
crearmos ruta en Web
 
+
 
<source lang="php">
+
<source lang="php">
Route::get('/imprimir', 'RelacionController@imprimir')->name('imprimir');
+
Route::get('/imprimir', 'RelacionController@imprimir')->name('imprimir');
</source>
+
</source>
 
+
 
y una vista llamada 'imprimir.blade.php' con código en html
+
y una vista llamada 'imprimir.blade.php' con código en html
<source lang="html">
+
<source lang="html">
<body>
+
<body>
         <h1>Página de prueba</h1>
+
         <h1>Página de prueba</h1>
 
+
 
</body>
+
</body>
</source>
+
</source>
 
+
 
 
+
 
<source lang="php">
+
<source lang="php">
use PDF;
+
use PDF;
......
+
......
 
+
 
public function imprimir(){
+
public function imprimir(){
     $pdf = PDF::loadView('imprimir');
+
     $pdf = PDF::loadView('imprimir');
     return $pdf->download('ejemplo.pdf');
+
     return $pdf->download('ejemplo.pdf');
}
+
}
 +
</source>
 +
 
 +
https://www.nigmacode.com/laravel/Generar-pdf-Dompdf-Laravel
 +
 
 +
=== DEBUGBAR ===
 +
<source lang="php">
 +
composer require barryvdh/laravel-debugbar --dev
 +
</source>
 +
Dentro de config->App añadimos en '''provider'''
 +
 
 +
Barryvdh\Debugbar\ServiceProvider::class,
 +
 
 +
En '''aliases'''
 +
 
 +
'Debugbar' => Barryvdh\Debugbar\Facade::class,
 +
 
 +
===EJERCICIO 1===
 +
 
 +
1. Se desea crear una filmografía de películas, por ello, debemos crear una página web que liste todas las películas que tiene almacenada localmente (array, fichero), también cabe la posiblidad de tener un formulario donde se pueda introducir el nombre de la película, año, director, descripción y una imagen (url) y se almacene.
 +
 
 +
Habrá que crear las rutas (crear, buscar/{id}, listar) y las correspondientes vistas(herencia). Lo ideal es que se muestre la imagen de película y clicando sobre ella muestre el resto de la información.
 +
 
 +
:[[array_ejemplo]]
 +
 
 +
 
 +
 
 +
https://medium.com/techcompose/create-rest-api-in-laravel-with-authentication-using-passport-133a1678a876
 +
 
 +
https://medium.com/@bapunawarsaddam/rest-api-with-laravel-5-8-using-laravel-passport-53b5953798bb
 +
 
 +
https://medium.com/@devfelipe.mansilla/usando-graphql-con-laravel-446f0de02424
 +
 
 +
https://github.com/chiraggude/awesome-laravel
 +
 
 +
Intersante
 +
 
 +
Lazy Size
 +
 
 +
===PRODUCCIÓN===
 +
 
 +
Vamos a subir un proyecto de Laravel en un servidor hosting concretamente fortrabbit, lo malo que tiene dos días de duración. Hay que tener instalado el git y el ssh
 +
 
 +
<source lang="script">
 +
 
 +
php artisan cache:clear //Limpiar el caché de la Aplicación
 +
 
 +
php artisan route:clear //Limpiar las rutas de la Aplicación.
 +
 
 +
php artisan config:clear //Limpiar las configuraciones de la Aplicación
 +
 
 +
php artisan view:clear  //Limpiar las vistas de la Aplicación
 +
 
 +
</source>
 +
 
 +
 
 +
En nuestro fichero archivo .env de nuestra aplicación, cambiaremos las valores de:
 +
 
 +
<source lang="script">
 +
APP_ENV = production
 +
APP_DEBUG = false
 +
</source>
 +
 
 +
 
 +
Después de eso nos disponemos a subir el proyecto
 +
 
 +
<source lang="script">
 +
cd proyecto
 +
 
 +
git init
 +
 
 +
git add -A
 +
 
 +
git commit -m 'Initial'
 +
 
 +
git remote add fortrabbit laravel-exey.cej3ggri1ze7ej4q@deploy.eu2.frbit.com:laravel-exey.git  //hay que buscar en la configuración de la página y cambiar el comando git
 +
 
 +
//git config --global user.email "correo@correo.com"
 +
 
 +
git push -u fortrabbit master
 +
 
 +
git push
 +
</source>
 +
 
 +
Ahora vamos a exportar la base de datos
 +
 
 +
<source lang="script">
 +
ssh laravel-exey.cej3ggri1ze7ej4q@deploy.eu2.frbit.com  //hay que buscar en la configuración de la página y cambiar el comando con el mysql
 +
 
 +
php artisan migrate --force
 
</source>
 
</source>
 
https://www.nigmacode.com/laravel/Generar-pdf-Dompdf-Laravel
 

Revisió de 10:09, 22 abr 2021

ESTRUCTURA DIRECTORIOS

COMANDOS INDISPENSABLES LARAVEL

/*CREAR PROYECTOS*/

composer create-project --prefer-dist laravel/laravel proyecto

composer create-project --prefer-dist laravel/laravel proyecto "6.0"  //especificamos la versión

composer require facade/ignition   //instalar nueva página errores


/*CONTROLADORES*/

php artisan make:controller PeliculasController //añadir CONTROLADOR vacio

php artisan make:model Trainer -m  //crea el modelo Trainer y además hace la migracion

php artisan make:model Task -mcr  //modelo migracion controlador

/*MODELO*/

php artisan make:model Categoria 

/*MIGRACIONES*/

php artisan make:migration create_categorias_table --create="categorias"  //creamos la migración (la tabla en la base de datos es en plural y el modelo en singular)

php artisan make:migration anadir_telefono_tabla_cate --table="categorias" //editar tabla (podemos crear otra migración con otro atributo)

php artisan migrate:rollback  //deshacer la última migración ejecutada y registrada en la base de datos.

php artisan migrate:fresh  //borra la base de datos y la carga de nuevo.

/*RUTAS*/

php artisan routes //genera todas las rutas get,put,post de un crud... Route::resource()  


php artisan route:list -v    ////Para listar las rutas, en terminal

Estructura Laravel 6

Estructura Laravel

RUTAS BÁSICAS

Dentro de Routers -> Web

Route::get('mundo', function () {
    return 'Hello World';
});

Le pasamos a la ruta un identificador que tendrá un valor por defecto y esa ruta tendrá un nombre

//dentro de la misma vista, asignamos valor por defecto
Route::get('/show/{id?}',function($id="122"){

    return $id;
    
    })->name('show');

Otra forma de ruta y utilizando un pattern númerico (sólo pueden introducir números)

Route::get('/par-o-impar-{numero}',function($numero){    // no hace falta usar '/'

return $numero;

//return redirect()->to('/show/3');  -> te redirije a la ruta que le indicas 
//return redirect()->route('show')  -> te redirije a la ruta que tiene el nombre asignado en el name.
//return redirect()->route('show',['id' => '222'])  -> en caso de pasarle algun parámetro
} )->where(['number' => '[\d]+']);    // de esta forma añadimos una expresion regular para que solo puedan introducir numeros


Restricciones con Expresiones Regulares

Route::get('user/{name}', function ($name) {
    //
})->where('name', '[A-Za-z]+');   //nomes poden passar lletres miníscules o Majúscules como mínim una volta 

Route::get('user/{id}', function ($id) {
    //
})->where('id', '[0-9]+');   //com a mínim, a soles podem passar com a mínim un nombre.

Route::get('user/{id}/{name}', function ($id, $name) {
    //
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);   //le pasamos un array en caso de más de un elemento.


Ruta en función del ROLE

// en el navegador puedes poner /admin/modificar-usuario  o  /admin/insertar-usuario
Route::group(['prefix'=>'admin'],function(){ 
    
    Route::get('modificar-usuario',function(){

    return "modifica usuario";

    });


    Route::get('insertar-usuario',function(){

    return "insertar usuario";

    });

});


Ruta que nos lleva directamente a una vista e incluso pasarle un argumento.

Route::view('/welcome', 'welcome');  //en el caso que sólo queramos enviar a una vista sin pasar por el controlador

Route::view('/welcome', 'welcome', ['name' => 'Taylor']);


Especificamos que podemos usar GET y POST para una ruta

//verbos HTTP múltiples
Route::match(['get', 'post'], '/', function () {
    //
});

//verbos HTTP cualquiera
Route::any('/', function () {
    //
});

Creamos un controlador vacio, App->http->Controller->

php artisan make:controller MoviesController --plain

//en route
Route::get('/ejemplo', 'PeliculasController@index');

//en controlador
public function index(){

echo "hola Julio";

}

https://github.com/dbushell/Nestable

https://medium.com/@cvallejo/los-mejores-30-tips-de-laravel-d0c96a1c900e

https://www.laraveltip.com/tips-por-temas/laravel/

https://pablomonteserin.com/curso/laravel/

VISTA

Podemos aprovechar herencia en las vistas, por ello, vamos a crear.

También podemos crear una carpeta que contiene vistas "menú" y dentro las páginas, para acceder a ellos, habría que poner "menu.pagina"

Vista Padre LAYOUT.blade.php

<!DOCTYPE html>
<head>
    <title>
        @yield('titulo')
    </title>
</head>
<body>

<ul>
  <li><a href="#home">Home</a></li>
  <li><a href="#news">News</a></li>
  <li><a href="#contact">Contact</a></li>
  <li><a href="#about">About</a></li>
</ul>

@yield('contenido')

</body>
</html>

Vista Layout Hija hija.blade.php

@extends('layout')

@section('titulo','Página Heredada')

@section('contenido')
    <h1>Página Hija</h1>
@endsection


SESIONES

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

/*diferentes formas de crear variables de sesión en el CONTROLADOR*/

$request->session()->put(['Julio'=>'Administrador']); //crea variable sesión con clave Julio y valor Administrador

session(['nombre'=>'Julio']); //otra forma de crear variables sesión

$nombre= session('nombre')  

$request->session()->forget('Juan'); //Borra Juan

$request->session()->flush(); //borra todo

return $request->session()->all();  //muestra todas las variables de sesión 
dd(session()->all()) //muestra todas las variables de sesión

/*mostrar variables sesión en blade VISTA*/

{{session('julio')}}

MENSAJES FLASH

//cuando en una página queremos enviar un mensaje flahs podemos poner

return back()->with('status','hemos recibido el mensaje'); //guardamos un mensaje flash

//luego en la misma pagina (back) ponemos una condicion en blade si hay mensaje de sesion muestra sino formulario.
 @if(session('status'))
{{session('status')}}
@else
 formulario
@endif

//como vamos a repetir este codigo en muchos lados, podemos ponerlo en un fichero partial (resources-views-partial) y luego en el codigo lo sustituimos por @include en el editar.blade.php

ALERT SWEET

https://sweetalert.js.org/guides/

<script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>

//ponerlo debajo del DOM en la vista
<script>
@if (session('success'))
swal("Buen Trabajo!", "{{ session('success') }}", "success");
@endif
</script>


//en el controlador 
return back()->with('success','Hemos recibido el mensaje');

TOASTR

En la página siguiente podemos hacer las modificaciones del script como más nos guste y sustituirlo en vez "toastr.info(....);"

https://codeseven.github.io/toastr/demo.html

https://github.com/CodeSeven/toastr


/*En la VISTA*/
<!--Añadir librerias BOOTSTRAP-->
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>

<!--Añadir librerias TOASTR-->
  <link href="//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/css/toastr.min.css" rel="stylesheet">
  <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/js/toastr.min.js"></script>

.......

<script>
    @if(Session::has('info'))
        toastr.info("{{ session('info') }}");
    @endif
</script>


/*En el CONTROLADOR*/
return back()->with('info','Hemos recibido el mensaje');

</script>

BASES DE DATOS - ORM

Para crear una base de datos empezaremos con una tabla, es recomendable primero crear la migracion que corresponde con la tabla en la base de datos "articulos" y a continuación crearemos el modelo que corresponde con la entidad "Articulo". Es preferible crearlo en ese orden, también hay que tener cuidado a la hora de crear la migración en plural y la entidad en singular.

php artisan make:migration create_articulos_table --create="articulos"

//Tabla articulos
 Schema::create('articulos', function (Blueprint $table) {
            $table->increments('id')->unsigned();
            $table->text('titulo');
            $table->mediumText('descripcion');
            $table->timestamps();
          });

IMPORTANTE - TIPOS DE COLUMNAS

https://laravel.com/docs/6.x/migrations#creating-columns


php artisan make:model Articulo

//Modelo Articulo
class Articulo extends Model
{
    protected $table = 'articulos';  //hacemos referencia a la tabla artículos
    protected $fillable = ['titulo', 'descripcion'];   //fillable para proteger los campos que desea que permitan la actualización a la hora de insertar en la base de datos por asignación masiva

}

SEEDER (SEMILLAS)

SEEDER normal

1. Ejecutamos en terminal php artisan make:seeder NombreSeeder

2. podemos ver que dentro de database->seeds se genera la nueva semilla e introducimos los siguientes datos.

//y en la clase NombreSeeder:

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;

......

  for ($i=0; $i<10; $i++) {
        DB::table('projects')->insert([
            'title' => Str::random(10),
            'description' => Str::random(10).'@gmail.com',
            'created_at' => date('Y-m-d'),
            'updated_at' => date('Y-m-d')        ]);
    }

3. luego en la clase DataBaseSeeder (otro fichero que ya está creado) activamos dentro de la clase $this->call(NombreSeeder::class);

.....
  public function run()
    {
       $this->call(NombreSeeder::class);
    }

4. Para generar los datos insertarmos en terminal php artisan db:seed

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


CLASE FAKER

Para utilizar la clase FAKER, viene a ser igual que la Seeder que trae por defecto Laravel. Página oficial https://github.com/fzaninotto/Faker#formatters

1. Instalamos la libreria en terminal composer require fzaninotto/faker

2. Ejecutamos en terminal php artisan make:seeder NombreSeeder

3. podemos ver que dentro de database->seeds se genera la nueva semilla e introducimos los siguientes datos.

//si queremos utilizar la clase FAKER

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Faker\Factory as Faker;

class ContactosSeeder extends Seeder
{
  public function run(){
    // puntero para recorrer Faker
    $handle = Faker::create();

    for ($i=0; $i<10; $i++) {
      DB::table('contactos')->insert([
        'nombre' => $handle->firstName,
        'apellidos' => $handle->lastName,
        'created_at' => $handle->dateTime($max = 'now', $timezone = null),
        'updated_at' => $handle->dateTime($max = 'now', $timezone = null)
      ]);
    }
  }
}

3. luego en la clase DataBaseSeeder (otro fichero que ya está creado) activamos dentro de la clase $this->call(NombreSeeder::class);

.....
  public function run()
    {
       $this->call(NombreSeeder::class);
    }

4. Para generar los datos insertarmos en terminal php artisan db:seed

CONSTRUCTOR DE CONSULTAS (Query Builder)

Cuando estamos usando conexiones múltiple

//añadimos 
use Illuminate\Support\Facades\DB;

....
//obtenemos todos los usuarios
$users = DB::table('users')->get();

foreach ($users as $user)
{
    echo $user->name;
}

//Más ejemplos de consultas
$user = DB::table('users')->first();

$user = DB::table('users')->where('name', 'julio')->get();

$users = DB::table('users')->where('edad', '>', 100)->get();

$users = DB::table('users')->where('estado', '<>', 'active')->get();

$users = DB::table('users')->where('name', 'like', 'J%')->get();

//insertar
DB::table('Articulos')->insert(
        ['titulo'=>"pepe",'descripcion'=>"nuevadescripcion"]
    );

//update

DB::table('datos')
              ->where('id', 1)
              ->update(['nombre' => 'Estefania']);

//delete
DB::table('datos')->delete();
DB::table('datos')->where('votes', '>', 100)->delete();

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

CONSULTAS SQL NATIVAS

//seleccionar
$results = DB::select('select * from users where id = :id', ['id' => 1]);

//insertar en la Base users
DB::insert('insert into users (id, name) values (?, ?)', [1, 'Dayle']);

//actualizar
$affected = DB::update('update users set votes = 100 where name = ?', ['John']);

//borrar
$deleted = DB::delete('delete from users');

//Ejecutando una instrucción general que no devuelve ningún valor
DB::statement('drop table users');

http://documentacion-laravel.com/database.html#ejecutando-consultas-sql-nativas

ELOQUENT

$escritores=Escritor::all();  //$escritores=Escritor::get();

$escritoresOrdenados=Escritor::orderBy('nombre','DESC')->get();

$escritor= App\Escritor::findOrFail(1);

$escritor= App\Escritor::where('edad', '>', 100)->firstOrFail();

$escritor= App\Escritor::whereEdad(100)->get();  //es más eficiente especificar las columnas Escritor::select('id','name')->whereEdad(100)->get()

$EscritoresUlti=Escritor::latest('created_at')->get();   //muestra los últimos que se han añadido


//insertar
        $escritor = new Escritor();  
        $escritor->nombre = 'Julio';    
        $escritor->save();

//actualizar
        $escritor = Escritor::find(1);  //$escritor = App/Escritor::find(1);
        $escritor->nombre = 'Pepe';     //$request->name;
        $escritor->save();
//borrar
        $escritor= App\Escritor::find(1);
        $escritor->delete();
  • all() devuelve todos los elementos de una tabla.
  • find($id) coge una id y devuelve un sólo modelo. Si no existe un modelo coincidente, devuelve null.
  • findOrFail($id) toma una idy devuelve un sólo modelo. Si no existe un modelo coincidente, arroja un error1 404.
  • first() devuelve el primer registro encontrado en la base de datos. Si no existe un modelo coincidente, devuelve null.
  • firstOrFail() devuelve el primer registro encontrado en la base de datos. Si no existe un modelo coincidente, arroja un error1 404.
  • get() devuelve una colección de modelos que coinciden con la consulta.
  • findOrCreate() en el caso que no existe en la BD, lo crea.
$dato=Escritor::firstOrCreate(['nombre'=>'Estefania','edad'=>'32']);

https://laravel-news.com/firstornew-firstorcreate-firstor-updateorcreate

  • toArray() convierte el modelo / colección en una matriz PHP simple.
  • Pluck() en caso de obtener una colección y filtrar la parte que nos interesa.
$users = User::all(); // Devuelve una colección de usuarios, por ejemplo, ['name' => 'John', 'age' => 55],['name' => 'Melissa', 'age' => 18],['name' => 'Bob', 'age' => 43]
$usernames = $users->pluck('name'); // tenemos una colección de ['John', 'Melissa', 'Bob', 'Sara']


¿Cúal forma es mejor o más óptima? ¿SQL NATIVE o QUERY BUILDER o ELOQUENT?

https://www.laraveltip.com/que-es-mejor-eloquent-query-builder-o-sql/

PAGINAR

/*en CONTROLADOR de index*/
        $datos=Dato::latest()->paginate(3);


/*en la VISTA debajo de forelse */
//en el momento que insertamos datos dentro de la tabla y queremos mostrar los datos de forma más humana.
<ul>
  @forelse ($datos as $item)
              <li>  {{$item->title}}  {{$item->created_at->diffForHumans() }} </li>  
            @empty
                <li>NO HAY NADA </li>
            @endforelse
</ul>

{{$datos->links()}}  //DEBAJO DEL FORELSE

CRUD

Creas la tabla

php artisan make:migration create_blogs_table --create=blogs


Luego en la migración creas los campos para la base de datos

Schema::create('blogs', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('blog_title');
$table->text('blog_content');
$table->timestamps();
});

Para generar las rutas podemos hacer dos cosas:

1)Generarlas automáticamente con el nombre de las rutas en inglés.


Generas las rutas insertando el fichero Web

Route::resource('blogs','blogController');

//Para listar las rutas, en terminal 

php artisan route:list -v


Creamos Controlador

php artisan make:controller blogController --resource

1.index()

2.create()

3.store()

4.show()

5.edit()

6.update()

7.destroy()


https://www.expertsphp.com/laravel-6-crud-create-read-update-delete-generator-for-beginners-with-example/


2) Diseñar nuestras rutas y controlador en castellano uno a uno

//Diseñamos nuestras rutas en Web
Route::get('/index', 'DatosController@index')->name('index');
Route::post('/almacenar', 'DatosController@almacenar')->name('almacenar');
Route::get('/editar/{id}', 'DatosController@editar')->name('editar');
Route::patch('/actualizar/{id}', 'DatosController@actualizar')->name('actualizar');
Route::delete('/borrar/{id}', 'DatosController@borrar')->name('borrar');
Route::view('/insertar','insertar')->name('insertar');


Diseñamos la migración y el modelo, en caso de necesitarlo

php artisan make:migration create_datos_table --create=datos


//creamos la migracion que es la tabla en la base de datos "datos"

Schema::create('datos', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('nombre');
            $table->text('descripcion');
            $table->timestamps();
        });


//creamos el modelo "Dato" que es la Entidad que vamos a trabajar y dentro ponemos los datos que queremos proteger.

php artisan make:model Dato

protected $table= 'datos';
protected $fillable = ['nombre', 'descripcion']; //¿Qué atributos deberías incluir en dicho array?

//Aquellos que consideres sensibles y que no deberían modificarse o asignarse en cierta forma, el más típico es el id, el cual normalmente no se modifica ni se asigna de forma manual.
}


INDEX-MOSTRAR DATOS

/**********en el CONTROLADOR**********/
 public function index(){

    $datos=Dato::all();

    return view('index',['datos'=>$datos]);  //view('index',compact('datos');
   } 

/***********en la VISTA***********/
@forelse ($datos as $item)
<li> 
{{$item->nombre}} {{$item->descripcion}} 
     <a href="{{ route('editar', $item->id)}}" >Edit</a> <!--añadimos también EDITAR-->
     <form action="{{ route('borrar', $item->id)}}" method="post"> <!--añadimos también BORRAR-->
        @csrf
        @method('DELETE')
        <button type="submit">borrar</button>
    </form>
</li>
@empty
<li>NO HAY NADA </li>
@endforelse

INSERTAR -STORE

/***********En el CONTROLADOR***********/
 public function almacenar(Request $request){

//LA MEJOR FORMA DE INSERTAR DATOS ya que se hace la comprobación de los campos obligatorios para que no hagan inyeccion y luego inserta.
    $datos=request()->validate([
        'nombre'=>'required|max:25', 
        'descripcion'=>'required']
    );

    Dato::create($datos);

    return redirect()->route('index');
 //return back(); //te redirecciona a la misma página
   } 


/***********En la VISTA***********/

@if ($errors->any())  //esto muestra todos los errores seguidos
    <ul>
        @foreach ($errors->all() as $error)
        <li>{{ $error }}</li>
        @endforeach
    </ul>
<br/>
@endif

<form method="post" action="{{ route('almacenar') }}"> 
/* action="{{ action('RelacionController@almacenar') }}"  //con esto vamos directamente al controlador desde la vista */
   
        @csrf
        <label for="name">Nombre:</label>
        <input type="text" name="nombre" value="{{old('nombre')}}"/>  <!--ponemos old porque en el caso que carguemos el formulario y diera error habría que volver a introducir todos los campos, así recuerda o guarda los campos que están bien-->
     {!! $errors->first('name', '<small>:message</small><br>' )!!}  <!-- así especificamos los errores debajo-->
  
        <label for="price">Descripcion:</label>
        <input type="text" name="descripcion" value="{{old('descripcion')}}"/>
     {!! $errors->first('descripcion', '<small>:message</small><br>' )!!}  
 

    <button type="submit">Crear</button>
</form>

EDITAR

/***********EN EL CONTROLADOR***********/

public function editar($id){

    $dato = Dato::findOrFail($id);  //como no está el dato si nos equivocamos de id nos muestra la página de error 404, podemos crear uno personalizado en la view->errors->404.blade.php , creamos carpeta "errors"


    return view('editar', compact('dato'));
   } 


/***********EN LA VISTA para EDITAR***********/

@if ($errors->any())
        <div class="alert alert-danger">
            <strong>Whoops!</strong> There were some problems with your input.<br><br>
            <ul>
                @foreach ($errors->all() as $error)
                    <li>{{ $error }}</li>
                @endforeach
            </ul>
        </div>
    @endif

<form method="post" action="{{ route('actualizar', $dato) }}">  //No es necesario especificar el Id ya que la nueva versión laravel ya busca dentro del Objeto
          <div > 
              @method('PATCH')
              @csrf
              
              <label for="name">nombre:</label>
              <input type="text"  name="nombre" value="{{ $dato->nombre }}"/>
          </div>
          <div >
              <label for="descripcion">descripcion</label>
              <input type="text"  name="descripcion" value="{{ $dato->descripcion }}"/>
          </div>
         
          <button type="submit" >Actualizar</button>
      </form>
  </div>
</div>

/***********En el CONTROLADOR para ALMACENAR DATOS ya MODIFICADOS***********/

public function actualizar(Request $request, $id){

        $validacion=$request->validate([
        'nombre' => 'required|min:1|max:10',
        'descripcion' => 'required',
        ]);
       
        Dato::whereId($id)->update($validacion); //otra opción

        /*  //otra forma de almacenar 
        $datos = Dato::find($id);   //podremos utilizar findOrFail($id) para que en caso de no encontrar no falle
        $datos->nombre = $validacion['nombre'];
        $datos->descripcion = $validacion['descripcion'];

        $datos->update();*/

        return redirect()->route('index');
      
    } 


// formar de recuperar datos de un formulario. $request->get('nombre'); $request->nombre;  $request->input('nombre');


BORRAR

/***********en el controlador borrar***********/

    public function borrar($id){

        $dato = Dato::findOrFail($id);
        
        $dato->delete();
    
        return redirect()->route('index');
       } 


/*Otra forma de Borrar*/
use App\Dato; //añadimos el modelo en el controlador

....

  public function borrar(Dato $dato){

        $dato->delete();
                  
        return redirect()->route('index');
         }

GENERAR CRUD AUTOMÁTICAMENTE

https://github.com/awais-vteams/laravel-crud-generator

https://github.com/appzcoder/crud-generator

RELACIONES

Se puede crear primero el Modelo(Entidad) y luego generar la migración, el problema es que si diseñamos el modelo Escritor(Entidad) generará automáticamente la migración Escritors, habría que definir la tabla en la entidad.

Por tanto, la otra opción es diseñar primero la migración (tablas) y luego los modelos (entidades)


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



RELACIÓN UNO A MUCHOS (1XM)

Una categoria tiene muchos artículos. Creamos primero las migraciones (bases datos) y luego el modelo (Entidades), también tenemos la opción de crear el modelo y luego automaticamente las migraciones pero hay que tener cuidado ya que genera el nombre de las tablas de la migración en inglés.

php artisan make:migration create_categorias_table --create="categorias"


php artisan make:migration create_articulos_table --create="articulos"


Tablas migraciones

//tabla Categories
  Schema::create('categorias', function (Blueprint $table) {
            $table->increments('id')->unsigned();
            $table->text('nombre');
            $table->mediumText('masInfo');
            $table->timestamps();
        });

//tabla articulos


    Schema::create('articulos', function (Blueprint $table) {
            $table->increments('id')->unsigned();
            $table->integer('categoria_id')->unsigned();  //si hubieramos puesto categorias_id tambien hubiera cogido la relación
            $table->text('titulo');
            $table->mediumText('descripcion');
            $table->timestamps();
            //relaciones
            $table->foreign('categoria_id')->references('id')->on('categorias')->onDelete('cascade')->onUpdate('cascade');
            //category_id hace referencia a la tabla categories y el borrado y la actualización es en cascada.
        });

Creamos los modelos

php artisan make:model Categoria

//Modelo Categoria
class Categoria extends Model
{
    protected $table = 'categorias';
    //protected $primary_key = 'categoria_id';  //Por defecto id es la clave primaria, podemos definir un campo diferente con la propiedad primaryKey
    //public $timestamps = true;  //especificamos si queremos crear created_at y updated_at en la base de datos
    protected $fillable = ['nombre', 'masInfo'];

    public function articulos()
    {
        return $this->hasMany('App\Articulo');
    }
}


//Modelo Artículos

class Articulo extends Model
{
    protected $table = 'articulos';
    protected $fillable = ['titulo', 'descripcion'];

    public function categoria()
    {
        return $this->belongsTo('App\Categoria');
    }
}

En el controlador

public function insertar()
    {
        $categoria = Categoria::find(3);   //buscamos que ya tenemos almacenada o la creamos.

        $articulo = new Articulo(['titulo' => 'Pedazo Artículo', 'descripcion' => 'toda la descripción']);  //creamos artículo.
        $categoria->articulos()->save($articulo);  //guardamos dentro de categoria un artículo.
       
       //en caso que tengamos varios artículos
       /* $categoria->articulos()->saveMany([
            new Articulo(['titulo' => 'A new comment.', 'descripcion' => 'hola']),
            new Articulo(['titulo' => 'Another comment.',  'descripcion' => 'hola']),
        ]);*/
        
    }

http://documentacion-laravel.com/eloquent-relationships.html#insertando-y-actualizando-modelos-relacionados


PROBLEMA N+1 - LAZY LOADING

//muestra el nombre de todas las categorias de todos los artículos. Una consulta para obtener todos los artículos en la tabla, después otra consulta para cada articulos para obtener quien es el autor

 $articulos = Articulo::all();

 foreach ($articulos as $articulo) {
     dump($articulo->categoria->nombre);
   }

SOLUCIÓN - EAGER LOADING //al usar la carga previa o carga impaciente (Eager Loading) para reducir esta operación a solo 2 consultas

$articulos = Articulo::with('categoria')->get();

 foreach ($articulos as $articulo) {
           echo $articulo->categoria->nombre ."</br>";
        }

https://styde.net/lazy-loading-vs-eager-loading/

Borrado

//borra la categoria 9 y todos los articulos relacionados (cascada)
$Categoria = Categoria::find(9);
$Categoria->delete();

//borra artículo
$articulo = Articulo::find(2);        
$articulo->delete();


Consultas interesantes para 1xN

//Métodos de relación
//Toda la info de Categoria
 $categoria = Categoria::find(3);  //debe existir categoria y artículos
 return $categoria->articulos()->where('descripcion', "hola")->get();  //->whereDescripcion('hola')


//Obtenemos del artículo el nombre de la Categoria relacionada
 $articulo = Articulo::findOrFail(2);
 dump($articulo->categoria->nombre);


https://desarrollowebtutorial.com/laravel-eloquent-orm-query-builder-consultas-sql/

HAS

Es como el WHERE, devuelve las categorias que tiene al menos 1 articulo

$categorias=Categoria::has('articulos')->get();


Categoria::where('descripcion','like','%#'.$etiqueta.'%')->get();


https://blog.coffeedevs.com/como-evitar-consultas-de-mas-al-utilizar-eloquent-orm/

https://medium.com/@hemnys25/de-0-a-100-con-eloquent-de-laravel-parte-0-d5347c060ad7

https://stackoverflow.com/questions/30231862/laravel-eloquent-has-with-wherehas-what-do-they-mean



CONSULTAS EN MULTIPLES TABLAS

Ejemplo// Tablas: a, b, c, d, e, f

Quiero traer los datos de todas las tablas relacionadas, los datos de a, b, c, d,e,f.

   A está relacionado con B (1,n)
   B con C (1,n)
   C con D (1,n)
   D con E (1,n)
   E con F (1,n)

Solución: https://es.stackoverflow.com/questions/173727/consultas-en-m%C3%BAltiples-tablas-con-laravel-5-5



RELACION DE MUCHOS A MUCHOS (NXM)

Un post puede tener muchas Etiquetas y una etiqueta puede tener muchos Posts, por tanto habrá que crear una tabla auxiliar.


php artisan make:migration create_etiquetas_table --create="etiquetas"

php artisan make:migration create_posts_table --create="posts"

php artisan make:migration create_etiqueta_post_table --create="etiqueta_post"


Dentro de la tabla de migraciones

//ETIQUETAS
Schema::create('etiquetas', function (Blueprint $table) {
            $table->increments('id');

            $table->string('nombre',128);
            $table->string('slug',128);

            $table->timestamps();
        });

//POSTS
   Schema::create('posts', function (Blueprint $table) {
            $table->increments('id');

             $table->string('nombre',128)->unique();
             $table->string('slug',128);
             $table->text('cuerpo');
             $table->enum('status',['PUBLISHED','DRAFT'])->default('DRAFT');
             $table->string('file', 128)->nullable();
 
             $table->timestamps();
             
        });

//ETIQUETA_POST
 Schema::create('etiqueta_post', function (Blueprint $table) {
            $table->increments('id');

            $table->integer('post_id')->unsigned();
            $table->integer('etiqueta_id')->unsigned();

            $table->timestamps();

             //relaciones
             $table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade')->onUpdate('cascade');
             $table->foreign('etiqueta_id')->references('id')->on('etiquetas')->onDelete('cascade')->onUpdate('cascade');
        });


Dentro de los modelos

//Modelo POST
class Post extends Model
{
    protected $table = 'posts';
    //protected $primary_key = 'categoria_id';
    protected $fillable = ['nombre', 'cuerpo','status'];

    public function etiquetas()
    {
        return $this->belongsToMany('App\Etiqueta');
    }
}

//Modelo ETIQUETA

class Etiqueta extends Model
{
    protected $table = 'etiquetas';
    //protected $primary_key = 'categoria_id';
    protected $fillable = ['nombre', 'slug'];

    public function posts()
    {
        return $this->belongsToMany('App\Post');
    }
}

//INSERTAR Tabla intermedia

public function insertarTablaIntermedia(){
        $etiqueta=Etiqueta::find(1);
        $post = Post::find(2);
        $post->etiquetas()->attach($etiqueta);
       }

//OBTENER DATOS DE LA otra TABLA RELACIONADA.

return Post::find(1)->etiquetas()->get();  //del Post(1) obtiene todas las etiquetas relacionadas
return Post::find(1)->etiquetas()->where('nombre','futbol')->get();  //del Post(1) obtiene la etiqueta relacionada que tiene nombre = "futbol"

CREAR MODELOS ELOQUENT desde la BASE DATOS

Introducimos el comando de instalación del paquete

composer require reliese/laravel --dev

Registrar el provider en app/Providers/AppServiceProvider.php

public function register()
{
    if ($this->app->environment() == 'local') {
        $this->app->register(\Reliese\Coders\CodersServiceProvider::class);
    }
}

Publicas el fichero de configuración:

php artisan vendor:publish --tag=reliese-models

Comandos:

//Crea todos los MODELOS de las tablas de la BD 
php artisan code:models

//Crea un MODELO de una tabla
php artisan code:models --table=users


https://cristianllanos.medium.com/eloquent-models-from-my-database-5d74c632e03c#.qg7cd4vri

SLUG (babosa)

Para mejorar el posicionamiento SEO de nuestra web en las url hay que evitar poner "/detalle/1" y darle un signficado a nuestras rutas "/detalle/julio-profesor"

Por tanto, podemos añadir a nuestra tabla de la base de datos un nuevo campo, por ello, podemos editar la tabla:

//php artisan make:migration anadir_slug_tabla_tareas --table=tareas
//creará una nueva migración donde añadiremos un nuevo campo, en este caso slug.

class AnadirSlugTablaTareas extends Migration
{
    public function up()
    {
        Schema::table('tareas', function (Blueprint $table) {
            $table->string('slug')->unique;
        });
    }
    public function down()
    {
        Schema::table('tareas', function (Blueprint $table) {
        $table->dropColumn('slug');    //eliminar campo.
        });
    }
}

Luego en el campo slug habrá que añadir "julio-profesor"

//CONTROLADOR
   public function mostrar()   //muestro todos los campos
    {
        $datos = Tarea::all();
        return view('datos', ['datos' => $datos]);
    }

    public function detalle($slug)   //Recibe el campo slug de la base de datos  y busca el resultado en la base de datos.
    {
        $tarea = Tarea::where('slug', $slug)->first();
        return $tarea;
    }
//VISTA
@forelse ($datos as $item)
<li> {{$item->nombre}}  <a href="{{ route('detalle', $item->slug)}}" >detalles</a></li>
@empty
<li>NO HAY NADA </li>
@endforelse
//RUTAS
Route::get('/mostrar', 'PruebaController@mostrar')->name('mostrar');
Route::get('/detalle/{slug}', 'PruebaController@detalle')->name('detalle');

MANEJAR VALIDACIONES

Para hacer las validaciones hay que evitar ponerlo en el controlador ya que es una mala práctica, por tanto el controlador solo debe tener la responsabilidad de tratar las solicitudes.

https://styde.net/como-trabajar-con-form-requests-en-laravel/

https://www.laraveltip.com/que-son-como-y-por-que-utilizar-los-form-request-de-laravel/

//Para mantener el código limpio y no tener que poner  app->http->request
php artisan make:request CreateDatosRequest   // [Nombre-del-modelo-que-impacta]+[Acción]+Request


 public function authorize()
    {
        return true;  //cambiar a true
    }

    public function rules()
    {
        return [
        'nombre' => 'required',
        'descripcion' => 'required',
        ];
    }

    public function messages()
    {
        return [
        'nombre.required' => 'El :attribute es obligatorio campeón',
        'descripcion.required' => 'El :attribute es obligatorio también',
        ];
    }

// en el controlador bastará con poner


public function actualizar(CreateDatosRequest $request){
//quitamos la validación
}

TRY ... CATCH

/*Las Rutas*/
Route::get('/formularioBusqueda', 'ProductController@formulario')->name('formularioBusqueda');   
Route::post('/product/resultado', 'ProductController@resultado')->name('resultadoBusqueda');
/*En la vista 'formularioBusqueda'*/
@if (session('error'))
<div>{{ session('error') }}</div>   <!--En caso de no encontrar el producto en la BBDD muestra error-->
@endif
 
<form action="{{ route('resultadoBusqueda') }}" method="POST">
@csrf

<input id="title name="title" type="text" value="{{ old('product') }}" placeholder="Product Title">

<input type="submit" value="Search">
</form>
/*En el controlador */

public function resultado(Request $request)
{
    try {
        $product = Product::where('title',$request->get('title'));  //busca el producto en la BBDD
    } catch (ModelNotFoundException $exception) {
        return back()->withError($exception->getMessage())->withInput();   //en caso de no encontrar en la BBDD captura la excepción y envia la info a la misma vista 
        //return $exception->getMessage();

    }
    return view('resultadoBusqueda', compact('product'));   //en caso de encontrar el producto manda otra vista el resultado
}

https://www.tutsmake.com/laravel-try-catch/

TRADUCCIÓN

Podemos hacerlo de dos formas:

1) Manualmente:

  • En el caso que queramos hacer validaciones en Castellano, deberemos ir a la carpeta Resources>Lang y crear una llamada ES. Luego para establecer el lang por defecto hay que cambiarlo en configuración APP>CONFIG>app.php y buscar la linea 'locate'=> 'es'.

2)También podemos instalar complemento:

  • composer require laraveles/spanish
  • php artisan vendor:publish --tag=lang

https://github.com/Laraveles/spanish

AUTENTIFICACIÓN

//Crear usuario en versiones anteriores a 6

php artisan make:auth

//Laravel 6

composer require laravel/ui "^3.0"   //composer require laravel/ui "^1.0" --dev -vvv

php artisan ui vue --auth   //php artisan ui bootstrap --auth

//para visualizar el login y registro con css, habrá que instalar nodejs y usar: 
//npm install
//npm run dev

1. Después si accedemos dentro routes->Web podemos ver que se ha creado Auth::routes();

2. Para cambiar la redirección después de Logearnos, tendremos que ir dentro app->http->Controller->Auth cambiamos las rutas de register y login cambiando ruta a /

3. Quitamos la ruta /home dentro de las rutas en web

"para borrar la sesion podemos borrar el fichero dentro storage->framework->session como prueba"

MUESTRA USUARIO BLADE

@auth    <!--sirve para mostrar en caso de estar autentificado, estar logeado-->
{{auth()->user()->name}}
@endauth
<!--tambien cambiar la ruta de middleware en caso de estar autentificado y volver hacer login peta y te manda a home por tanto cambiar a raiz.-->

@if(auth()) <!--si el usuario está autentificado-->

@endif


SABER SI ESTÁ LOGEADO EN EL CONTROLADOR

use Illuminate\Support\Facades\Auth;

if(Auth::check()){ 
 return "estas logeado";
}else { 
 return "no estas logeado";
} 

// Obtiene el objeto del Usuario Autenticado
$user = Auth::user();
$user->name;

SECURIZAR

También podemos indicarlo directamente en el constructor de un controlador

public function __construct()
{
$this->middleware('auth');
}

Otra forma es indicándolo en la ruta para protegerla

Route::get('/resultado', 'PruebasController@ejemplo')->middleware('auth);

LOGOUT

//usar directiva @guest- invitado. en caso de no estar logueado no muestra
@guest 
<a href="{{route('login')}}">Login</a>
@else   
<a href="{{ route('logout') }}" onclick="event.preventDefault(); document.getElementById('logout-form').submit();"> Logout </a>

  <form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
    {{ csrf_field() }}
  </form>
@endguest

DESHABILITAR REGISTRO

vamos a Web y modificamos ruta

Auth::routes(['register'=>false]);

BLOQUEAR USUARIO, INTENTOS FALLIDOS

En el caso que querramos bloquear al usuario por intentos de ingresos fallidos y penalizar el tiempo a la hora de volver autenficarte, bastará con añadir el controlador por defecto app->http->Controller->auth-> LoginController

class LoginController extends Controller
{
   
    use AuthenticatesUsers;

    public $maxAttempts = 2;   //número máximo de intentos
    public $decayMinutes = 2;  //tiempo que durará el bloqueo

MIDDLEWARE o FILTRO

filtran las peticiones http, en nuestro caso que compruebe si el usuario está autentificado o no. Son puertas que una peticion de usuario tiene que pasar antes de llegar al controlador que tiene la logica a la que el usuario intenta acceder.

php artisan make:middleware DomingoMiddleware


<?php

namespace App\Http\Middleware;

use Closure;

class DomingoMiddleware
{
    public function handle($request, Closure $next)
    {
        if(date('w')==='0'){
            //echo "Es domingo!"; 
           redirect()->route('home');

        }else{
            echo "No es domingo";
        }
        return $next($request);   //"continua tu camino"
    }
}

Luego hay dos formas de registrar el MiddleWare

1) de Forma GLOBAL en app/Http/Kernel.php

protected $middleware = [
        \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
        // otros middleware
        // ...
        \App\Http\Middleware\DomingoMiddleware::class,
    ];

2)Una ruta determinada o un controlador en app/Http/Kernel.php

protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        // otros middleware de rutas...
        'domingo' => \App\Http\Middleware\DomingoMiddleware::class,
];

//hay que añadir en la ruta web ->middleware('domingo');


Ahora podemos probar que funciona nuestro middleware

//pruebas en route web

Route::get('/test', ['middleware' => 'domingo', function(){
    return 'Probando ruta con middleware';
}])

Route::get('/test1','MoviesController@insertar')->name('insertar')->middleware('domingo');

//segunda prueba en route web

Route::group(['middleware' => 'domingo'], function(){
    Route::get('/probando/ruta', function(){
        //código a ejecutar cuando se produzca esa ruta y el verbo 
        return 'get';
    });

    Route::post('/probando/ruta', function(){
        //código a ejecutar cuando se produzca esa ruta y el verbo POST
        return 'post';
    });
});

//también se puede llamar desde dentro de un controlador y afectará a todas las acciones de dentro.

class PrimerController extends Controller
{
    public function __construct(){
        $this->middleware('domingo');
    }
}


https://programacionymas.com/blog/restringir-acceso-solo-administradores-laravel-usando-middlewares

https://desarrolloweb.com/articulos/laravel-middleware.html

ROLE

Añadimos en la tabla de migracion users un nuevo atributo role de tipo enum y luego hacemos la migración

$table->enum('role',['user','admin'])->default('user');

//hacemos la migración
php artisan migrate

Añadimos la autentificación de usuarios en este caso para Laravel 6.0

composer require laravel/ui 

php artisan ui bootstrap --auth

Creamos el MiddleWare y dentro introducimos el siguiente código app->http->Middleware

//php artisan make:middleware Admin

  public function handle($request, Closure $next)
    {
        if (auth()->user()->role == "admin") {

            return $next($request);
        }
        return redirect('home')->with('error', 'You dont have admin access');
    }

Luego registramos dentro del fichero Kernel.php el middleware en $routeMiddleware

'admin' => \App\Http\Middleware\Admin::class,

Creamos la ruta nueva

Route::get('admin/routes', 'HomeController@admin')->middleware('admin');

En el controlador de HomeController, son las dos rutas que hemos indicado en caso de ser user o admin

public function index()
    {
        return view('home');
    }

    public function admin()
    {
       return view('admin');
    }

Creamos las dos vistas

home.blade

@extends('layouts.app')
 
@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">USER NORMAL</div>
 
                <div class="card-body">
                    @if(auth()->user()->role== "admin")
                    <a href="{{url('admin/routes')}}">Admin</a>
                    @else
                    <div class="panel-heading">Normal User</div>
                    @endif
                </div>
            </div>
        </div>
    </div>
</div>
@endsection


admin.blade.php

@extends('layouts.app')
 
@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">ADMINISTRADOR</div>
 
                <div class="card-body">
                    @if(auth()->user()->role== "admin")
                    <a href="{{url('admin/routes')}}">Admin</a>
                    @else
                    <div class="panel-heading">Normal User</div>
                    @endif
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

//nota: habrá que cambiar la ruta del fichero loginController a la ruta /admin/routes para que haga el middleware

https://w3path.com/laravel-6-multiple-authentication-system-example-tutorial/ https://stackoverflow.com/questions/39555865/laravel-routegroup-for-admins


Ejercicio: Modificar el registro de usuarios para que pueda añadirse el diferente tipo de role con un desplegable (user o Admin)

composer dump-autoload

RECUPERAR CONTRASEÑA POR CORREO

https://stackoverflow.com/questions/33939393/failed-to-authenticate-on-smtp-server-error-using-gmail

https://github.com/facade/ignition-code-editor

SUBIR FICHEROS

RUTAS

Route::view('/subir','subir')->name('subir');   //va directamente a la vista, no hace falta poner controlador

Route::post('/subidoFichero','PruebasController@subidoFicheroPost')->name('subidoFicheroPost');

VISTA Subir

@if ($message = Session::get('success'))
<strong>{{ $message }}</strong>  <!-- muestra el mensaje flash en caso de ser cierto-->
@endif

@if (count($errors) > 0)
<div>
    <strong>Uppss!</strong> Hay algunos problemas en la subida.<br><br>
    <ul>
        @foreach ($errors->all() as $error)
        <li>{{ $error }}</li>
        @endforeach
    </ul>
</div>
@endif


<form action="{{ route('subidoFicheroPost')}}" method="post" enctype="multipart/form-data">
    @csrf
    <div class="form-group">
        <input type="file" name="fileToUpload" id="exampleInputFile" aria-describedby="fileHelp">
        <small id="fileHelp">El tamaño del fichero no debe ser superior a 2 MB.</small>
    </div>
    <button type="submit">Subir</button>
</form>
</div>
</div>
</div>
</div>

CONTROLADOR SubidaFicheroPost

public function subidoFicheroPost(Request $request){
        $request->validate([
            'fileToUpload' => 'required|file|max:1024',
        ]);

       // $request->fileToUpload->store('logos');   //almacena el fichero dentro de storage->app->logos

       $fileName = "fileName".time().'.'.request()->fileToUpload->getClientOriginalExtension();  //filename+ tiempo desde inicio UNIX + extensión fichero (.pdf...)

        $request->fileToUpload->storeAs('public/logos',$fileName); //almacena el fichero dentro de storage->app->public->logos

        return back()->with('success','Tu imagen se ha subido satisfactoriamente');  //retorna a la misma página

       //public_path() , storage_path()

    }

Cuando subimos imágenes y queremos mostrarla en la vista, por defecto se almacenan dentro de storage->app->public->logos, el problema es que esa carpeta no es pública para todo el mundo, por tanto, si ejecutamos el comando php artisan storage:link creará un enlace simbólico creando una nueva carpeta dentro public->storage->logos


//vista  (las imágenes deben estar en la carpeta app/storage/public/logos)
<img src="{{ url('storage/logos/'.$imagen) }}">
<img src="{{ asset('storage/logos') }}/{{$b->imagen}}">


http://documentacion-laravel.com/filesystem.html#introduccion http://documentacion-laravel.com/filesystem.html#configuracion

DRAG & DROP

Creamos la vista y luego en el controlador tenemos que guardar al igual que subimos un fichero

/*En la VISTA*/
//librerias
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"> 
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.5.0/min/dropzone.min.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.5.0/dropzone.js"></script>
  </head>

  <body>
    <div class="container">
        <h2>Laravel 6 Subir multiples imágenes</h2><br/>
      
        <form method="post" action="{{ route('almacenar') }}" enctype="multipart/form-data" class="dropzone" id="dropzone">
        @csrf
        </form>

    </div>

    <script type="text/javascript">

        Dropzone.options.dropzone =
        {
            maxFilesize: 10,
            acceptedFiles: ".jpeg,.jpg,.png,.gif",
            addRemoveLinks: false,
            timeout: 60000,
            success: function (file, response) {
                console.log(response);
            },
            error: function (file, response) {
                return false;
            }
        };

    </script>
  </body>
/*En el CONTROLADOR*/

//otra forma de subir fichero en la carpeta Public
public function subidoFicheroPost(Request $request){

        $image = $request->file('file');
        $avatarName = $image->getClientOriginalName();
        $image->move(public_path('images'),$avatarName);  //guarda en la ruta ->public->images
        //$image->move(storage_path('\app\public\images'),$avatarName);  //almacena en la ruta storage->app->public->images

}

https://appdividend.com/2018/05/31/laravel-dropzone-image-upload-tutorial-with-example/

DESCARGAR FICHEROS .ZIP

composer require chumper/zipper

//dentro de config/app.php
//en providers
Chumper\Zipper\ZipperServiceProvider::class,
//en aliases
'Zipper' => Chumper\Zipper\Zipper::class,

Controlador

use Zipper;

class Controller extends BaseController
{
 

    public function comprimirDescargar()
    {
        /*Añadimos la ruta donde se encuentran los archivos que queramos comprimir,
          en este ejemplo comprimimos todos los que se encuentran en la carpeta 
          storage/app/public*/
        $files = glob(storage_path('app/public/*'));
        
        /* Le indicamos en que carpeta queremos que se genere el zip y los comprimimos*/
        Zipper::make(storage_path('app/public/ejemplo.zip'))->add($files)->close();
        
        /* Por último, si queremos descarlos, indicaremos la ruta del archiv, su nombre
        y lo descargaremos*/
        return response()->download(storage_path('app/public/ejemplo.zip'));
    }


}

RUTA

Route::get('/comprimir', 'Controller@comprimirDescargar')->name('comprimir');

VISTA

<a href="{{route('comprimir')}}">Comprimir y descargar</a>

AJAX

https://www.tutsmake.com/laravel-6-install-yajra-datatables-example-tutorial/

https://laraveles.com/implementacion-datatables-laravel-5-4/

//instalamos paquete yajra	
composer require yajra/laravel-datatables-oracle

Cambiar -> config/app.php

añadir en alias
'Datatables' => yajra\Datatables\Datatables::class,

añadir en providers
yajra\Datatables\DatatablesServiceProvider::class,

hacer público el archivo de configuración con el siguiente comando, el cual nos crea el archivo config/datatables.php	
php artisan vendor:publish --tag=datatables


//Migración
 Schema::create('tareas', function (Blueprint $table) {
            $table->increments('id');
            $table->string('nombre');
            $table->string('apellido');
            $table->string('estado');
            $table->timestamps();
        });

//Modelo

class Tarea extends Model
{
    protected $table = 'tareas';
    protected $primary_key = 'tareas_id';
}


// web
Route::get('/', 'PruebaController@index');
Route::get('/tareas', 'PruebaController@getTareas')->name('datatable.tareas');


//controlador

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Redirect,Response,DB,Config;
use Datatables;
use App\tarea;

class PruebaController extends Controller
{
    public function index()
    {
        return view('vista');
    }
 
    /**
     * @return mixed
     */
    public function getTareas()
    {
        $tareas = Tarea::select(['id','nombre','apellido','estado']);
 
        return Datatables::of($tareas)->make(true);
    }
}


//vista


<!DOCTYPE html>
 
<html lang="en">
<head>
<title>Laravel DataTable - Tuts Make</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">  
<link  href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css" rel="stylesheet">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js"></script>  
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js"></script>
</head>
<body>
 
<div class="container">
    <table id="task" class="table table-hover table-condensed">
        <thead>
        <tr>
            <th>Id</th>
            <th>Task</th>
            <th>Category</th>
            <th>State</th>
        </tr>
        </thead>
    </table>
</div>
 
<script type="text/javascript">
    $(document).ready(function() {
        oTable = $('#task').DataTable({
            "processing": true,
            "serverSide": true,
            "ajax": "{{ route('datatable.tareas') }}",
            "columns": [
                {data: 'id', name: 'id'},
                {data: 'nombre', name: 'nombre'},
                {data: 'apellido', name: 'apellido'},
                {data: 'estado', name: 'estado'}
            ]
        });
    });
</script>
</body>
</html>

CLASES PERSONALIZADAS

//Crear nuestra Clase Personaliza Helper.php dentro de un directorio Helpers dentro de nuestra carpeta app de laravel quedando de la siguiente forma: app/Helpers/Helper.php con la siguientes lineas de codigo,

# Ubicacion app\Helpers\Helper.php

namespace App\Helpers;

class Helper
{
    public static function strUp(string $string)
    {
        return strtoupper($string);
    }
}

Crear Alias en nuestra aplicacion

# Ubicacion: config/app.php

    'aliases' => [
     ...
        'Helper' => App\Helpers\Helper::class,
     ...

Usarlo en nuestras plantillas Blade

{{ Helper::strUp('mostrar este texto en mayúsculas!') }}

Usarlos en nuestro controlador

namespace App\Http\Controllers;

//use Helper;
use App\Helpers\Helper;
//use App\Helpers;

class TuController extends Controller
{

    public function metodo()
    {
        Helper::strUp('mostrar este texto en mayúsculas!');
    }
}

TRAITS

/*En el CONTROLADOR*/

use App\Http\Traits\Mayusculas;
.....

class PeliculasController extends Controller
{

  use Mayusculas;

  public function ejemplo()
  {
    echo Mayusculas::convertir("Julio Noguera");
  }

}

Nos creamos un fichero en app->Http->Traits->Mayusculas.php

<?php

namespace App\Http\Traits;

trait Mayusculas
{
    public static function convertir(string $string)
    {

        $mayusculas=strtoupper($string);

        return $mayusculas;
    }
}

https://diego.com.es/traits-en-php

GENERAR PDF

Instalamos libreria

composer require barryvdh/laravel-dompdf

añadimos la siguiente ruta en config/app.php en el array 'provider'

Barryvdh\DomPDF\ServiceProvider::class,

luego añadimos la siguiente ruta en config/app.php en el array 'aliases'

'PDF' => Barryvdh\DomPDF\Facade::class,

crearmos ruta en Web

Route::get('/imprimir', 'RelacionController@imprimir')->name('imprimir');

y una vista llamada 'imprimir.blade.php' con código en html

<body>
        <h1>Página de prueba</h1>

</body>


use PDF;
......

public function imprimir(){
     $pdf = PDF::loadView('imprimir');
     return $pdf->download('ejemplo.pdf');
}

https://www.nigmacode.com/laravel/Generar-pdf-Dompdf-Laravel

DEBUGBAR

composer require barryvdh/laravel-debugbar --dev

Dentro de config->App añadimos en provider

Barryvdh\Debugbar\ServiceProvider::class,

En aliases

'Debugbar' => Barryvdh\Debugbar\Facade::class,

EJERCICIO 1

1. Se desea crear una filmografía de películas, por ello, debemos crear una página web que liste todas las películas que tiene almacenada localmente (array, fichero), también cabe la posiblidad de tener un formulario donde se pueda introducir el nombre de la película, año, director, descripción y una imagen (url) y se almacene.

Habrá que crear las rutas (crear, buscar/{id}, listar) y las correspondientes vistas(herencia). Lo ideal es que se muestre la imagen de película y clicando sobre ella muestre el resto de la información.

array_ejemplo


https://medium.com/techcompose/create-rest-api-in-laravel-with-authentication-using-passport-133a1678a876

https://medium.com/@bapunawarsaddam/rest-api-with-laravel-5-8-using-laravel-passport-53b5953798bb

https://medium.com/@devfelipe.mansilla/usando-graphql-con-laravel-446f0de02424

https://github.com/chiraggude/awesome-laravel

Intersante

Lazy Size

PRODUCCIÓN

Vamos a subir un proyecto de Laravel en un servidor hosting concretamente fortrabbit, lo malo que tiene dos días de duración. Hay que tener instalado el git y el ssh

php artisan cache:clear //Limpiar el caché de la Aplicación

php artisan route:clear //Limpiar las rutas de la Aplicación.

php artisan config:clear //Limpiar las configuraciones de la Aplicación

php artisan view:clear  //Limpiar las vistas de la Aplicación


En nuestro fichero archivo .env de nuestra aplicación, cambiaremos las valores de:

APP_ENV = production
APP_DEBUG = false


Después de eso nos disponemos a subir el proyecto

cd proyecto

git init

git add -A

git commit -m 'Initial'

git remote add fortrabbit laravel-exey.cej3ggri1ze7ej4q@deploy.eu2.frbit.com:laravel-exey.git  //hay que buscar en la configuración de la página y cambiar el comando git

//git config --global user.email "correo@correo.com"

git push -u fortrabbit master

git push

Ahora vamos a exportar la base de datos

ssh laravel-exey.cej3ggri1ze7ej4q@deploy.eu2.frbit.com   //hay que buscar en la configuración de la página y cambiar el comando con el mysql

php artisan migrate --force