2

我有一个非常简单的一对多多态关系如下。

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(),我可以正常得到一个评论概览表。但是,当我尝试使用 Backpack 搜索表单搜索内容时,出现以下错误:

{
  message: "Please use whereHasMorph() for MorphTo relationships."
  trace: [
    {file: vendor/backpack/crud/src/PanelTraits/Search.php", line: 91}
  ]
}

我确实理解,因为它是与函数的One-To-Many多态关系,并且在我用来添加as 列的函数中,尝试搜索记录时会尝试在函数内执行以下查询:morphTo()CommentCrudController::setup()'type' => "select"title"Related Entity"Laravel Backpacktrait 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相关模型的列中进行搜索。
我怎样才能解决这个问题?

4

1 回答 1

1

我通过覆盖以下三个函数找到了解决方案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 . '%')
              }
          );
} 
于 2019-09-02T08:30:56.473 回答