Laravel-datatables: Relación de laravel donde la cláusula no se aplica en la clasificación de la tabla de datos de laravel

Creado en 15 ago. 2017  ·  14Comentarios  ·  Fuente: yajra/laravel-datatables

Resumen del problema o solicitud de función

Hola
Lo siento
No soy bueno en inglés;
la búsqueda funciona con modelos relacionados
pero cuando quiero ordenar como campo relacionado, está duplicado
porque traducir la cláusula donde no se aplica en la clasificación

alguna solución ?

Fragmento de código del problema

Detalles del sistema

  • linux
  • versión php: 7.1
  • Versión de Laravel: 5.4
  • Versión de Laravel-Datatables: 7.0
enhancement for review

Todos 14 comentarios

 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],
        ];
    }

Este problema ya se solucionó en v8. Es compatible con Laravel 5.4 pero tiene cambios importantes. Sin embargo, tenga en cuenta que aún no está etiquetado como estable. ¡Gracias!

¡muchas gracias!

este problema no se soluciona en v8

¿Debo hacer un cambio en mis códigos?

El problema aquí está en la relación de traducción, ¿verdad?

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

¿El problema es que no se aplica la cláusula where? Esto se solucionó en la v8 a menos que haya otro problema que no esté viendo.

al ordenar 3 consultas se ejecuta

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

tal vez donde la cláusula debe estar en la segunda consulta, no 3

esta consulta

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

es para

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

que no afecta los resultados

@aliworkshop Creo que estoy viendo el problema ahora. Profundizaré más en esto cuando tenga la oportunidad.

muchas gracias maestro :)

el error no está arreglado?

Solucioné el problema con la edición de la clase EloquentDataTable en el espacio de nombres 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());
        }
    }

este cambio aplica manualmente lang columna donde la cláusula para unirse a la consulta

si hubiera existido una forma de esa relación donde se aplicarían cláusulas como esta
sería muy bueno

@aliworkshop gracias, pero la solución propuesta solo funcionará en su caso. ¿Puedes intentar tal vez usar el código a continuación?

Reemplazar:

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

Con:

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

Estoy un poco ocupado en proyectos de trabajo y últimamente no puedo dedicar mucho tiempo al sistema operativo. ¡Gracias!

hola de nuevo maestro
Encontré otra solución para este problema
si editamos la clase EloquentDataTable en el espacio de nombres Yajra \ DataTables como esto, probablemente funcione

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']);
            }
        }
    }

aplique este código en la próxima versión

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

Abdulhmid picture Abdulhmid  ·  3Comentarios

jgatringer picture jgatringer  ·  3Comentarios

t0n1zz picture t0n1zz  ·  3Comentarios

techguydev picture techguydev  ·  3Comentarios

kamrava picture kamrava  ·  3Comentarios