Laravel如何通过数据透视表获取相关字段列表
Posted
技术标签:
【中文标题】Laravel如何通过数据透视表获取相关字段列表【英文标题】:Laravel how to get list of related fields through pivot table 【发布时间】:2021-06-06 06:11:51 【问题描述】:我有 4 个表:peoples、company、country 和数据透视表 company_people(因为 peoples 和 Companies 都属于很多),它同时具有 people_id 和 company_id。
在 People 模型中,我有以下功能:
class People extends Model
// main company (only one)
public function company()
return $this->belongsTo(Company::class);
// all other companies
public function companies()
return $this->belongsToMany(Company::class);
public function country()
return $this->belongsTo(Country::class);
然后在人员控制器中,我有以下内容,以便准备将所有人员的列表与相关的主要公司名称(只有一个)、国家名称(只有一个)和其他公司显示为名称列表.我可以做前两个,但不能做最后一个。我该怎么做?
$peoples = People::orderBy($sortField,$sortOrder)
->with(['companies','company','country'])
->get();
foreach ($peoples as $people)
$people->company = '['.$people->company->company.']'; // main company name
$people->country = '['.$people->country->country.']'; // country name
$people->otherCompanies = ? // list of other company names through pivot table
这里是 4 个表的所有结构:
CREATE TABLE `company_people` (
`id` bigint NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`company_id` bigint UNSIGNED NOT NULL,
`people_id` bigint UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `countries` (
`id` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'AA',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`is_active` int NOT NULL DEFAULT '1',
`country` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `peoples` (
`id` bigint UNSIGNED NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`is_active` int NOT NULL DEFAULT '1',
`firstname` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`lastname` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '',
`country_id` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'ZA',
`company_id` bigint UNSIGNED DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci PACK_KEYS=0;
ALTER TABLE `company_people`
ADD PRIMARY KEY (`id`),
ADD KEY `article_id` (`company_id`),
ADD KEY `tag_id` (`people_id`);
ALTER TABLE `countries`
ADD PRIMARY KEY (`id`);
ALTER TABLE `peoples`
ADD PRIMARY KEY (`id`),
ADD KEY `country_id` (`country_id`),
ADD KEY `company_id` (`company_id`);
ALTER TABLE `company_people`
MODIFY `id` bigint NOT NULL AUTO_INCREMENT;
ALTER TABLE `peoples`
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `peoples`
ADD CONSTRAINT `peoples-company` FOREIGN KEY (`company_id`) REFERENCES `companies` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `peoples-country` FOREIGN KEY (`country_id`) REFERENCES `countries` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
ALTER TABLE `companies`
ADD CONSTRAINT `peoples-country` FOREIGN KEY (`country_id`) REFERENCES `countries` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
ALTER TABLE `company_people`
ADD CONSTRAINT `companies-peoples` FOREIGN KEY (`company_id`) REFERENCES `companies` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `peoples-companies` FOREIGN KEY (`people_id`) REFERENCES `peoples` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
【问题讨论】:
请分享所有表的架构,尤其是数据透视表,以及您希望获得其他公司的逻辑。company_people
这对很多人来说都是正确的,为什么您需要单一公司public function company()
我之所以有 company() 也是因为该表最初的结构是这样的,我最近才意识到有些人属于多个公司,否则我将不得不复制人员记录这是不对的。所以 company() 处理主要的公司关系,company() 处理可选的其他公司关系。
【参考方案1】:
您可以使用pluck() 获取所有公司名称然后toArray() 像这样转换成数组
$peoples = People::orderBy($sortField,$sortOrder)
->with(['companies','company','country'])
->get();
foreach ($peoples as $people)
$people->company = '['.$people->company->company.']'; // main company name
$people->country = '['.$people->country->country.']'; // country name
$people->otherCompanies = $people->companies->pluck('name')->toArray(); // list of other company names through pivot table
如果你想要
otherCompanies
名称作为逗号分隔,那么使用$people->companies->pluck('name')->join(',');
【讨论】:
我认为没有$people->companies
可以做到。 $people->companies()
将创建新查询,并使 with
范围浪费。
@MuhammadDyasYaskur 是的,谢谢以上是关于Laravel如何通过数据透视表获取相关字段列表的主要内容,如果未能解决你的问题,请参考以下文章