SQLSTATE[HY000]: General error: 1835 Malformed communication packet

laravel error

El error ‘SQLSTATE[HY000]: General error: 1835 Malformed communication packet’, que suele aparecer si nuestra APP en Laravel, trabaja con Maria DB y no soporta la nueva versión del PHP.

Como es un error de configuración, y las nuevas versiones de PHP, son algo mas dúctiles, con la creación de consultas,  debe bastarnos con modificar nuestro archivo database config, añadiendo esta línea de código:

options => [PDO::ATTR_EMULATE_PREPARES => true]

Ojo, esta solución puede tener inconvenientes, pues lo que estamos haciendo es habilitar el uso de declaraciones preparadas en la caché, lo cual puede no ser siempre conveniente.

Lo que hace esta sentencia es hacer el reemplazo de los parámetros  en la librería PDO, en vez de hacerlo en el servidor y así burla la desactualización, por lo que los errores de sintaxis en el tiempo de preparación de la consulta desaparecen, y se traspasan solo al momento de ejecución.

«Quien va en busca de montañas, no puede detenerse a recoger las piedras del camino»

Creando conexiones dinámicas en Laravel

logo laravel

Para crear conexiones dinámicas en Laravel, que varíen en función de nuestras necesidades, tendremos que modificar los valores de los archivos de configuración, que están dentro de la carpeta config.

Los pasos son :

  • Añadimos al archivo .env  las nuevas referencias de valores de conexión.
  • Creamos un tipo de conexión nueva en el archivo que establece nuestra conexión.
  • Creamos una clase que se seteará dinámicamente  los valores.

El archivo .env

Es el encargado de establecer la estructura básica del comportamiento de Laravel para conexiones entre otras cosas.

Aquí añadiremos el marco de las conexiones a la base de datos y al servidor.

DB_CONNECTION_VAR=server_variable
DB_HOST_VAR=  
DB_HOST_VAR=  
DB_PORT_VAR= 
DB_DATABASE_VAR=   
DB_USERNAME_VAR=
DB_PASSWORD_VAR= 
 
FTP_HOST= 
FTP_PASSWORD=  
FTP_USERNAME= 
FTP_PORT= 

El archivo database.

Como sabemos este archivo establece los términos de conexión a la base de datos,  e inicialmente  toma  valores del archivo .env.

Podemos crear en él, tantas conexiones,  como necesitemos, así que lo que haremos será crear una nueva conexión, dentro de database,  que será nuestro conexión dinámica:

'connections' => […….
 'server_variable' => [ 
 'driver' => 'mysql', 
 'url' => env('DB_DATABASE_URL_VAR',''), 
 'host' => env('DB_HOST_VAR', ''), 
 'port' => env('DB_PORT_VAR', ''), 
 'database' => env('DB_DATABASE_VAR','' ), 
 'username' => env('DB_USERNAME_VAR','' ), 
  'password' => env('DB_PASSWORD_VAR','' ), 
   'unix_socket' => env('DB_SOCKET_VAR', ''), 
     'charset' => 'utf8mb4', 
   'collation' => 'utf8mb4_unicode_ci', 
    'prefix' => '', 
  'strict' => false, 
   'engine' => null, 
    ], 
 …………..] 

Lo que haremos ahora  es crear una clase que modifica los valores del archivo config, para poder acceder a ellos de modo dinámico y variarlos en función del tipo de conexión que queremos establecer.

La clase

 ?php 
 namespace App\Personalizado;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Storage;
 use Illuminate\Support\Facades\Config;
  
 class Conexion
 {
          
     public function conectar()
     {
       $hora = date("H.i.s");
       $sitio = DB::table('sitios')->where('hora_deseada','=',$hora)->get();
       
     if ($sitio); 
          {
             $sitio = DB::table('sitios')->where('id')->first();
             $driv='msql';
             $puerto_conex=$sitio->port_conex;
             $database_name=$sitio->nombre_bd;
             $user_name=$sitio->usuario_bd;
             $contra_=$sitio->pass_bd;
             $host_con=$sitio->host_conex;
             $user_FTP=$sitio->user_FTP; 
             $pass_FTP=$sitio->pass_FTP; 
             $port_conex=$sitio->port_conex;

Leer: Buenas practicas de programación en Laravel

Establecemos la ruta de los  archivos database y filesystem, dentro del archivo config, utilizando la convención del punto de Laravel, y seteamos los datos dinámicos tomados de la bd.

 Config::set([
  'database.connections.server_variable.driver'=>$driv,
  'database.connections.server_variable.database'=>$database_name,   'database.connections.server_variable.username'=>$user_name,
  'database.connections.server_variable.password'=>$contra,
  'filesystem.disk.ftp.driver'=> 'ftp',
  'filesystem.disk.ftp.host' => $host_con,
  'filesystem.disk.ftp.username' => $user_FTP,
  'filesystem.disk.ftp.password' => $pass_FTP,
  'filesystem.disk.ftp.port' => $puerto_conex,
  
       ]);

 Solo conectaremos por ahora via ftp_connect  

 $driver = ( Config::get('filesystem.disk.ftp.driver'));
     
       $host = ( Config::get('filesystem.disk.ftp.host'));
       
       $username = ( Config::get('filesystem.disk.ftp.username'));
       
       $password = ( Config::get('filesystem.disk.ftp.password'));
       
       $port = ( Config::get('filesystem.disk.ftp.port'));
      
       $conex = [$driver, $host, $username, $password, $port];
  
       $ftp_conn = ftp_connect($host) or die("no conecta ftp");
   
       if ($ftp_conn){
  
         echo "<br>Conectado";
  
       $login =ftp_login($ftp_conn,$username,$password);
       
       ftp_pasv($ftp_conn, TRUE);
  
       if($login)
         {echo "<br>logeado";
  
       $remote='httpdocs/tienda/import/importacion.csv';
       $local='./storage/app/csv/convertidos.csv';
         if (ftp_put($ftp_conn,$remote,$local, FTP_BINARY))
           { echo "<br>Upload";}
         else
           {echo "<br>not upload";}
  
         }
       else
         {echo "fallo login";}
  
       if(ftp_close($ftp_conn))
         {echo "conexion cerrada";};
    
    } 
    
     return $conex;
    
     }  

Y listo, esto es todo.

Espero modestamente que este artículo, sirva de ayuda a alguien.

Gracias.

….un sueño es casi todo  y más que  nada;  más que todo al soñarlo, casi nada después……

Crear y almacenar clases

laravel

Laravel trabaja con clases que generalmente se guardan en repositorios desde el cual son llamadas. Esta estructura requiere que ademas de conocer la organización del framework, comprendamos su enfoque para crear y almacenar las clases.

Puede parecer para muchos complicado, pero es una estructura que desde mi punto de vista esta enfocada a componentes como parte de un todo, de ahi la necesidad de entenderla adecuadamente

Crear una clase

Las clases en Laravel se crean dentro de la carpeta App, usando psr-4. Basta con crear un archivo en una dirección dentro de App y comenzaremos a tener una clase reconocida, por la aplicación:

Creamos el archivo Conexión dentro de una carpeta nueva llamada Personalizado

  App/Personalizado/Conexión.php 

Y luego colocamos la clase con sus métodos y/o atributos. En nuestro caso estamos creando una clase que sustituirá los valores de conexión a la bd en el archivo env.

 class Conexion
 {
    public function conectar()
    {
         return 'conecto';
 }
 } 

Una vez creado, la clase principal que se encuentra ubicada en “App\Personalizado\Conexion\conexion.php”, tendrá como namespace y que es el que podrá ser usado desde cualquier lugar de la aplicación, o sea hacer bind, este:

 App\Personalizado\conexion 

Para que el bind funcione, son necesarios unos pasos más. Lo siguiente que haremos será crear el Service Provider de la clase.

Lo haremos con Artisan desde la consola:

 php artisan make:provider ConexionServiceProvider 

Lo que sigue es registrar la clase en el método register() del  ConexionServiceProvider, haciendo el adecuado bind.

  public function register()
     {
         //registramos la clase
         \App::bind('Conexion');
     }  

Y finalmente registramos ConexionServiceProvider en el fichero de configuración, que  se encuentra en la ruta config/app.php, agregando la clase, dentro del array de providers:

  /*
          * Application Service Providers...
          */
         App\Providers\AppServiceProvider::class,
         App\Providers\AuthServiceProvider::class,
         …………
          /*
          * Clases Propias añadidas...
          */
         App\Providers\ConexionServiceProvider::class,
   

Nos faltaría comprobar que nuestra clase es accesible, podemos hacer diferentes pruebas, como llamar la clase desde una ruta o correr una prueba con Tinker.

Comencemos con Tinker, llamándolo desde la consola:

  >>>php artisan tinker 

Una vez abierto, llamamos la clase, y la corremos :

  Psy Shell v0.9.12 (PHP 7.2.3 — cli) by Justin Hileman
 >>> use App\Personalizado\Conexion; 

La instanciamos :

 >>> $h =new Conexion();
 => App\Personalizado\Conexion {#3106} 

Y llamamos la funcion:

 >>> $h->conectar();
 => "conecto"
 >>>                         

Salimos de Tinker, con control +C.

Tambien podemos probarlo en el sistema de rutas de Laravel.

 Route::get('conectando', function(){
     if(class_exists('App\Personalizado\Conexion'))
     dd('hallada');
     else dd(' no hallada');
 }
 ); 

Si accedemos ahora a la ruta conectando deberíamos ver escrita la palabra hallada.

Ahora, nuestra clase esta lista y disponible para ser usada.

Y listo, esto es todo.

Espero modestamente que este artículo, sirva de ayuda a alguien.

Gracias.

…., si avanzo sígueme, si me detengo empújame, si retrocedo mátame…….

Crear un comando en Laravel

logo laravel

Crear comandos que nos permiten ejecutar acciones manuales desde la consola,  es una herramienta que necesitamos más comúnmente de lo que parece, por eso crear un comando en Laravel, es una buena opción que agiliza el desarrollo.

Hablo por supuesto desde mi humilde experiencia.

El desarrollo me he exigido que además de las herramientas de testeo, en muchos casos correr directamente comandos de Artisan, para comprobar el funcionamiento en vivo de funciones o métodos construidos, como parte del proceso de creación de una aplicación.

En este ejemplo muestro como crear un comando Artisan,  que va a conectarse a un base de datos y hacer una inserción según un momento determinado en ella.

Llamaremos a nuestro comando importar.

En la consola dentro del root de nuestro proyecto creamos el comando:

 php artisan make:command Importar 

Como crear un componente en Laravel

Esto creará nuestro comando, si vamos ahora a la ruta

app/Console/Commands/importar.php, 

el archivo Commands, que se crea al correr

make:command 

tendrá dentro los datos del comando creado.Dentro del comando hay varias zonas importantes:

La primera es la  variable  $signature, que es donde daremos el nombre con que llamaremos al comando en la consola

  protected $signature = 'importar'; 

La  segunda es la variable descripción, allí escribiremos la descripción de la razon de ser del comando que aparecerá cuando listemos los comandos de Artisan

protected $description = 'Insertar productos en la Base de datos';

La tercera zona importante es la función handle en la cual desarrollaremos la lógica.

   public function handle()
     {//

    $archivos =  \Storage::disk('listos')->files(); 
    $ultimo =  end($archivos);
    $contenido_Exp = \Storage::disk('listos')->get($ultimo);

    $contenido_Exp = json_decode($contenido_Exp);
    //dd($contenido_Exp[2]->codigo);
                   /* 
                    ->get(); */
    //dd($archivo);


    function hora_exportar($sitio, $hora)
    {
      $hora = date("H.i.s");
      $hora_deseada  = DB::table('sitios')->hora_deseada;
      if ($hora === $hora_deseada){
        $sitio = DB::table('sitios')->nombre;
        $host = DB::table('sitios')->host_conex;
        $username = DB::table('sitios')->usuario_bd;
        $passwd = DB::table('sitios')->pass_bd;
        $dbname = DB::table('sitios')->nombre_bd; 
      }

     }


    /*
    $host ="154.53….";
    $username =  "admin_bd ";
    $passwd= "Hlnv68?";
    $dbname= "bd_pt";*/


   // $consulta = ;
    $enlace = mysqli_connect($host,$username,$passwd,$dbname);
  /*  if ($mysqli_ping($enlace)){
        printf("conexion bien");
    }
    else{ printf("error de conexion");}
    mysqli_close($enlace);*/
    if(!$enlace){
        echo "Error no se pudo conectar".PHP_EOL;
        echo "Errno de depuracion:".msqli_connect_errno().PHP_EOL;
        echo "Errno de depuracion:".msqli_connect_error().PHP_EOL;
        exit;
    }
    echo "realizada conexion exitosa".PHP_EOL;
    echo "info del host:".msqli_get_host($enlace).PHP_EOL;
    mysqli_close($enlace);


   //insertamos en nuestra bd los datos de la ultima exportacion  
  $insertar_exportacion = DB::table('importaciones')->insert([
              'users_id' => 1,
              'estados_id' => '3',
              'proveedores_id' =>'1',
              'sitios_id' => $ultimo,
              'url_archivo'  => $url,
              'nombre_archivo'  => $url,
              'tipo_archivo'  =>$tipo,
              'tamaño'  =>'1',

             ]);
}

En nuestro ejemplo tenemos una columna en la bd llamada hora deseada, que compareremos con la hora actual del servidor, si el valor es igual  ejecutaremos la consulta.

El ultimo paso para que el comando funcione es declararlo en el  archivo kernel.php dentro de la ruta App/Console, dentro de los comandos protegidos

protected $commands = [
     //     Commands\Importar::class, ]; 

Y en la función Schedule, tenemos la opción de configurar la ejecución  su ejecución periódicamente,  podríamos también colocar una  tarea en el servidor de llamar esta función, a una hora especifica,  en nuestro caso la colocaremos aquí diaria.  

protected function schedule(Schedule $schedule)
     {
          $schedule->command('Importar')
                 ->daily();
     }

Esto es todo, no obstante debemos decir que la recomendación de  Laravel es que los comandos sean ligeros para no cargar demasiado la ejecución del sistema en si y como una buena  práctica de programación.

La mejor opción es aprovechar la reusabilidad, y utilizar ese mismo código dentro de un controlador,  ejecutándolo de  modo periódico, y así dejar la ejecución del comando solo para tareas manuales.

Y listo, esto es todo.

Espero modestamente que este artículo, sirva de ayuda a alguien.

Gracias.

…todo lo que se contiene,  termina  desbordándose……

Creando un componente en Laravel

laravel

¿Que necesidad hay de andar creando un componente en Laravel?

Laravel es un framework basado en componentes y esta es una  de sus características y quizás la mas importante de todas,   que lo hace tan útil, sencillo y potente a la vez.

Los componentes dicho de forma rápida son un conjunto de funciones, scripts  y/u otros elementos que pueden  que crean una funcionalidad y que son reusables.

Piensa en una pieza de ropa  o un accesorio femenino que puedes combinar(usar), con varias otras prendas, sin que pierda funcionalidad, y para diferentes ocasiones y tantas veces como quieras.

Hay diferentes tipos de componentes, voy a centrarme hoy en construir uno en Blade el gestor de plantillas Blade

Un componente en Blade,  cumple la misma función que la combinación entre las directrices section y layouts, por tanto es una alternativa a esta, digamos más moderna.

Consta de dos variables, el component y el slot. Mientras que el component es la estructura general,  slot es la parte dinámica  que inyectaremos en el.

Crear un componente

El primer paso para crear un componente Blade, considerando que va a estar relacionado con las vistas, es colocarlo dentro del área que tiene que ver con las capas(layouts) de las vistas, así que en la ruta resources/views/layouts, creamos una carpeta llamada componentes.

Luego crearemos un  archivo, que contendrá la lógica del componente.

El compenente, que vamos a construir, va a llamarse curric_autor, y se encargará de mostrar  una pequeña nota al final de cada articulo que publiquemos en nuestro blog.

Estará colocado a la izquierda de la página, e incluirá la  foto del autor y un pequeño texto  con su descripción.

 A este archivo lo nombraremos curric_autor.php y lo  guardaremos en la carpeta componentes que hemos creado.

El próximo paso es escribir nuestro código, el cual podría ser este:

 <divclass = flex-row comd-6>
 <div class=d- flexjustify-content-end col-md-9>
 <spanclass= text-justify> Amante del codigo, y de las mascotas  con garras.</span>
 <divclass="text-center col-md-3">
<imgsrc="..."class="rounded"alt="...">
</div>
</div>
</div> 

Una vez creado el componente podemos usarlo de diferente modo:

Podemos llamarlos desde nuestra vista e inyectarlo  en la vista siguiendo las directivas @ de Blade.

  @component('layouts.components.curric_autor')
 @endcomponent 

Con esto será suficiente, pero ¿que sucede si en el blog publica más de un autor y por tanto los datos que usamos necesitan ser extraidos dinámicamente de la base de datos?

Tendríamos entonces que añadir en el código del componente  variables necesarias para  que recojan esta dinámica, y lo haríamos  con $autor que representará al modelo autor que posee varios atributos, lema, avatar_alt y avatar, y para añadirlos seria asi:

  <div class = flex-row col-md-6  >
 <div class=d- flexjustify-content-end col-md-9>
 <spanclass= text-justify> {{$autor->lema}}.</span>
 <divclass="text-center col-md-3">
<imgsrc="{{$autor->avatar}}..."class="rounded"alt=" {{$autor->avatar_alt}}">
</div>
</div>
</div> 

Una alternativa es que no extraigamos valores de la base de datos y solo necesitemos introducir variables que llevan valores estaticos.

 <div class = flex-row col-md-6  >
 <div class=d- flexjustify-content-end col-md-9>
 <spanclass= text-justify> {{$autor}}.</span>
 <divclass="text-center col-md-3">
<imgsrc="{{$avatar}}..."class="rounded"alt=" {{$avatar_alt}}">
</div>
</div>
</div>
  

Llamar al componente

Ahora al llamar el componente desde la vista añadiríamos la directiva slot que es la encargada de traernos el valor de esas variables.

 @component('layouts.components.navbar')
 @slot('autor')
 colocamos aquí el valor 
 @endslot
 @slot('avatar')
 colocamos aquí el valor 
 @endslot
 @endcomponent
 @slot('avatar_alt')
 colocamos aquí el valor 
 @endslot 

Esto pudiéramos hacerlo también de otro modo, gracias a la ductilidad de Laravel. Esta via por cierto es un poco más robusta.
Para ello declararemos, nuestro componente en el proveedor de servicios de Laravel, en su función boot()

Leer mas sobre Laravel

Antes de hacer esto debemos decirle al proveedor de servicios que vamos a usar una instancia de la fachada Blade, asi que tendremos que incluir al inicio la sentencia.

 use Illuminate\Support\Facades\Blade;

//Luego podemos ya incluir en la función boot, lo siguiente:

 Blade::component('layouts.components.curric_autor,'autor'); 

Con esto le estamos diciendo a Laravel primero donde se encuentra el componente, y segundo nombre que utulizaremos para llamarlo, entendemos entonces que la  estructura es:

(ruta o namespace del componente, alias del componente)

Entonces, ahora podremos llamar al componente, desde cualquier lugar con la directriz @y su alias, en nuestro caso será:

@autor

Quedando el modo de llamar a nuestro componente como:

@autor(['autor'=>'valor', 'avatar'=>'valor', 'avatar_alt'=>'valor',]) @endautor

Y listo, esto es todo.

Espero modestamente que este artículo, sirva de ayuda a alguien.

Gracias.

….un sueño es casi todo  y más que  nada, más que todo al soñarlo, casi nada después……

Hacer override del update_at con save

laravel

El método save(), acepta parámetros, ello da la capacidad para decirle que ignore el la asignación que hace update_at por defecto, tomando la fecha y momento actual, haciendo esto, lo cual nos permite hacer override del update_at con save(), sin mayores problemas:

$product = Product::find($id);	
$product->updated_at = '2019-01-01 10:00:00';
$product->save(['timestamps' => false]);

Y listo, esto es todo.

Otros artículos sobre Laravel

Espero modestamente que este artículo, sirva de ayuda a alguien.

Gracias.

Subir montañas hermana hombres……

El uso de when

laravel

When() es una de los métodos con los que Laravel, sorprende a los que comienzan. El uso de when, es un recurso al que recurro cada vez que puedo, por la potencia que aporta, ya que permite crear un código más reusable.    

Veamos por ejemplo que si queremos introducir una condicional del tipo if else,  en un código podemos escribir algo asi enlazando ifs:

En el primer caso estamos diciendo algo como esto: Si filtramos lo que trae el request, por la columna likes, el valor de la variable query acogerá,    aquellos registros  en que likes, sea mayor que el valor de request donde likes_amount sea 0

if (request('filter_by') == 'likes') {
    $query->where('likes', '>', request('likes_amount', 0));
}
if (request('filter_by') == 'date') {
    $query->orderBy('created_at', request('ordering_rule', 'desc'));
}

Leer otros artículos sobre Laravel

Aquí estamos enlazando dos condiciones, que consideran el valor de unos campos para decidir que hacer.
Si usaramos when lo escribiríamos asi:

$query = Author::query();
$query->when(request('filter_by') == 'likes', function ($q) {
    return $q->where('likes', '>', request('likes_amount', 0));
});

$query->when(request('filter_by') == 'date', function ($q) {
    return $q->orderBy('created_at', request('ordering_rule', 'desc'));
});

Y lo que estamos diciendo es que la variable query, aplicará al modelo Author el método query, y que cuando el valor ejecute el filter_by a la columna likes dentro del metodo request, la función anónima se le pasara como parámetro una variable $q cuyo valor seran aquellos registros donde likes sea mayor que la likes_amount igual 0

Como vemos $q es una variable comodin que soporta el peso de la función, pues su valor variara en función del resultado.

$query = Producto::query();
$query->when(request('marca', false), function ($q, $marca) { 
    return $q->where('marcas_id', $marca);
});
$store = $query->get();

Y listo, esto es todo.

Espero modestamente que este artículo, sirva de ayuda a alguien.

Gracias.

Subir montañas hermana hombres……

Metodos Raw

laravel

Para añadir consultas tipo Raw  en Eloquent, contamos con algunos métodos muy útiles. Aquí muestro  ejemplos con tres  metodos Raw ( whereRaw, havinRaw y orderByRaw)

 // whereRaw
$orders = DB::table('orders')
    ->whereRaw('price > IF(state = "TX", ?, 100)', [200])
    ->get();

// havingRaw
Product::groupBy('category_id')->havingRaw('COUNT(*) > 1')->get();

// orderByRaw
User::where('created_at', '>', '2016-01-01')
  ->orderByRaw('(updated_at - created_at) desc')
  ->get();

Y listo, esto es todo.

Más sobre Laravel en mi blog

Espero modestamente que este artículo, sirva de ayuda a alguien.

Gracias.

Subir montañas hermana hombres……

Relaciones en Laravel

laravel

Establecer y definir correctamente las relaciones en Laravel cuando construimos una APP, es uno de los pasos más importantes para lograr una solución solida y escalable.

Las relaciones que se dan entre los modelos son la base de todo lo que haremos después.

Laravel aporta una estructura sencilla para construir sus modelos y relaciones, dentro del mundo de Eloquent, el cual aporta un conjunto de convenciones, que en esencia son estas

Convenciones de Eloquent Model

Los nombres de la tablas se escriben en minúsculas, corresponderán con el nombre del modelo y se le agrega una  s, y   si el modelo   tiene un nombre compuesto por dos palabras, la s se añade al final de todo, separando las palabras con una guion bajo.

De este modo , la tabla del modelo Cliente sería clientes y la de ClienteLike sería cliente_likes.
El campo primary key de una tabla debe tener el nombre de id, con el atributo AUTO_INCREMENT, en laravel 5 o bigIncrements en Laravel 6.

Los modelos son clases extienden de la clase Model, un modelo al ser creado tiene esta estructura

 <?php namespace App; use Illuminate\Database\Eloquent\Model; class NombreModelo extends Model {     // } 

Es aquí donde definiremos las relaciones y estructura del modelo, esto incluye la tabla a que se refiere, los campos que deberán ser llenados dentro de su tabla, y los cambios que queramos hacer en la estructura de la tabla que corresponde al modelo.

Otros Posts sobre Laravel

Las convenciones no son inviolables, sino una guía de organizar el código y su legibilidad pero pueden cambiarse todo lo que se desee dentro del modelo.  Por ejemplo un modelo Productos variado puede quedar así

class Producto extends Model
 {
     // cambiamos el nombre de la tabla que controla el modelo en vez de productos, trabajara con mercancia
     protected $table = 'mercancia';
 // cambiamos la clave primaria, que por defecto es id pero usaremos el código ean definiendo ese campo en la propiedad  primaryKey protected $primaryKey = 'ean_code'; // Anulamos los valores por defecto de los campos  timestamp que Laravel crea automáticamente en cada tabla, cambiando su valor a false public $timestamps = false; // asignamos  un nombre de conexión diferente protected $connection = 'connection-name'; // Establecemos aquellos atributos  a los que se les pueden asignar valores protected $fillable = ['name',’fabricante’]; // Definimos en la variable guarded, los atributos que no pueden se asignados protected $guarded = ['price',’expire_date’];
 }
 <?php namespace App; use Illuminate\Database\Eloquent\Model; class Producto extends Model {     // cambiamos el nombre de la tabla que controla el modelo en vez de  productos, trabajara con mercancia     protected $table = 'mercancia';       // cambiamos la clave primaria, que por defecto es id pero usaremos  el código ean definiendo ese campo en la propiedad  primaryKey     protected $primaryKey = 'ean_code';       // Anulamos los valores por defecto de los campos  timestamp que  Laravel crea automáticamente en cada tabla, cambiando su valor a false     public $timestamps = false;       // asignamos  un nombre de conexión diferente     protected $connection = 'connection-name';       // Establecemos aquellos atributos  a los que se les pueden asignar  valores     protected $fillable = ['name',’fabricante’];       // Definimos en la variable guarded, los atributos que no pueden se  asignados     protected $guarded = ['price',’expire_date’]; } 

Las relaciones pueden ser de uno a uno, de uno  a muchos o de muchos a muchos, hay suficiente información sobre esto en la red, muy bien explicado, pero en esencia en una aplicación donde un cliente, con un buzón de correos individual,  tendrá más de un rol, y habrá varios usuarios de la misma empresa, los modelos quedarían relacionados así.

Un cliente  con un buzón de correo (de uno a uno), pertenece solo a una empresa (de uno a uno) y un cliente tiene varios roles(relación de uno a muchos)

Como puede verse las relaciones son bilaterales, por tanto la inversa es que entre buzon y cliente también es de uno a uno, entre empresa    y clientes hay una relación de muchos a  uno  y entre roles y cliente también de uno a varios.

Cuando en ambos lados la relación es de uno a muchos,  se considera una relación de muchos a muchos y debe crearse una tabla pivote que acoja solo aquellos valores de ambos modelos que no son coincidentes y que será la tabla objeto de las consultas.

Si a las relaciones son de uno a muchos de  un lado y de uno a uno en el otro, es una relación de general de uno a muchos y si ambos lados son de uno a uno, pues asi queda de uno a uno.

Uno a Uno

Ejemplo Cliente y Buzón están relacionados uno a uno

namespace App;
use Illuminate\Database\Eloquent\Model;
class Cliente extends Model
{
public function buzon()
{
return $this->hasOne('App\Buzon');
// Si el id tiene un nombre diferente al que corresponde por convención buzons_id lo especificamos
return $this->hasOne('App\Buzon', 'code_id', 'local_key');
}
}

Definimos la otra clase

namespace App;
use Illuminate\Database\Eloquent\Model;
class Dni extends Model
{
public function cliente()
{
return $this->belongsTo('App\Cliente');
// Si el id tiene un nombre diferente al que corresponde por convención clientes_id lo especificamos
return $this->belongsTo('App\Cliente', 'nombre_id', 'local_key');
}
}

Uno a Muchos

En esta caso la definición es prácticamente igual

Una Empresa tiene muchos Clientes

namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
public function clientes()
{
return $this->hasMany('App\Cliente');
// Si el id tiene un nombre diferente al que corresponde por convención clientes_id lo especificamos
return $this->hasMany('App\Cliente', 'name_id', 'local_key'); }
}

Un Cliente pertenece a una Empresa

namespace App;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
public function empresa() { return $this->belongsTo('App\Empresa'); }
}

Muchos a Muchos

Un Cliente tiene varios Roles

namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function roles() { return $this->belongsToMany('App\Role');
// Si el nombre de la tabla es diferente a lo predeterminado o el ID de la tabla tiene otro nombre.
return $this->belongsToMany('App\Role', 'cliente_roles', 'name_id', 'defin_id');
}
}

Un Rol tiene varios Clientes

namespace App;
use Illuminate\Database\Eloquent\Model;
class Role extends Model
{
public function clientes() { return $this->belongsToMany('App\Cliente');
// Si el nombre de la tabla es diferente a lo predeterminado o el ID de la tabla tiene otro nombre.
return $this->belongsToMany('App\User', 'cliente_roles', 'defin_id', 'name_id');
}
}

Aquí debemos crear una tabla intermedia, con el nombre cliente_roles, de las cual será donde obtengamos los datos. La idea básica es que esta tabla tendrá los id de las tablas que la conforman y otros campos que sean interesantes tener para nuestra aplicación

Definimos en la función withPivot los campos de la tabla intermedia, y el acceso a ellos.

namespace App;
use Illuminate\Database\Eloquent\Model;
class Cliente extends Model
{
public function roles()
{
return $this->belongsToMany('App\Role', 'cliente_roles')
->withPivot('create', 'read','update', 'delete');
}
}

Y para acceder  a los datos intermediamos la palabra pivot en la solicitud/orden  que hacemos. 

$user = App\Cliente::find(1);
foreach ($cliente->roles as $role) {
    echo $role->pivot->create;
}

Ademas podemos acceder directamente a las tablas para obtener diferentes resultados

// retorna App\Buzon
App\Cliente::first()->buzon;

Nos devolverá valores del modelo Buzon

// retorna Illuminate\Database\Eloquent\Relations\BelongsToMany
App\Cliente::first()->roles();

Nos devolverá valores del modelo Role, de acuerdo a su relación con el modelo cliente

// retorna Illuminate\Database\Eloquent\Collection
App\Cliente::first()->roles;
Nos devolverá una colección 

Y listo, esto es todo.

Espero modestamente que este artículo, sirva de ayuda a alguien.

Gracias.

…., si avanzo sígueme, si me detengo empújame, si retrocedo mátame…….

Translate »