Inicio
NexoPOS

Definir dependencia de modelos

La dependencia del modelo garantiza que un modelo no se pueda eliminar si aún se utiliza como referencia en otro modelo. Por ejemplo, no se puede eliminar un cliente si todavía está asociado a un pedido, y no se puede eliminar un producto si todavía está asociado a un producto de pedido.

Esta función tiende a proteger la integridad de sus datos al exigir la eliminación adecuada de las entradas para evitar entradas huérfanas y ocultas.

Declarando dependencia

La dependencia se crea de forma predeterminada en cada modelo. Usarás la propiedad "setDependencies", donde proporcionarás un array con la clase relacionada como clave y otro array para configurar la configuración. Aquí tienes un ejemplo.

<?php
namespace Modules\YourModules\Models;

use App\Models\NsModel;
use App\Classes\Model;

class Book extends NsModel
{
    public function setDepedencies() {
        return [
            BookChapter::class => Model::dependant(
                local_index: 'id', // the index on Book that will be used as reference
                local_name: 'name', // the attribute that will be used to display the error. e.g "a Storm of Sword cannot be deleted..."
                foreign_index: 'id', // is the relation attribute on the BookChapter class
                foreign_name: 'name', // as for the book, this attribute will be used on the error. e.g "a Storm of Sword cannot be deleted as it's used by Chapter 1"
            )
        ];
    }
}

Usando la tabla relacionada como referencia

A veces, quieres vincular tu dependencia a otra tabla relacionada. Consideremos el siguiente escenario. Tienes una receta que utiliza productos como ingredientes. Aquí tenemos una tabla intermedia que vincula los productos con las tablas de ingredientes de la receta. Por lo general, esa tabla intermedia no tiene ningún atributo “nombre”; por lo tanto, usaremos el nombre de la tabla relacionada.

Aquí tienes una estructura detallada para este ejemplo.

Products
-> name: "Tomato"
-> id: 2

Recipe
->name "Hot Tomato"
->id 1

Ingredient
-> product_id: 2
-> recipe_id: 1

Aquí, necesitamos crear una forma de evitar que se eliminen los productos si se usan como ingredientes, y necesitamos usar el nombre de la receta para mostrar un error como: "El tomate no se puede eliminar porque es una dependencia de Hot Tomato".

<?php
namespace Modules\YourModule\Models;

use App\Models\NsModel;
use App\Classes\Model;

class Product extends NsMoels
{
    public function setDependencies()
    {
        return [
            Ingredient::class => Model::dependant(
                local_name: 'name', // local attribute to be used for the error on the Product table
                foreign_index: 'product_id', // the attribute on the Ingredient table, which is the middleman table
                related: Model::related( // we define the attribute here
                    model: Recipe::class, // we link the related model Recipe
                    local_name: 'name', // the attribute to be used for the error.
                    local_index: 'id', // the foreign attribute on Recipe. The value is by default "id"
                    foreign_index: 'recipe_id', // the local attribute on Ingredient                
                )
            );
        ];
    }
}

Prefijo para el nombre de la dependencia

El error lanzado hasta ahora extrae el nombre de los elementos y lo muestra como si dependiera de él. Sin embargo, quizá quieras dar un contexto a ese nombre. En nuestro ejemplo anterior, ¿no sería mejor si, en lugar de “Hot Tomato”, pudiéramos usar “Recipe: Hot Tomato”? Ahí es donde se usa el “prefijo” en el método relacionado.

Definirás un argumento con nombre «prefix» para una función de devolución de llamada que usa el nombre del modelo dependiente como parámetro. A partir de ahí, puedes devolver cualquier otra cadena localizada usando ese nombre.

Ampliando la dependencia de otros modelos

No estás obligado a proporcionar solo una dependencia para tu modelo, pero puedes proporcionar una dependencia personalizada para otros modelos. Por ejemplo, no se puede eliminar un usuario si todavía tiene un libro que ingresó en el sistema.

Para eso, en nuestro módulo, registraremos esa dependencia de la siguiente manera:

<?php
namespace Modules\YourModule\Providers;

use Illuminate\Support\Provider as CoreProvider;
use App\Classes\Hook;
use App\Classes\Model;
use App\Models\User;
use Modules\YourModule\Models\Book;

class ServiceProvider extends CoreProvider
{
    public function register()
    {
        Hook::filter( User::method( 'setDependencies' ), function( $dependants ) {
            $dependants[ Book::class ]  =   Model::dependant(
                local_index: 'id',
                local_name: 'name',
                foreign_index: 'user_id',
                foreign_name: 'name'
            );
            
            return $dependants;
        });
    }
}