当前位置:网站首页>Read multiple associations from a field using delimiters in laravel

Read multiple associations from a field using delimiters in laravel

2022-06-25 19:16:00 kankan231

In database design , It is often useful to store information separated by commas

In our business scenario , Will design a lot For example, label records for orders or users , One to many relationship between user and tag If you use a single table to maintain label relationships When the actual business scenario is not particularly complex , It seems a little superfluous , At this time, a field is often used to separate the record label or other information with special characters ;

stay laravel In frame , In this scene , If the echo of data is join Or one to many association , It is not suitable for data query, echo and data duplication elimination , If there is a single field , Special associations separated by special characters are good

Below we give a description of the single field , According to the special separator character , Load the associated code implementation

Define a class HasManyFromStr.php


use Illuminate\Database\Eloquent\Builder;

use Illuminate\Database\Eloquent\Collection;

use Illuminate\Database\Eloquent\Model;

use Illuminate\Database\Eloquent\Relations\HasOneOrMany;

class HasManyFromStr extends HasOneOrMany

{

    protected $separator = ',';

    public function __construct(Builder $query, Model $parent, string $foreignKey, string $localKey, $separator)

    {

            parent::__construct($query, $parent, $foreignKey, $localKey);

            $this->separator = $separator;

        }

    /**

        * Get the results of the relationship.

        *

         * @return mixed

    */

    public function getResults()

    {

            return ! is_null($this->getParentKey())

               ? $this->query->get()

                : $this->related->newCollection();

        }

    /**

* Initialize the relation on a set of models.

*

    * @param  array  $models

    * @param  string  $relation

    * @return array

*/

    public function initRelation(array $models, $relation)

{

        foreach ($models as $model) {

            $model->setRelation($relation, $this->related->newCollection());

        }

        return $models;

    }

    /**

    *  Rewrite matching method 

    * @param array      $models

    * @param Collection $results

    * @param string    $relation

    * @return array

*/

    public function match(array $models, Collection $results, $relation)

{

        $dictionary = $this->buildDictionary($results);

        // Once we have the dictionary we can simply spin through the parent models to

// link them up with their children using the keyed dictionary to make the

// matching very convenient and easy work. Then we'll just return them.

        foreach ($models as $model) {

            $keys = $model->getAttribute($this->localKey);

            $keys = explode($this->separator, $keys);

            $keys = array_unique(array_filter($keys));

            $type = 'one';

            $relationResults = [];

            foreach ($keys as $key) {

                if (isset($dictionary[$key])) {

                    $temp = $this->getRelationValue($dictionary, $key, $type);

                    $relationResults[] = $temp;

                }

}

            $model->setRelation(

                $relation, collect($relationResults)

            );

        }

        return $models;

    }

    /**

* Get all of the primary keys for an array of models.

*

    * @param  array  $models

    * @param  string  $key

    * @return array

*/

    protected function getKeys(array $models, $key = null)

{

        $keysArr = [];

        collect($models)->map(function ($value) use ($key, &$keysArr) {

            $result = $key ? $value->getAttribute($key) : $value->getKey();

            $keysArr = array_merge($keysArr, explode(',', $result));

        });

        return collect($keysArr)->values()->filter()->unique()->sort()->all();

    }

}

In the model of the base class , Inherit lavarel Model class , Implement the following methods baseModel.php


/**

* Define a one-to-many relationship From a field with comma or other separator.

*

* @param        $related

* @param null  $foreignKey

* @param null  $localKey

* @param string $separator

* @return HasManyFromStr

*/

public function hasManyFromStr($related, $foreignKey = null, $localKey = null, $separator = ',')

{

    $instance = $this->newRelatedInstance($related);

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

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

    return $this->newHasManyFromStr(

        $instance->newQuery(), $this, $instance->getTable().'.'.$foreignKey, $localKey, $separator

    );

}

/**

* Instantiate a new HasManyFromStr relationship.

*

* @param Builder $query

* @param Model  $parent

* @param        $foreignKey

* @param        $localKey

* @param string  $separator

* @return HasManyFromStr

*/

protected function newHasManyFromStr(Builder $query, Model $parent, $foreignKey, $localKey, $separator = ',')

{

    return new HasManyFromStr($query, $parent, $foreignKey, $localKey, $separator);

}

Actual model classes ( Inherit the above model base class ) in The association of is defined as follows :


public function tagList()

{

    return $this->hasManyFromStr(ErpTagModel::class, 'id', 'tag_id');

}


author :linlancer
link :https://www.jianshu.com/p/882aa5eec382
 

原网站

版权声明
本文为[kankan231]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202190519259590.html