sql >> データベース >  >> RDS >> Mysql

MySQLのネストされたリソース(ピボットテーブル)の表示/更新/管理の権限

    与えられたモデルが別のモデルに関連しているかどうかを確認するために必要なのは、Eloquentを最大限に活用するこの小さなメソッドだけです。 :

    BaseModelに実装します 、Entity またはスコープ、あなたに合ったものは何でも)

    // usage
    $task->isRelatedTo('transactions.users', $id);
    // or
    $template->isRelatedTo('tasks.transactions.users', Auth::user());
    
    // or any kind of relation:
    // imagine this: User m-m Transaction 1-m Item m-1 Group
    $group->isRelatedTo('items.transaction.users', $id);
    

    魔法はここで起こります:

    /**
     * Check if it is related to any given model through dot nested relations
     * 
     * @param  string  $relations
     * @param  int|\Illuminate\Database\Eloquent\Model  $id
     * @return boolean
     */
    public function isRelatedTo($relations, $id)
    {
        $relations = explode('.', $relations);
    
        if ($id instanceof Model)
        {
            $related = $id;
            $id = $related->getKey();
        }
        else
        {
            $related = $this->getNestedRelated($relations);
        }
    
        // recursive closure
        $callback = function ($q) use (&$callback, &$relations, $related, $id) 
        {
            if (count($relations))
            {
                $q->whereHas(array_shift($relations), $callback);
            }
            else
            {
                $q->where($related->getQualifiedKeyName(), $id);
            }
        };
    
        return (bool) $this->whereHas(array_shift($relations), $callback)->find($this->getKey());
    }
    
    protected function getNestedRelated(array $relations)
    {
        $models = [];
    
        foreach ($relations as $key => $relation)
        {
            $parent = ($key) ? $models[$key-1] : $this;
            $models[] = $parent->{$relation}()->getRelated();
        }
    
        return end($models);
    }
    

    ねえ、でもそこで何が起こっているの?

    isRelatedTo() このように機能します:

    1. $idが渡されたかどうかを確認します はモデルまたは単なるIDであり、$relatedを準備します モデルとその$id コールバックで使用します。オブジェクトを渡さない場合、Eloquentは$relationsで関連するすべてのモデルをインスタンス化する必要があります (relation1.relation2.relation3... )興味のあるものを取得するためのチェーン-それがgetNestedRelated()で発生します 、かなり簡単です。

    2. 次に、次のようなことを行う必要があります:

      // assuming relations 'relation1.relation2.relation3'
      $this->whereHas('relation1', function ($q) use ($id) {
         $q->whereHas('relation2', function ($q) use ($id) {
            $q->whereHas('relation3', function ($q) use ($id) {
               $q->where('id', $id);
            });
         });
      })->find($this->getKey()); 
      // returns new instance of current model or null, thus cast to (bool)
      
    3. 関係がどの程度深くネストされているかわからないため、再通貨を使用する必要があります。ただし、ClosureをwhereHasに渡します 、したがって、本体内で自分自身を呼び出すには、ちょっとしたトリックを使用する必要があります(実際には、それを呼び出さず、$callbackとして渡します。 whereHasへ メソッド、後者は2番目のパラメータとしてクロージャを想定しているため)-これは、なじみのない匿名の再帰的PHP関数

      // save it to the variable and pass it by reference
      $callback = function () use (&$callback) {
        if (...) // call the $callback again
        else // finish;
      }
      
    4. また、クロージャー$relationsに渡します (現在は配列として)その要素のシフトを解除するために参照し、すべてを取得したとき(つまり、whereHasをネストしました )、最終的にwhereを配置します 別のwhereHasの代わりに句 、$relatedを検索するには モデル。

    5. 最後に、boolを返しましょう



    1. XA / JTAトランザクションはまだ使用されていますか?

    2. c3p0が待機中にハングします休止状態で使用可能

    3. Hibernateでの正規表現クエリ

    4. 配列要素の順序を持​​つ配列型のPostgreSQLJOIN、実装方法は?