NF2 - Framework Laravel

De wikiserver
Dreceres ràpides: navegació, cerca

ESTRUCTURA DIRECTORIOS

=RUTAS BÁSICAS

Dentro de Routers->Web

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

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";

}


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

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


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

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


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


Route::get('user/{name?}', function ($name = 'John') {  //$name=null
    return $name;
});

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]+');

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.


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

    return "modifica usuario";

    });


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

    return "insertar usuario";

    });

});

RELACIONES

Se deben de hacer las relaciones de la base de datos en las migraciones y también en los modelos para facilitar a Eloquent las consultas.

Relaciones Uno a Muchos Migraciones

un usuario tiene muchos post y un post lo tiene un usuario

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

//tabla Posts


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


Para las relaciones NxM Muchos a Muchos. Un post puede tener muchas Etiquetas y una etiqueta puede tener muchos Posts, por tanto habrá que crear una tabla auxiliar.

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

           // $table->integer('user_id')->unsigned();
           // $table->integer('category_id')->unsigned();
            
            $table->string('name',128)->unique();
            $table->string('slug',128)->unique();

            $table->mediumText('excerpt')->nullable();
            $table->text('body');
            $table->enum('status',['PUBLISHED','DRAFT'])->default('DRAFT');

            $table->string('file', 128)->nullable();

            $table->timestamps();

            //relaciones
            //$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade');
            //$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade')->onUpdate('cascade');

        });

//tabla Tags

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

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

            $table->timestamps();
        });


//tabla auxiliar

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

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

            $table->timestamps();

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


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();
});

Generas las rutas insertando el fichero Web

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

//Para listar las rutas, en terminal 

php artisan route:list -v

Creamos el modelo

php artisan make:model Blog

//dentro del modelo 
class Blog extends Model
{
protected $fillable = ['blog_title', 'blog_content'];

//¿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.
}

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/

//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.

protected $fillable = ['nombre', 'descripcion'];

añadimos las rutas
public function index(){

    $datos=Dato::all();

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

//en la vista
@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


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())
    <ul>
        @foreach ($errors->all() as $error)
        <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" />
    </div>
    <div>
        <label for="price">Descripcion:</label>
        <input type="text" name="descripcion" />
    </div>

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


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 de 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>

//hacer el actualizar

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

         $validacion=$request->validate([
        '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();
        
        
        // Dato::whereId($id)->update($validacion); //otra opción

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

//$request->input() es un array


//en el controlador borrar

    public function borrar($id){

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


//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');


//PAGINAR

en controlador de index
        $datos=Dato::latest()->paginate(3);
y en vista debajo de forelse 

{{$datos->links()}}


//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>


//obtener datos.

use app\Dato; 

$datos=Dato::get();
$datos=Dato::orderBy('nombre','DESC')->get();
$datos=Dato::latest('created_at')->get();   //muestra los últimos que se han añadido


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
}


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

AUTENTIFICACIÓN Crear usuario en versiones anteriores a 6

php artisan make:auth

Laravel 6

composer require laravel/ui

php artisan ui vue --auth

Después podremos ver que en las rutas Web ha creado Auth::routes();

Dentro app->http->Auth cambiamos las rutas de register y login cambiando ruta a /

Quitamos la ruta /home dentro de las rutas en web

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


@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.

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

 <form id="logout-form" action="Plantilla:Route('logout')" method="POST" style="display: none;">
   Plantilla:Csrf field()
 </form>

@endguest

//deshabilitar registro , vamos a Web y modificamos ruta

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

para saber si está logeado en el Controlador

use Illuminate\Support\Facades\Auth;

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

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- 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:

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
public __construct(){
  $this->middleware('auth')->only('create', 'edit'); //y con esto especificamos que redirija a login en caso de entrar a create y no está logeado.
//  $this->middleware('auth')->except('create', 'edit');  // lo contrario, bloquea a todos los metodos/controladores excepto el create y edit que podrán acceder.
}


ELOQUENT

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

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


//insertar
        $escritor = Escritor::find(1);  //$escritor = App/Escritor::find(1);
        $escritor->nombre = 'Pepe';     //$request->name;
        $escritor->save();
//borrar
        $escritor= App\Escritor::find(1);
        $escritor->delete();


//Toda la info de escritor
$escritor = Escritor::find(1);
$escritor->articulo()->get();


//Muestra todos los articulos del escritor 1.
$escritor = Escritor::find(1);
foreach ($escritor->articulo as $articulo) {
   dump($articulo);
 }


//el artículo 1 devuelve quién es su escritor
$articulos = Articulo::find(1);
dump($articulos->escritor->nombre);


//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
$articulos = Articulo::all();
foreach ($articulos as $articulo) {
    echo $articulo->escritor->nombre;
 }


//al usar la carga previa para reducir esta operación a solo 2 consultas
 $articulos = Articulo::with('escritor')->get();
       foreach ($articulos as $articulo) {
           echo $articulo->escritor->nombre ."</br>";
        }