sql >> Databáze >  >> RDS >> Mysql

Oprávnění k zobrazení/aktualizaci/správě vnořených zdrojů MySQL (kontingenční tabulky).

Chcete-li zkontrolovat, zda daný model souvisí s jiným, což je to, co chcete, pokud vám rozumím správně, vše, co potřebujete, je tato malá metoda, která maximálně využije Eloquent :

(Implementujte jej v BaseModel , Entity nebo rozsah, podle toho, co vám vyhovuje)

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

Kouzlo se děje zde:

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

Hele, ale co se tam děje?

isRelatedTo() funguje takto:

  1. zkontrolujte, zda jste předali $id je model nebo jen id a připravuje $related model a jeho $id pro použití při zpětném volání. Pokud nepředáte objekt, musí Eloquent vytvořit instanci všech souvisejících modelů v $relations (relation1.relation2.relation3... ), abychom získali ten, který nás zajímá – to se děje v getNestedRelated() , docela přímočaré.

  2. pak musíme udělat něco takového:

    // 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. protože nevíme, jak hluboko je vztah vnořen, musíme použít recurrency. Nicméně předáme uzavření do whereHas , takže musíme použít malý trik, abychom se v jeho těle zavolali (ve skutečnosti to nevoláme, ale předáme to jako $callback do whereHas metoda, protože ta očekává uzavření jako 2. param) - toto může být užitečné pro ty, kteří neznají Anonymní rekurzivní funkce PHP :

    // save it to the variable and pass it by reference
    $callback = function () use (&$callback) {
      if (...) // call the $callback again
      else // finish;
    }
    
  4. přejdeme také do uzávěrky $relations (nyní jako pole) odkazem, aby se zrušilo posunutí jeho prvků, a když jsme je dostali všechny (což znamená, že jsme vnořili whereHas ), nakonec vložíme where klauzule namísto jiného whereHas , a vyhledejte naše $related model.

  5. nakonec vraťme bool



  1. Jak vyřešit 10 běžných problémů s Access 2019

  2. enum('yes', 'no') vs tinyint – který použít?

  3. mysql aktualizuje více sloupců se stejným now()

  4. mysql_insert_id s aktualizací