eloquent-versioning icon indicating copy to clipboard operation
eloquent-versioning copied to clipboard

Overwrite `qualifyColumn` model method in order to make some relationship work on versioned model

Open Mortred974 opened this issue 6 years ago • 0 comments

Hi guys !

Inspired by #17 , i try this in order to make some relationships work :

App\Custom\ProAI\Versioning\Versionable.php

<?php
namespace App\Custom\ProAI\Versioning;

use Illuminate\Support\Str;
use ProAI\Versioning\Versionable as BaseVersionable;

/**
 * Trait Versionable
 *
 * @package App\Custom\ProAI\Versioning
 */
trait Versionable
{
    use BaseVersionable;
    use HasVersionedRelationships;

    /**
     * Qualify the given column name by the model's table.
     *
     * @see \Illuminate\Database\Eloquent\Model::qualifyColumn()
     *
     * @param  string  $column
     *
     * @return string
     */
    public function qualifyColumn($column)
    {
        if (Str::contains($column, '.')) {
            return $column;
        }

        $table = (isset($this->versioned) && in_array($column, $this->versioned)) ? $this->getVersionTable() : $this->getTable();

        return "{$table}.{$column}";
    }

}

App\Custom\ProAI\Versioning\HasVersionedRelationships.php

<?php

namespace App\Custom\ProAI\Versioning;

/**
 * Trait HasVersionedRelationships
 *
 * @package App\Custom\ProAI\Versioning
 * @mixin \Illuminate\Database\Eloquent\Model
 * @mixin \ProAI\Versioning\Versionable
 */
trait HasVersionedRelationships
{
    /**
     * Define a one-to-one relationship.
     *
     * @see \Illuminate\Database\Eloquent\Concerns\HasRelationships::hasOne()
     *
     * @param  string $related
     * @param  string $foreignKey
     * @param  string $localKey
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function hasOneVersioned($related, $foreignKey = null, $localKey = null)
    {
        $instance = $this->newRelatedInstance($related);

        $foreignKey = $foreignKey ?: $this->getForeignKey();

        $localKey = $localKey ?: $this->getKeyName();

        return $this->newHasOne($instance->newQuery(), $this, $instance->qualifyColumn($foreignKey), $localKey);
    }

    /**
     * Define a one-to-many relationship.
     *
     * @see \Illuminate\Database\Eloquent\Concerns\HasRelationships::hasMany()
     *
     * @param  string  $related
     * @param  string  $foreignKey
     * @param  string  $localKey
     * 
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function hasManyVersioned($related, $foreignKey = null, $localKey = null)
    {
        $instance = $this->newRelatedInstance($related);

        $foreignKey = $foreignKey ?: $this->getForeignKey();

        $localKey = $localKey ?: $this->getKeyName();

        return $this->newHasMany(
            $instance->newQuery(), $this, $instance->qualifyColumn($foreignKey), $localKey
        );
    }

}

In fact, i need to overwrite the qualifyColumn in order to make whereHas function from builder work when i have a versioned foreign key (and make belongsTo relationship work).

I can understand that overwrite a model method can't be the best solution, but if we're already overwriting the method getQualifiedDeletedAtColumn() in the SoftDeletes trait, i think we can do it.

That fix make the SoftDeletes trait useless and allow us to write less code in model.

What do you think about it ?

Mortred974 avatar Sep 10 '18 10:09 Mortred974