Laravel-datatables: relation laravel où la clause ne s'applique pas dans le tri de la table de données laravel

Créé le 15 août 2017  ·  14Commentaires  ·  Source: yajra/laravel-datatables

Résumé du problème ou de la demande de fonctionnalité

salut
Pardon
Je ne suis pas bon en anglais;
la recherche fonctionne avec des modèles associés
mais quand je veux trier en tant que champ connexe, il est dupliqué
car traduire la clause where ne s'appliquant pas au tri

Toute solution ?

Extrait de code du problème

Détails du système

  • linux
  • version php : 7.1
  • Version Laravel : 5.4
  • Laravel-Datatables Version : 7.0
enhancement for review

Tous les 14 commentaires

 class OrderFood extends Model
{
    protected $table = 'order_foods';
    protected $fillable = [
        'order_id','food_id','quantity','food_price'
    ];

    public function order()
    {
        return $this->belongsTo(Order::class);
    }

    public function food()
    {
        return $this->belongsTo(Food::class)
            ->with('translate');
    }
}


class Food extends Model
{
    protected $table = 'foods';
    protected $fillable = [
        'title','date','tax','tax_enabled','tax_included','images','star','description','recipes','status','lang'
    ];

    public function translate()
    {
        return $this->hasOne(FoodTranslator::class,'food_id')
            ->where('lang',app()->getLocale());
    }
}

    public function query()
    {
        DB::statement(DB::raw('set @rownum=0'));
        DB::statement(DB::raw('SET collation_connection = utf8_general_ci'));
        DB::statement(DB::raw('SET character_set_connection = utf8'));
        $order_id = $this->order_id;
        $order_foods = Order::find($order_id)->foods()->with(['food.translate'])->select(['*','order_foods.created_at',DB::raw('<strong i="5">@rownum</strong>  := <strong i="6">@rownum</strong>  + 1 AS rownum')]);
        return $this->applyScopes($order_foods);
    }


    private function getColumns()
    {
        return [
            ['title' => trans('form.row'),'name' => 'rownum', 'data' => 'rownum','searchable'=>false],
            ['title' => trans('order.order_food'),'name' => 'food.translate.title', 'data' => 'food.translate.title','orderable'=>false],
            ['title' => trans('order.quantity'),'name' => 'quantity', 'data' => 'quantity'],
            ['title' => trans('order.food_price'),'name' => 'food_price', 'data' => 'food_price'],
            ['title' => trans('form.created_at'),'name' => 'created_at', 'data' => 'created_at'],
            ['title' => trans('form.action'),'name' => 'action', 'data' => 'action','searchable'=>false,'exportable'=>false,'printable'=>false],
        ];
    }

Ce problème a déjà été résolu sur la v8. Il est compatible avec Laravel 5.4 mais a des changements de rupture. Notez cependant qu'il n'est pas encore marqué comme stable. Merci!

Merci beaucoup!

ce problème n'est pas résolu dans la v8

dois-je changer mes codes ?

Le problème ici concerne la relation de traduction, n'est-ce pas ?

public function translate()
{
    return $this->hasOne(FoodTranslator::class,'food_id')
        ->where('lang',app()->getLocale());
}

Le problème, c'est que la clause où n'est pas appliquée ? Cela a été résolu sur la v8 à moins qu'il n'y ait un autre problème que je ne vois pas ?

à la commande 3 requêtes sont exécutées

1:
bindings:[]
query:"select count(*) as aggregate from (select '1' as `row_count` from `foods`) count_row_table"
time:0.29
2:
bindings:[]
query:"select *, <strong i="6">@rownum</strong>  := <strong i="7">@rownum</strong>  + 1 AS rownum from `foods` left join `food_translator` on `food_translator`.`food_id` = `foods`.`id` order by `food_translator`.`title` desc limit 10 offset 0"
time:0.81
3:
bindings:["fa", 1]
query:"select * from `food_translator` where `lang` = ? and `food_translator`.`food_id` in (?)"
time:0.46

peut-être que la clause where doit être dans la deuxième requête pas 3

cette requête

query:"select * from `food_translator` where `lang` = ? and `food_translator`.`food_id` in (?)"

est pour

public function translate()
{
    return $this->hasOne(FoodTranslator::class,'food_id')
        ->where('lang',app()->getLocale());
}

qui n'affecte pas les résultats

@aliworkshop Je pense que je vois le problème maintenant. Je creuserai plus loin quand j'en aurai l'occasion.

merci beaucoup maître :)

l'erreur n'est pas corrigée ?

J'ai résolu le problème d'édition de la classe EloquentDataTable dans l'espace de noms Yajra\DataTables

protected function joinEagerLoadedColumn($relation, $relationColumn)
    {
        $table     = '';
        $lastQuery = $this->query;
        foreach (explode('.', $relation) as $eachRelation) {
            $model = $lastQuery->getRelation($eachRelation);
            $fillable = [];
            switch (true) {
                case $model instanceof BelongsToMany:
                    $pivot   = $model->getTable();
                    $pivotPK = $model->getExistenceCompareKey();
                    $pivotFK = $model->getQualifiedParentKeyName();
                    $this->performJoin($pivot, $pivotPK, $pivotFK);

                    $related = $model->getRelated();
                    $table   = $related->getTable();
                    $tablePK = $related->getForeignKey();
                    $foreign = $pivot . '.' . $tablePK;
                    $other   = $related->getQualifiedKeyName();

                    $lastQuery->addSelect($table . '.' . $relationColumn);
                    $this->performJoin($table, $foreign, $other);

                    break;

                case $model instanceof HasOneOrMany:
                    $table   = $model->getRelated()->getTable();
                    $foreign = $model->getQualifiedForeignKeyName();
                    $other   = $model->getQualifiedParentKeyName();
                    $fillable = $model->getRelated()->getFillable();
                    break;

                case $model instanceof BelongsTo:
                    $table   = $model->getRelated()->getTable();
                    $foreign = $model->getQualifiedForeignKey();
                    $other   = $model->getQualifiedOwnerKeyName();
                    break;

                default:
                    throw new Exception('Relation ' . get_class($model) . ' is not yet supported.');
            }
            $this->performJoin($table, $foreign, $other,'inner',$fillable);
            $lastQuery = $model->getQuery();
        }

        return $table . '.' . $relationColumn;
    }

protected function performJoin($table, $foreign, $other, $type = 'left', $fillable = [])
    {
        $joins = [];
        foreach ((array) $this->getBaseQueryBuilder()->joins as $key => $join) {
            $joins[] = $join->table;
        }

        if (! in_array($table, $joins)) {
            $this->getBaseQueryBuilder()->join($table, $foreign, '=', $other, $type);
            if (in_array('lang',$fillable))
                $this->query->where('lang', app()->getLocale());
        }
    }

ce changement applique manuellement la colonne lang où la clause pour joindre la requête

si un moyen avait existé cette relation où les clauses s'appliqueraient comme cela
ce serait très bien

@aliworkshop merci, mais la solution proposée ne fonctionnera que sur votre cas. Pouvez-vous essayer peut-être en utilisant le code ci-dessous?

Remplacer:

$this->getBaseQueryBuilder()->join($table, $foreign, '=', $other, $type);

Avec:

$this->query->join($table, $foreign, '=', $other, $type);

Un peu occupé sur des projets de travail et ne peut pas consacrer beaucoup de temps à oss ces derniers temps. Merci!

re-bonjour maître
je trouve une autre solution à ce problème
si nous éditons la classe EloquentDataTable dans l'espace de noms Yajra\DataTables comme ceci , cela fonctionne probablement

protected function joinEagerLoadedColumn($relation, $relationColumn)
    {
        $table     = '';
        $lastQuery = $this->query;
        foreach (explode('.', $relation) as $eachRelation) {
            $model = $lastQuery->getRelation($eachRelation);
            switch (true) {
                case $model instanceof BelongsToMany:
                    $pivot   = $model->getTable();
                    $pivotPK = $model->getExistenceCompareKey();
                    $pivotFK = $model->getQualifiedParentKeyName();
                    $this->performJoin($pivot, $pivotPK, $pivotFK);

                    $related = $model->getRelated();
                    $table   = $related->getTable();
                    $tablePK = $related->getForeignKey();
                    $foreign = $pivot . '.' . $tablePK;
                    $other   = $related->getQualifiedKeyName();

                    $lastQuery->addSelect($table . '.' . $relationColumn);
                    $this->performJoin($table, $foreign, $other);

                    break;

                case $model instanceof HasOneOrMany:
                    $table   = $model->getRelated()->getTable();
                    $foreign = $model->getQualifiedForeignKeyName();
                    $other   = $model->getQualifiedParentKeyName();
                    break;

                case $model instanceof BelongsTo:
                    $table   = $model->getRelated()->getTable();
                    $foreign = $model->getQualifiedForeignKey();
                    $other   = $model->getQualifiedOwnerKeyName();
                    break;

                default:
                    throw new Exception('Relation ' . get_class($model) . ' is not yet supported.');
            }
            $wheres = $model->getQuery()->getQuery()->wheres;
            $this->performJoin($table, $foreign, $other,'inner',$wheres);
            $lastQuery = $model->getQuery();
        }

        return $table . '.' . $relationColumn;
    }


    protected function performJoin($table, $foreign, $other, $type = 'left', $wheres = [])
    {
        $joins = [];
        foreach ((array) $this->getBaseQueryBuilder()->joins as $key => $join) {
            $joins[] = $join->table;
        }

        if (! in_array($table, $joins)) {
            $this->query->join($table, $foreign, '=', $other, $type);
            foreach ($wheres as $where) {
                if ($where['boolean'] == 'and')
                    $this->query->where($where['column'], $where['operator'], $where['value']);
                else
                    $this->query->orWhere($where['column'], $where['operator'], $where['value']);
            }
        }
    }

veuillez appliquer ce code dans la prochaine version

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

vipin733 picture vipin733  ·  3Commentaires

SGarridoDev picture SGarridoDev  ·  3Commentaires

shadoWalker89 picture shadoWalker89  ·  3Commentaires

Mopster picture Mopster  ·  3Commentaires

FilipeBorges1993 picture FilipeBorges1993  ·  3Commentaires