Manual avanzado para Laravel
Crear Una migración desde la consola
Dentro del proyecto ejecutar el comando
php artisan make:migration nombredelamigracion --create=nombredelatabla
Ejecutar las migraciones
El siguiente comando lo que hara sera crear las tablas y relaciones que se hayan especificado en la migracion
php aritsan migrate
Crear un modelo
php artisan make:model Category
Autenticacion
Crear sistema de autenticacion login, registro, reseteo de clave, es una librería externa
php artisan make:auth
Crear controlador
php artisan make:controler nombrecontrolador
Mensaje flash
Es una libreria externa para mostrar mensajes tipo warning, danger, susses.
https://github.com/laracasts/flash
Filtros a tablas
Tutorial de como crear un filtro para las tablas
https://www.youtube.com/watch?v=IcLaNHxGTrs
Ejecutar un solo Seed
php artisan db:seed --class=ProfesionCliente
En el caso de que erroje errores como de que la clase no existe ejecutar
composer update
composer dump-autoload
Usar Model Factories
Los model factories es una apoyo a los seeds, el model factories se encarga de generar un numero de registros aleatorios para un modelo que a su vez se almacenan en la tabla que corresponde al modelo.
La ruta es database/factories/ModelFactory.php
Se crea algo como esto para el modelo usuarios
$factory->define(App\User::class, function (Faker\Generator $faker) { static $password; return [ 'name' => $faker->name, 'email' => $faker->unique()->safeEmail, 'password' => $password ?: $password = bcrypt('secret'), 'remember_token' => str_random(10), ]; });
y ahora para poder ejecutar esto se hace desde un seed que se halla creado. Dentro del sedd se coloca algo como esto:
public function run() { //primero recibe el modelo luego la cantidad factory(App\User::class,20)->create(); }
y listo ahora solo se ejecuta el comando php artisan db:seed para correr los seeds y los registros se debieron haber creado en la base de datos.
Pero tambien se pueden crear de cualquier cosa ya que el model factory tiene varios atributos, por ejemplo el siguiente model factory que lo arme para un modelo y tabla de pagos:
Es decir en el siguiente link que es del repositorio del creador del componente https://github.com/fzaninotto/Faker#fakerprovideren_uscompany se puede encotnrar varios atributos uno simplemente va tomado el atrbiuto que necesite, es como ir a la tienda y armar un combo 😎.
Crear un coomandoPero tambien se pueden crear de cualquier cosa ya que el model factory tiene varios atributos, por ejemplo el siguiente model factory que lo arme para un modelo y tabla de pagos:
$factory->define(App\Pago::class,function(Faker\Generator $faker){ return [ 'tipo_targeta'=>$faker->creditCardType, 'numero_targeta'=>$faker->creditCardNumber, 'color'=>$faker->safeColorName ];
Es decir en el siguiente link que es del repositorio del creador del componente https://github.com/fzaninotto/Faker#fakerprovideren_uscompany se puede encotnrar varios atributos uno simplemente va tomado el atrbiuto que necesite, es como ir a la tienda y armar un combo 😎.
php artisan make:command SendEmails
Obtener modelos de query
para obtener el o los modelos de un query where como por ejemplo
$modelosquequiero = modelo::where('id',2);
Se utiliza el metodo get(); quedando de la siguiente forma
$modelosquequiero = modelo::where('id',2)->get();
Crear API REST
se modifica las rutas en api.php con
Route::resource laravel establece una rutas por defecto
Route::resource('kaseya','SasAdminApi', [
'only'=>['index','store','update']
]);
RUTAS
Expresiones regularesPara tener una mayor seguridad se pueden aplicar expresiones regulares a las rutas para que solo sean accedidas si cumple en patron de Regex.
Para ello se utiliza el metodo where
Route::get('{proveedor}', [ 'uses'=>'Auth\RegisterController@redirectToProvider', 'as'=>'.redirect' ])->where(['proveedor'=>'^(google||facebook||linkedin)$']);
En la anterior ruta solo pueden accer cuando se manda el parámetro de google, facebook o linkedin el resto se daria la excepción NotFoundHttpException
Generar excepciones HTTP
Se puede obligar a generar excepciones http para que el usuario vea el error en el navegador con la función abort().
Utilizándolo de la siguiente manera
abort(400,'memsanej')
El 400 es el codio del error en este caso de pagina no encontrada.
Generar Logs
Los logs son importante a las hora de detectar fallas para su rápida solución.
Los se pueden consultar en storage/log/laravel.log.
Tipos de logs ordenados de mas critico a menos:
Log::emergency($message);
Log::alert($message);
Log::critical($message);
Log::error($message);
Log::warning($message);
Log::notice($message);
Log::info($message);
Log::debug($message);
Vaciar Cache
Ocurren ocasiones en las no aparece un error que todo esta bien, uno revisa linea a linea el código y todo esta al pelo. Pero sigue apareciendo un error esto puede deberse a que el navegador o laravel tiene ese error en cache. Para poder solucionarlo desde laravel se pueden ejecutar los siguientes comandos.
composer dump-autoload
Este comando recomiendo lo usen cuando se realiza algun cambio al .env para que la configuracion de laravel se actualice.
Ahora también se puede ejecutar el comando
php artisan config:cache
Que este comando limpiar los archivos de configuración y vistar que laravel tiene almacenado dentro de la carpeta bootstrap. Recomiendo ejecutar este comando cuando el error es directamente en una vista o controlador.
En ultimas si nada fuciona recomiendo usar el comando
php artisan cache:clear
Y ya en ultima instancia, es maximo que he llegado es ejecutando esta linea dentro de tinker:
Cache::flush();
Scopes o ambitos
Los ámbitos en laravel son simplemente funciones que permiten evitar la repetición de código. En este caso se explicara los ámbitos locales, los cuales se definen en el modelo.
dentro del modelo se define una función, anteponiendo al nombre la palabra scope. Ademas esta función tiene que recibir un parámetros llamado $query.
Digamos que tengo el modelo de usuario y tengo que repetir varias veces un query hacia este mdelo en diferentes partes del proyecto.
Es en este momento donde se puede usar los scopes, si quiero obtener lo usuarios activos el scope quedaria asi:
dentro del modelo se define una función, anteponiendo al nombre la palabra scope. Ademas esta función tiene que recibir un parámetros llamado $query.
Digamos que tengo el modelo de usuario y tengo que repetir varias veces un query hacia este mdelo en diferentes partes del proyecto.
Es en este momento donde se puede usar los scopes, si quiero obtener lo usuarios activos el scope quedaria asi:
public function scopeActivos($query){ return $query->where('state',1); }
Ahora para usar este scope se usa de la siguiente forma.
User::Activos()->get()
Así obtendré todos los usuarios activos
Modelos
Proteger campos
Para proteger campos de nuestro modelo para que no se inserten datos en campos que por ejemplo son auto incrementales o son forenkey se le agrega el siguiente atributo al modelo
protected $guarded = [''];
Simplemente en el arreglo se agregan las columnas que no se van a poder insertar en masa, basicamente es el contrario del fillable , ya que es una lista negra de los capos que no se permiten insertar. Nota: No se puede usa fillable y guarded al mismo tiempo.
En el ejemplo mi modelo se llama producto utilizo withTrashed para que solo obtenga los registros eliminado y luego con find le aplico el filtro pasandole el id del registro a restaurar y por ultimo obiamente el metodo restore
Eliminacion logica
La eliminacion logica consiste solo en cambiar el estado de un registro, estoy es muy util para la persistencia de datos de igual forma es recomendado que los registros de una base de datos nunca se borren.
para implementar la eliminacion logica en laravel se hace de la siguiente manera.
Primero es necesario agregar lo siguiente a la migracion
$table->softDeletes();
luego al modelo se le agrega lo siguiente:
use Illuminate\Database\Eloquent\SoftDeletes;
use SoftDeletes;
y listo básicamente en la tabla del modelo se crea un capo llamado deleted_at entonces si se hace un destroy laravel simplemente lo que ara sera agregar en este campo la fecha de la eliminación.
Ahora para restaurar alguno de estos registros se hace de la siguiente manera.
Product::withTrashed()->find(1)->restore();
Obtener datos viejos
Con la ayuda de laravel podemos auto-rellenar un input de un formulario que ha fallado. Por ejemplo cuando se tienen varios inputs el usuario envia el formulario pero ingresa un dato mal, al pasar esto se debe retornar nuevamente al formulario pero se quiere que los datos que ingreso el usuario asi sean mal ya este llenados en el input, para conseguir ellos se utiliza old
ejemplo
<input name="description" type="text" value="{{ old('username') }}" />
por ultimo en el controlador que redirige nuevamente a la vista es necesario agregar ->withInput(), si antes de llegar al controlador se tiene un validados no es necesario poner nada en el controlador el validados lo hace ademas si se usa laravel Colective no es necesario poner el old.
Ejemplo del controlador
return redirect()->back()->withInput();
Mostrar Errores de campos
Esto es util para los formulacios ya que se muestra el error del campo abajo de este, para ello se usa la variable $errors la cual comprobando si existe el campo es por que existe un error si existe, se obtiene el valor de la primera ocurrencia en el array de errores.
<div class="form-group"> <input type="password" name="password" placeholder="Contraseña..." class="form-control" id="form-password"> @if($errors->has('email')) <strong>{{$errors->first('password')}}</strong> @endif</div>
Requests
Validacion
Si se quiere que solo un requests también sea usado por un rol en especifico a parte de hacerlo con un middelware para ellos se puede usar lo siguiente para ellos en lugar de retornar
/** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return true; }
Se puede usar
public function authorize() { return Auth::users()->rol()->id == 1; }
Lo que solo autoriza el uso del requests para los usuario que tengan el rol 1
Schedule
Estos son las tareas que se puede programas para que laravel por medio de un cron ejecute dichas tareas, es muy util en caso de que queramos que se envien correos a media noche o una fecha en especifico o etc.
El archivo de cron seria algo como esto
* * * * * php /var/www/html/proyecto/artisan schedule:run >> /dev/null 2>&1
Limpiar cache
En ocasiones se necesita acceder a las variables de entorno del archivo .env de laravel pero no se puede acceder a ellas o cuando se accede a ellas retorna un valor nulo, para solucionar ello es necesario ejecutar los siguiente comandos.
php artisan config:clear
php artisan cache:clear
Eventos y listener
El patrón de diseño Observador es implementado en laravel y llamado en el framework como los eventos y listener. Este patron puede se aplicado en el framework a los controladores, a los modelos por ejemplo cuando se crea se actualiza, se elimina etc.
Los modelos ya viene con la funcionalidad para inyectarles observadores gracias al trait HasEvents, este trait permite a cualquier modelo añadirle observadores, inyectarle un observador que se encargue de manejar todos los eventos del modelo, obtener los eventos del modelo, añadirle eventos, y muchas otras cosas mas que si las desean ver el trait esta en la siguiente ruta Illuminate\Database\Eloquent\Concerns\HasEvents.
Para este ejemplo lo que quiero es que el modelo usuario tenga un observador que maneje todos los eventos del modelo, por defecto los modelos tiene los siguientes eventos observables.
Eventos en los modelos
Los modelos ya viene con la funcionalidad para inyectarles observadores gracias al trait HasEvents, este trait permite a cualquier modelo añadirle observadores, inyectarle un observador que se encargue de manejar todos los eventos del modelo, obtener los eventos del modelo, añadirle eventos, y muchas otras cosas mas que si las desean ver el trait esta en la siguiente ruta Illuminate\Database\Eloquent\Concerns\HasEvents.
Para este ejemplo lo que quiero es que el modelo usuario tenga un observador que maneje todos los eventos del modelo, por defecto los modelos tiene los siguientes eventos observables.
[
'retrieved', 'creating', 'created', 'updating',
'updated', 'deleting', 'deleted', 'saving',
'saved', 'restoring', 'restored', ]Sin embargo se le pueden reemplazar los eventos observables o añadir.
Bueno lo primero para mi ejemplo lo que voy a hacer es crearme una clase que contenga esos métodos o los que yo quiera que se ejecute algo.
use App\User; /** * Description of UserModelObserver * * @author Juan Diaz - FuriosoJack <http://blog.furiosojack.com/> */ class UserModelObserver { public function saving(User $user) { dd("hola mundo"); } public function memu() { dd("me mundo"); } }Mi clase se ve algo como esto. Y lo que espero que pase es que cuando el modelo se este guardando se muestre el hola mundo para ello es necesario inyectarle esta clase al modelo.
Por eso nos vamos a EventServiceProvider y en el metodo boot hago algo como esto
\App\User::Observe(\App\Repository\Patterms\Oberver\UserModelObserver::class);
do ahora si en cualquier parte del proyecto ejecuto el metodo save del modelo se dispara el evento saving y por consiguiente el hola mundo.
//Esto dispararia el evento $user = new \App\User(); $user->name = "juan"; $user->save();
El ejemplo anterior funciona con los eventos por defecto, pero que hay si se quiere añadir un evento personalizado al modelo. Para ello como el trait HasEvents hace un array merge con los eventos que tiene por defecto y el atributo observables entonces lo que se puede hacer es sobreescribir el dicho atributo y en formar de array añadir los eventos que queremos que se disparen. Quedando el modelo algo asi
class User extends Authenticatable { use Notifiable; /** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'name', 'email', 'password', ]; protected $observables = ['memu'];Ahora solo hay que disparar el evento, en este caso yo me voy a crear un método en el modelo el cual sera el que dispare el evento quedando asi el el modelo
class User extends Authenticatable { use Notifiable; /** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'name', 'email', 'password', ]; protected $observables = ['meming']; /** * The attributes that should be hidden for arrays. * * @var array */ protected $hidden = [ 'password', 'remember_token', ]; public function memu() { $this->fireModelEvent('meming',false); }entonces si yo ejecuto esto
$user = new \App\User(); $user->memu();Pues se dispara el evento que es un dd("me mundo")
Eventos en los controladores
Lo primero es abrir la clase EventServiceProvider y modificar el atributoprotected $listen
en este atributo aparecerán unos listener por defecto
'App\Events\Event' => [ 'App\Listeners\EventListener', ],
'App\Events\RunIntance' => [ 'App\Listeners\PushNotificationRunIntance', ], 'App\Events\StopIntance' => [ 'App\Listeners\PushNotificationStopIntance', ], 'App\Events\RestartIntance' => [ 'App\Listeners\PushNotificationRestartIntance', ],
Ahora se debe saber que un evento puede tener varios listeners, luego se corre el comando
php artisan even:generate el cual se encargara de generar los eventos y los listeners por consiguiente se crearan dos carpetas en el proyecto
Por ultimo es necesario comenzar a configurar para ellos en mi caso lo primero es configurar el evento, para un evento necesito pasarle un objeto de tipo usuario que a su vez el evento se lo pasara al listener el cual es el encargado de hacer toda la lógica.
Entonces lo primeor es necesaro crear un atributo al evento entonces de la siguiente manera entonces el evento quedaria asi:
<?php namespace App\Events; use Illuminate\Broadcasting\Channel; use Illuminate\Queue\SerializesModels; use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Broadcasting\PresenceChannel; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use App\Instancia; class RunInstance { use Dispatchable, InteractsWithSockets, SerializesModels; /** * Create a new event instance. * * @return void */ public $user; public function __construct(User $user) { $this->user= $user; } /** * Get the channels the event should broadcast on. * * @return Channel|array */ public function broadcastOn() { return new PrivateChannel('channel-name'); } }
Y el listner queda de la siguiente manera
<?php namespace App\Listeners; use App\Events\RunInstance; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Support\Facades\Log; use App\Components\Push; use App\Components\Firebase; class PushNotificationRunInstance { /** * Create the event listener. * * @return void */ public function __construct() { // } /** * Handle the event. * * @param RunIntance $event * @return void */ public function handle(RunInstance $event) { $user = $event->user;
//Aca va la logica
} }
Y en el listener se hace toda la logica necesario ya sea enviar correos etc. Para finalizar solo es necesario poner el evento en el controlador de la siguiente manera
event(new RunInstance($instancia));
Llamar Comandos desde el controlador
Es posible ejecutar un comando que se a hecho con anterioridad para ellos se hace son la siguiente linea
Artisan::call('generate:bills');
Ocultar los atributos de un modelo
Esto es útil cuando se hace una serialización del modelo a formato json y queremos ocultar algunos de los atributos para que no salgan en el json generado, para ello es necesario definir un atributo en el modelo
protected $hidden = ['password'];
En este ejemplo se oculta el atributo password, al ser una arreglo se pueden agregar los otros campos que se quieran ocultar.
https://www.youtube.com/watch?v=iKRLrJXNN4M
https://www.youtube.com/watch?v=iKRLrJXNN4M
Intencion de redireccion
Con el metoo intendent de redirect es posible redireccionar al usuario a la ruta a donde se dirijia antes de que fuera redireccionado a la ruta actual, como cuando usuario se termina su sesion y va hacia las publicaciones pero como ya se termino su sesion es redireccionado a la pagiana de autenticacion cuando este ingresa sus datos y todo es correcto es redireccionado a la pagina a donde se dirijia antes de autenticarse.
if(Auth::guard('alianza')->attemp($credential, $request->get('remember'))){ return reidrect()->intendent(route('alianzas.login.index'));}
Añadir input luego de una redireccion
Esto es util cuando se quire redireccionar un usuario y que la redireccion exista una session donde esten dos atributos que serian los inputs que el usuario ingreso al momentos de hacer la petición del formulario y luego recuperar estos dos campos en la vista si se quiere mostrar.
return reidrect()->back()
->withInput($request->only('email','remember'));