Laravel-datatables: laravel 데이터 ν…Œμ΄λΈ” μ •λ ¬μ—μ„œ 절이 μ μš©λ˜μ§€ μ•ŠλŠ” laravel 관계

에 λ§Œλ“  2017λ…„ 08μ›” 15일  Β·  14μ½”λ©˜νŠΈ  Β·  좜처: yajra/laravel-datatables

문제 λ˜λŠ” κΈ°λŠ₯ μš”μ²­ μš”μ•½

μ•ˆλ…•
μ£„μ†‘ν•©λ‹ˆλ‹€
λ‚˜λŠ” μ˜μ–΄λ₯Ό 잘 λͺ»ν•œλ‹€.
검색은 κ΄€λ ¨ λͺ¨λΈκ³Ό ν•¨κ»˜ μž‘λ™ν•©λ‹ˆλ‹€.
ν•˜μ§€λ§Œ κ΄€λ ¨ ν•„λ“œλ‘œ μ •λ ¬ν•˜κ³  싢을 λ•Œ μ€‘λ³΅λ©λ‹ˆλ‹€.
정렬에 μ μš©λ˜μ§€ μ•ŠλŠ” where μ ˆμ„ λ²ˆμ—­ν•˜κΈ° λ•Œλ¬Έμ—

μ–΄λ–€ ν•΄κ²°μ±…?

문제의 μ½”λ“œ μŠ€λ‹ˆνŽ«

μ‹œμŠ€ν…œ 세뢀정보

  • λ¦¬λˆ…μŠ€
  • PHP 버전: 7.1
  • 라라벨 버전 : 5.4
  • Laravel-Datatables 버전 : 7.0
enhancement for review

λͺ¨λ“  14 λŒ“κΈ€

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

이 λ¬Έμ œλŠ” v8μ—μ„œ 이미 μˆ˜μ •λ˜μ—ˆμŠ΅λ‹ˆλ‹€. Laravel 5.4와 ν˜Έν™˜λ˜μ§€λ§Œ μ£Όμš” λ³€κ²½ 사항이 μžˆμŠ΅λ‹ˆλ‹€. 아직 μ•ˆμ • νƒœκ·Έκ°€ μ§€μ •λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. 감사 ν•΄μš”!

정말 κ°μ‚¬ν•©λ‹ˆλ‹€!

이 λ¬Έμ œλŠ” v8μ—μ„œ μˆ˜μ •λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.

λ‚΄ μ½”λ“œλ₯Ό λ³€κ²½ν•΄μ•Ό ν•©λ‹ˆκΉŒ?

μ—¬κΈ°μ„œ λ¬Έμ œλŠ” λ²ˆμ—­ 관계 λ§žμŠ΅λ‹ˆκΉŒ?

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

λ¬Έμ œλŠ” where 절이 μ μš©λ˜μ§€ μ•ŠμŠ΅λ‹ˆκΉŒ? 이것은 λ‚΄κ°€ 보지 λͺ»ν•˜λŠ” λ‹€λ₯Έ λ¬Έμ œκ°€ μ—†λŠ” ν•œ v8μ—μ„œ ν•΄κ²°λ˜μ—ˆμŠ΅λ‹ˆκΉŒ?

μ£Όλ¬Έ μ‹œ 3개의 쿼리가 μ‹€ν–‰λ©λ‹ˆλ‹€.

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

μ•„λ§ˆλ„ where μ ˆμ€ 3이 μ•„λ‹Œ 두 번째 쿼리에 μžˆμ–΄μ•Ό ν•©λ‹ˆλ‹€.

이 쿼리

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

λ₯Ό μœ„ν•œ

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

결과에 영ν–₯을 λ―ΈμΉ˜μ§€ μ•ŠλŠ”

@aliworkshop μ§€κΈˆ 문제λ₯Ό 보고 μžˆλŠ” 것

κ°μ‚¬ν•©λ‹ˆλ‹€ λ§ˆμŠ€ν„° :)

였λ₯˜κ°€ μˆ˜μ •λ˜μ§€ μ•ŠμŠ΅λ‹ˆκΉŒ?

Yajra\DataTables λ„€μž„μŠ€νŽ˜μ΄μŠ€μ˜ EloquentDataTable 클래슀 νŽΈμ§‘ 문제λ₯Ό μˆ˜μ •ν–ˆμŠ΅λ‹ˆλ‹€.

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());
        }
    }

이 변경은 lang 열을 μˆ˜λ™μœΌλ‘œ μ μš©ν•©λ‹ˆλ‹€. where μ ˆμ€ 쿼리λ₯Ό μ‘°μΈν•©λ‹ˆλ‹€.

방법이 μ‘΄μž¬ν–ˆλ‹€λ©΄ 절이 λ‹€μŒκ³Ό 같이 μ μš©λ˜λŠ” 관계
μ•„μ£Ό 쒋을 κ²ƒμž…λ‹ˆλ‹€

@aliworkshop κ°μ‚¬ν•©λ‹ˆλ‹€. ν•˜μ§€λ§Œ μ œμ•ˆλœ μ†”λ£¨μ…˜μ€ κ·€ν•˜μ˜ κ²½μš°μ—λ§Œ μž‘λ™ν•©λ‹ˆλ‹€. μ•„λž˜ μ½”λ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ μ‹œλ„ν•΄ λ³Ό 수 μžˆμŠ΅λ‹ˆκΉŒ?

λ°”κΎΈλ‹€:

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

와 ν•¨κ»˜:

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

μž‘μ—… ν”„λ‘œμ νŠΈμ— μ•½κ°„ λ°”μ˜κ³  μ΅œκ·Όμ—λŠ” OS에 λ§Žμ€ μ‹œκ°„μ„ ν• μ• ν•  수 μ—†μŠ΅λ‹ˆλ‹€. 감사 ν•΄μš”!

μ•ˆλ…• λ‹€μ‹œ λ§ˆμŠ€ν„°
λ‚˜λŠ”μ΄ λ¬Έμ œμ— λŒ€ν•œ 또 λ‹€λ₯Έ 해결책을 μ°ΎμŠ΅λ‹ˆλ‹€
Yajra\DataTables λ„€μž„μŠ€νŽ˜μ΄μŠ€μ˜ EloquentDataTable 클래슀λ₯Ό λ‹€μŒκ³Ό 같이 νŽΈμ§‘ν•˜λ©΄ μ•„λ§ˆλ„ μž‘λ™ν•  κ²ƒμž…λ‹ˆλ‹€.

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

λ‹€μŒ λ²„μ „μ—μ„œ 이 μ½”λ“œλ₯Ό μ μš©ν•˜μ‹­μ‹œμ˜€

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰