Как исправить ошибку "Пожалуйста, используйте whereHasMorph() для отношений MorphTo". при использовании функции поиска Laravel BackPack?
У меня очень простые полиморфные отношения "один ко многим", как показано ниже.
posts
id - integer
title - string
videos
id - integer
title - string
comments
id - integer
body - text
commentable_id - integer
commentable_type - string
Ниже показано, как выглядят отношения в моделях:
class Comment extends Model
{
public function commentable()
{
return $this->morphTo();
}
}
class Post extends Model
{
public function comments()
{
return $this->morphMany('App\Comment', 'commentable');
}
}
class Video extends Model
{
public function comments()
{
return $this->morphMany('App\Comment', 'commentable');
}
}
Я использую Laravel Backpack CRUD для управления comments
, в CommentCrudController::setup()
Функция, я добавляю столбцы следующим образом:
public function setup() {
// Standard CrudPanel Basic Information goes here...
$this->crud->addColumn([
'name' => 'body',
'label' => 'Comment',
]);
$this->crud->addColumn([
'label' => "Related Entity",
'type' => "select", // Need to use type 'select' for property of related model.
'name' => 'commentable_id ',
'entity' => 'commentable', // Function name, defining the polymorphic relationship.
'attribute' => "title", // The column name of the related database table.
]);
}
С вышеуказанной конфигурацией в CommentCrudController::setup()
функция, я получаю обзорную таблицу комментариев как обычно. Но когда я пытался найти что-то с помощью формы поиска по рюкзаку, я получил следующую ошибку:
{
message: "Please use whereHasMorph() for MorphTo relationships."
trace: [
{file: vendor/backpack/crud/src/PanelTraits/Search.php", line: 91}
]
}
Я понимаю это, потому что это One-To-Many
полиморфная связь с morphTo()
функция и в CommentCrudController::setup()
функция, которую я использовал 'type' => "select"
добавить title
из "Related Entity"
как столбец, при попытке поиска записей Laravel Backpack
попытается выполнить следующий запрос внутри trait Search::applySearchLogicForColumn()
функция:
if ($column['tableColumn']) {
switch ($columnType) {
// Skipped other cases here...
case 'select':
case 'select_multiple':
$query->orWhereHas($column['entity'], function ($q) use ($column, $searchTerm) {
$q->where($column['attribute'], 'like', '%'.$searchTerm.'%');
});
break;
// Skipped default case here...
}
Как говорится в ошибке, $query->orWhereHas()
следует изменить на $query->whereHasMorph()
, Но изменение этого не решает проблему. И я также хочу иметь возможность искать в title
столбец связанной модели.
Как я могу это исправить?
0 ответов
Я нашел решение, переопределив следующие три функции в CommentCrudController
:
search()
applySearchTerm($searchTerm)
applySearchLogicForColumn($query, $searchTerm)
в search()
функция, я сохранил все, так как это связано с разбивкой на страницы, сортировкой и т. д. Кроме вызова $this->crud->applySearchTerm()
функция. Я изменил его на звонок$this->applySearchTerm()
который я также переопределил в CommentCrudController
.
Поскольку в моем случае эта операция работает с определенными таблицами и столбцами базы данных, я мог переопределить applySearchTerm($searchTerm)
функционируют следующим образом:
public function applySearchTerm($searchTerm)
{
return $this->crud->query->where(function ($query) use ($searchTerm) {
$this->applySearchLogicForColumn($query, $searchTerm);
});
}
И решение происходит путем переопределения applySearchLogicForColumn($query, $searchTerm)
функционируют следующим образом:
public function applySearchLogicForColumn($query, $searchTerm)
{
$query->orWhere('body', 'LIKE', '%' . $searchTerm . '%')
->orWhereHasMorph(
'commentable',
[
Post::class,
Video::class,
],
function (Builder $query) use ($searchTerm) {
$query->where('title', 'LIKE', '%' . $searchTerm . '%')
}
);
}
В случае, если у вас есть другая связанная модель морфа с другим именем столбца, чем title
например
posts
id - integer
title - string
videos
id - integer
title - string
users
id - integer
full_name - string // table 'users' with 'full_name' column where you also want to apply search term to.
comments
id - integer
body - text
commentable_id - integer
commentable_type - string
Вы можете переопределить applySearchLogicForColumn($query, $searchTerm)
функционируют следующим образом:
public function applySearchLogicForColumn($query, $searchTerm)
{
$query->orWhere('body', 'LIKE', '%' . $searchTerm . '%')
->orWhereHasMorph(
'commentable',
[
Post::class,
Video::class,
],
function (Builder $query) use ($searchTerm) {
$query->where('title', 'LIKE', '%' . $searchTerm . '%')
}
)
->orWhereHasMorph(
'commentable',
[
User::class,
],
function (Builder $query) use ($searchTerm) {
$query->where('full_name', 'LIKE', '%' . $searchTerm . '%')
}
);
}