From c8af15ed4fd21385229b40a4dafd84083e07d9a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Alfaiate?= Date: Fri, 21 Feb 2025 15:50:17 +0700 Subject: [PATCH 1/2] fix: prevent duplicate table name errors --- src/EloquentDataTable.php | 48 ++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/src/EloquentDataTable.php b/src/EloquentDataTable.php index 8a6f154e..edcb9294 100644 --- a/src/EloquentDataTable.php +++ b/src/EloquentDataTable.php @@ -164,7 +164,7 @@ protected function resolveRelationColumn(string $column): string { $parts = explode('.', $column); $columnName = array_pop($parts); - $relation = implode('.', $parts); + $relation = str_replace('[]', '', implode('.', $parts)); if ($this->isNotEagerLoaded($relation)) { return $column; @@ -184,54 +184,56 @@ protected function resolveRelationColumn(string $column): string */ protected function joinEagerLoadedColumn($relation, $relationColumn) { - $table = ''; + $tableAlias = ''; $lastQuery = $this->query; foreach (explode('.', $relation) as $eachRelation) { $model = $lastQuery->getRelation($eachRelation); + $lastAlias = $tableAlias ?: $lastQuery->getModel()->getTable(); + $tableAlias = $tableAlias.'_'.$eachRelation; + $pivotAlias = $tableAlias.'_pivot'; switch (true) { case $model instanceof BelongsToMany: - $pivot = $model->getTable(); - $pivotPK = $model->getExistenceCompareKey(); - $pivotFK = $model->getQualifiedParentKeyName(); + $pivot = $model->getTable().' as '.$pivotAlias; + $pivotPK = $pivotAlias.'.'.$model->getForeignPivotKeyName(); + $pivotFK = $lastAlias.'.'.$model->getParentKeyName(); $this->performJoin($pivot, $pivotPK, $pivotFK); $related = $model->getRelated(); - $table = $related->getTable(); + $table = $related->getTable().' as '.$tableAlias; $tablePK = $model->getRelatedPivotKeyName(); - $foreign = $pivot.'.'.$tablePK; - $other = $related->getQualifiedKeyName(); + $foreign = $pivotAlias.'.'.$tablePK; + $other = $tableAlias.'.'.$related->getKeyName(); - $lastQuery->addSelect($table.'.'.$relationColumn); - $this->performJoin($table, $foreign, $other); + $lastQuery->addSelect($tableAlias.'.'.$relationColumn); break; case $model instanceof HasOneThrough: - $pivot = explode('.', $model->getQualifiedParentKeyName())[0]; // extract pivot table from key - $pivotPK = $pivot.'.'.$model->getFirstKeyName(); - $pivotFK = $model->getQualifiedLocalKeyName(); + $pivot = explode('.', $model->getQualifiedParentKeyName())[0].' as '.$pivotAlias; // extract pivot table from key + $pivotPK = $pivotAlias.'.'.$model->getFirstKeyName(); + $pivotFK = $lastAlias.'.'.$model->getLocalKeyName(); $this->performJoin($pivot, $pivotPK, $pivotFK); $related = $model->getRelated(); - $table = $related->getTable(); + $table = $related->getTable().' as '.$tableAlias; $tablePK = $model->getSecondLocalKeyName(); - $foreign = $pivot.'.'.$tablePK; - $other = $related->getQualifiedKeyName(); + $foreign = $pivotAlias.'.'.$tablePK; + $other = $tableAlias.'.'.$related->getKeyName(); $lastQuery->addSelect($lastQuery->getModel()->getTable().'.*'); break; case $model instanceof HasOneOrMany: - $table = $model->getRelated()->getTable(); - $foreign = $model->getQualifiedForeignKeyName(); - $other = $model->getQualifiedParentKeyName(); + $table = $model->getRelated()->getTable().' as '.$tableAlias; + $foreign = $tableAlias.'.'.$model->getForeignKeyName(); + $other = $lastAlias.'.'.$model->getLocalKeyName(); break; case $model instanceof BelongsTo: - $table = $model->getRelated()->getTable(); - $foreign = $model->getQualifiedForeignKeyName(); - $other = $model->getQualifiedOwnerKeyName(); + $table = $model->getRelated()->getTable().' as '.$tableAlias; + $foreign = $lastAlias.'.'.$model->getForeignKeyName(); + $other = $tableAlias.'.'.$model->getOwnerKeyName(); break; default: @@ -241,7 +243,7 @@ protected function joinEagerLoadedColumn($relation, $relationColumn) $lastQuery = $model->getQuery(); } - return $table.'.'.$relationColumn; + return $tableAlias.'.'.$relationColumn; } /** From 1b026ba1f190383d8863df88572e3fac5fbd95df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Alfaiate?= Date: Mon, 24 Feb 2025 09:23:29 +0700 Subject: [PATCH 2/2] fix: applyOrderColumn with column alias --- src/QueryDataTable.php | 8 +++----- tests/Integration/CustomOrderTest.php | 4 ++-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/QueryDataTable.php b/src/QueryDataTable.php index f6610dad..b8c359ab 100644 --- a/src/QueryDataTable.php +++ b/src/QueryDataTable.php @@ -662,8 +662,6 @@ protected function defaultOrdering(): void $column = $this->resolveRelationColumn($orderable['name']); if ($this->hasOrderColumn($orderable['name'])) { - $this->applyOrderColumn($orderable['name'], $orderable); - } elseif ($this->hasOrderColumn($column)) { $this->applyOrderColumn($column, $orderable); } else { $nullsLastSql = $this->getNullsLastSql($column, $orderable['direction']); @@ -687,16 +685,16 @@ protected function hasOrderColumn(string $column): bool */ protected function applyOrderColumn(string $column, array $orderable): void { - $sql = $this->columnDef['order'][$column]['sql']; + $sql = $this->columnDef['order'][$orderable['name']]['sql']; if ($sql === false) { return; } if (is_callable($sql)) { - call_user_func($sql, $this->query, $orderable['direction']); + call_user_func($sql, $this->query, $orderable['direction'], $column); } else { $sql = str_replace('$1', $orderable['direction'], (string) $sql); - $bindings = $this->columnDef['order'][$column]['bindings']; + $bindings = $this->columnDef['order'][$orderable['name']]['bindings']; $this->query->orderByRaw($sql, $bindings); } } diff --git a/tests/Integration/CustomOrderTest.php b/tests/Integration/CustomOrderTest.php index d4664405..d1915d98 100644 --- a/tests/Integration/CustomOrderTest.php +++ b/tests/Integration/CustomOrderTest.php @@ -54,8 +54,8 @@ protected function setUp(): void parent::setUp(); $this->app['router']->get('/relations/belongsTo', fn (DataTables $datatables) => $datatables->eloquent(Post::with('user')->select('posts.*')) - ->orderColumn('user.id', function ($query, $order) { - $query->orderBy('users.id', $order == 'desc' ? 'asc' : 'desc'); + ->orderColumn('user.id', function ($query, $order, $column) { + $query->orderBy($column, $order == 'desc' ? 'asc' : 'desc'); }) ->toJson()); }