sql >> Database >  >> RDS >> Mysql

MySQL geneste bronnen (draaitabellen) toestemming om te bekijken/bijwerken/beheren

Om te controleren of een bepaald model gerelateerd is aan een ander model, wat je wilt als ik het goed begrijp, is alles wat je nodig hebt deze kleine methode om het meeste uit Eloquent te halen. :

(Implementeer het in BaseModel , Entity of een scope, wat bij je past)

// 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);

De magie gebeurt hier:

/**
 * 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);
}

Hé, maar wat is daar aan de hand?

isRelatedTo() werkt als volgt:

  1. controleer of doorgegeven $id is een model of gewoon een ID, en bereidt $related . voor model en zijn $id voor gebruik bij het terugbellen. Als u geen object doorgeeft, moet Eloquent alle gerelateerde modellen op de $relations instantiëren (relation1.relation2.relation3... ) keten om degene te krijgen waarin we geïnteresseerd zijn - dat is wat er gebeurt in getNestedRelated() , vrij eenvoudig.

  2. dan moeten we zoiets als dit doen:

    // 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. omdat we niet weten hoe diep de relatie is genest, moeten we herhaling gebruiken. We geven echter een sluiting door aan de whereHas , dus we moeten een klein trucje gebruiken om zichzelf in zijn lichaam te noemen (in feite noemen we het niet, maar geven het door als $callback naar de whereHas methode, aangezien de laatste een sluiting verwacht als 2e parameter) - dit kan handig zijn voor degenen die onbekend zijn Anonieme recursieve PHP-functies :

    // save it to the variable and pass it by reference
    $callback = function () use (&$callback) {
      if (...) // call the $callback again
      else // finish;
    }
    
  4. we gaan ook door naar de sluiting $relations (nu als een array) door te verwijzen om de elementen ervan ongedaan te maken, en wanneer we ze allemaal hebben (wat betekent dat we whereHas hebben genest ), plaatsen we tenslotte de where clausule in plaats van een andere whereHas , om te zoeken naar onze $related model.

  5. laten we tot slot bool return teruggeven



  1. 4 manieren om rijen met kleine letters te vinden in MariaDB

  2. Records van de afgelopen 3 maanden alleen retourneren in MySQL

  3. Het raiserror-bericht van SqlServer opslaan in C#

  4. Aan de slag met Oracle SQL Developer op Windows