在我的应用程序中,我对两个不同的表和两个不同的列名称执行关键字搜索。我想将
movies.title
和 people.title
组合起来,以便我可以按字母顺序将它们全部排序。目前,我合并了两个查询,结果首先返回电影,然后返回人物。
public function get_from_keyword($keyword){
$movie_query = $this->db
->select('id, title, release_year')
->from('movies')
->like('movies.title', $keyword)
->where('movies.id IS NOT NULL', null)
->get()
->result();
$person_query = $this->db
->select('name, person_id')
->from('people')
->like('name', $keyword)
->get()
->result();
$merged_queries = array_merge($movie_query, $person_query);
return $merged_queries;
}
我不确定是否需要动态更改
SELECT
查询中的列名称之一以便将它们合并在一起。
尝试使用“AS”来命名 movie.title 和 people.name 字段,如下所示:
$person_query = $this->db
->select('name', 'MySortTitle') // AS
->select('person_id')
->from('people')
->like('name', $keyword)
->get()
->result();
电影查询也是如此:
$movie_query = $this->db
->select('title', 'MySortTitle') // AS
->select('id, release_year')
->from('movies')
->like('movies.title', $keyword)
->where('movies.id IS NOT NULL', null)
->get()
->result();
然后通过 MySortTitle 对合并后的数组进行排序。
无需重构模型方法来使用 ORDER BY 条件实现 UNION 查询,您只需在回调中使用
usort()
和后备。
现在,您有一个模型方法,它正在做两件事 - 它不应该这样设计,因为它限制了该方法的“实用性”/“可重用性”。 我建议在两个单独的模型中使用一个方法,并使用一个库来合并和排序。
简短的回答:
usort(
$merged_results,
fn($a, $b) => ($a->name ?? $a->title) <=> ($b->name ?? $b->title)
);
使用后备意味着您可以覆盖作为
$a
和 $b
传入的值的不可预测性,并且您不必改变模型方法来实现所需的有效负载。
长答案:
重申我之前的建议,合并和排序过程可能不理想地添加到模型层,当然不应该添加到控制器层(控制器不做工作,它们委托工作)由其他层完成)。
您的控制器应该看起来像指令列表。您可能让控制器调用库来合并和排序数据
public function moviesAndActorsLike(string $term)
{
$this->load->library('CinemaLib');
$data['results'] = $this->CinemaLib->getPeopleAndMoviesLike($term);
$this->CinemaLib->sortByTitleOrName($data['results']);
$this->load->view('search', $data);
}
图书馆可能是逻辑的最佳场所。
public function getPeopleAndMoviesLike(string $term): array
{
$this->load->model('People_model', 'PeopleModel');
$this->load->model('Movies_model', 'MoviesModel');
return array_merge(
$this->PeopleModel->getLike('name', $term),
$this->MoviesModel->getLike('title', $term)
);
}
public function sortByTitleOrName(array &$mixedTableRecords): void
{
usort(
$mixedTableRecords,
fn($a, $b) => ($a->name ?? $a->title) <=> ($b->name ?? $b->title)
);
}