Laravel soft delete in pivot tables

0

I have a m-n relationship between two tables using a pivot table. In the migration of the pivot table, I created it with a deleted_at field, using the softDeletes() method, like this:

public function up()
{
    Schema::create('customer_store', function (Blueprint $table) {
        $table->increments('id');
        /** Satisfacción */
        $table->char('satisfaccion', 1)->nullable();
        /** Los campos de fechas */
        $table->timestamps();
        $table->softDeletes();
        /** La definición de los campos que se usarán como claves foráneas */
        $table->integer('customer_id')->unsigned();
        $table->integer('store_id')->unsigned();
        /** La declaración de las claves foráneas en los campos necesarios. */
        $table->foreign('customer_id')->references('id')->on('customers');
        $table->foreign('store_id')->references('id')->on('stores');
    });
}

Also, as you can see, I've also added a field called satisfaccion . The goal is for the same relationship to include data that is inherent in that relationship.

The point is that when the elements are disassociated (customers and stores), I do not want the relationship to be deleted, as it must remain historical, due to traceability issues. However, the detach() method does not look for a deleted_at field. Eliminate the relationship for good. Is there a specific method for relationships to be marked in the deleted_at field, or would I have to manually program it using the pivot table model?

And then the most important thing. When it comes to obtaining a list of customers related to a store, how can I decide if I want to see all the relationships, or only those that are active (that have null in deleted_at )?

    
asked by Chefito 29.12.2018 в 14:31
source

2 answers

1

The pivot tables in Laravel (and in the databases in general) are nothing more than the representation of relationships, and they do not have a primary key (or at least they should not have it), because if they did, they would be a model and they would have "a life of their own," like the other models.

Being totally dependent on the models, they can not have the same functionalities and / or characteristics of these, and in Laravel is well supported, in this case there would be a "correct" way to find the relationship.

In terms of code we find it in the SoftDeletes trait, where it is observed that a primary key is needed to perform the soft delete, therefore an instance of the model:

/**
 * Perform the actual delete query on this model instance.
 *
 * @return void
 */
protected function runSoftDelete()
{
    $query = $this->newModelQuery()->where($this->getKeyName(), $this->getKey());

    $time = $this->freshTimestamp();

    $columns = [$this->getDeletedAtColumn() => $this->fromDateTime($time)];

    $this->{$this->getDeletedAtColumn()} = $time;

    if ($this->timestamps && ! is_null($this->getUpdatedAtColumn())) {
        $this->{$this->getUpdatedAtColumn()} = $time;

        $columns[$this->getUpdatedAtColumn()] = $this->fromDateTime($time);
    }

    $query->update($columns);
}

There are many proposed solutions for this, from playing to add the trait softdeletes in certain parts to pretend to use the Laravel methods, to packages developed exclusively for this purpose.

In my opinion, one of the most interesting solutions is to take advantage of the eager load for this purpose when defining the relationship:

public function stores()
{
    return $this->belongsToMany('Store')
        ->whereNull('customer_store.deleted_at')
        ->withTimestamps();

}

The soft delete would be done like this:

DB::table('customer_store')
->where('customer_id', $customer_id)
->where('store_id', $srote_id)
->update(['deleted_at' => now()]);

And as for the second answer, the solution was also raised implicitly above, although it can be done in other ways as well.

    
answered by 31.12.2018 / 06:22
source
0

After doing several tests, and googling a few hours, I see that the pivot tables are, exactly, that: hinges between two or more foreign keys. Additional data must be stored in other tables designed for that purpose, not in the pivot tables. It has cost me, but I understood that my approach was wrong, and that limits the benefits of Laravel and Eloquent, making some methods not work as expected. Once the content is separated into the necessary models, everything works to order by mouth, following the documentation and the manuals that there are. I put these comments so that if some other rookie in Laravel (like myself) has the same idea, I know not, that the pivot tables are not the yellow ointment.

    
answered by 30.12.2018 в 11:48