I have a product table in my Laravel project, products. I have another table, product_assocs:
CREATE TABLE `product_assocs` (
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`product_id_primary` bigint(20) UNSIGNED DEFAULT NULL,
`product_id_assoc` bigint(20) UNSIGNED DEFAULT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
which allows me to connect related products to each other. I want these relations to be symmetrical. I.e., if you create one record in the product_assocs table, it creates a relation that works both ways.
I'm defining a method in my product model to fetch the ids of associated products:
$associationsForProduct = $product->associated()->get();
This method draws on a function in the Products model like so:
public function associated() {
return $this->belongsToMany(Product::class, 'product_assocs', 'product_id_primary', 'product_id_assoc');
I'm having some trouble doing this 'the laravel way'. Obviously, when I get associated products for a particular product $id, I have to fetch all records in product_assocs where id1=$id OR id2=$id
. I can imagine an old-school PHP loop that might accomplish this:
// assume $assocs is an array of records fetched where product_id_primary=$id or product_id_assoc=$id
// assume $id is the current product for which we are fetching records
$clean = array();
foreach($assocs as $asc) {
if ($asc["product_id_primary"] != $id && !in_array($asc["product_id_primary"], $clean)) {
$clean[] = $asc["product_id_primary"];
}
if ($asc["product_id_assoc"] != $id && !in_array($asc["product_id_assoc"], $clean)) {
$clean[] = $asc["product_id_assoc"];
}
}
Am I to understand that if I made a reciprocal function in the Product model to query the second ID from the pivot table I could somehow join the function in the controller? Maybe something like this:
public function related() {
return $this->belongsToMany(Product::class, 'product_assocs', 'product_id_assoc', 'product_id_primary');
Then how's the correct way to formulate the controller statement so it looks for relations in both the associated() and the related() functions here:
$associationsForProduct = $product->[--associated()--OPERAND --related()]->get();
I'm wondering if maybe there's a better way to pull this off. Can someone show me how it is recommended to handle this in Laravel?