Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions src/HasTranslations.php
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,47 @@ public function scopeWhereJsonContainsLocales(Builder $query, string $column, ar
}
});
}
/**
* Scope: Order query results by a JSON translated attribute for a given locale.
*
* @param Builder $query The Eloquent query builder instance.
* @param string $column The JSON column name (e.g. "name").
* @param string $direction Sort direction ("asc" or "desc").
* @param string|null $locale The locale key (e.g. "en", "ar"). Defaults to current locale.
* @return Builder
*/
public function scopeOrderByLocale(
Builder $query,
string $column,
string $direction = 'asc',
?string $locale = null
): Builder {
$locale = $locale ? $locale : $this->getLocale();

$this->guardAgainstNonTranslatableAttribute($column);

// Detect database driver to use the correct syntax
$driver = $query->getConnection()->getDriverName();

if ($driver === 'pgsql') {
// PostgreSQL uses ->> operator to extract JSON values as text
return $query->orderBy("{$column}->{$locale}", $direction);
}

if ($driver === 'mysql') {
// MySQL uses JSON_EXTRACT and JSON_UNQUOTE
$jsonPath = '$."' . addslashes($locale) . '"';

return $query->orderByRaw(
"JSON_UNQUOTE(JSON_EXTRACT(`$column`, ?)) $direction",
[$jsonPath]
);
}

// Fallback for SQLite or others (assume JSON stored as text)
return $query->orderBy("{$column}->{$locale}", $direction);
}


/**
* @deprecated
Expand Down