faisalsharif's avatar

How to implement multiple foreign key relations matching with OR condition

items
	id
	name
	sku 
	price

similar_items
	id
	item_main_id
	item_detail_id

items

id 		name		sku			price
=====================================
1		FR1224		00001		12.9

2 		FR2607		00002		12.3

3		FR0106		00003		11.5
=====================================

similar_items

id 		item_main_id		item_detail_id
===========================================
1		1 					2

2 		1 					3

class Item extends Model
{

	public function similar_items(){

        return $this->hasMany("App\Models\Inventory\SimilarItems",'item_main_id', 'id');

   
    }                
}
class SimilarItems extends Model
{
    
  protected $with=['item'];

  public function item(){
    return $this->belongsTo("App\Models\Inventory\Item",'item_detail_id');
   }
}
class ItemController extends Controller
{

	public function getAll(Request $request)
    
    {

		$items=Item::all();

		$items->load([
		   'similar_items'
		]);
	}
}

The Result is

[
    {
        "id": 1,
        "name": "FR1224",
        "similar_items": [
            {
                "item_main_id": 1,
                "item_detail_id": 2,
                "item": {
                    "id": 2,
                    "name": "FR2607"
                }
            },
            {
                "item_main_id": 1,
                "item_detail_id": 3,
                "item": {
                    "id": 3,
                    "name": "FR0106"
                }
            }
        ]

    }
    {
        "id": 2,
        "name": "FR2607",
        "similar_items":[] 

    }
    {
        "id": 3,
        "name": "FR0106",
        "similar_items":[] 

    }
]

The Required Response

[
    {
        "id": 1,
        "name": "FR1224",
        "similar_items": [
            {
                "item_main_id": 1,
                "item_detail_id": 2,
                "item": {
                    "id": 2,
                    "name": "FR2607"
                }
            },
            {
                "item_main_id": 1,
                "item_detail_id": 3,
                "item": {
                    "id": 3,
                    "name": "FR0106"
                }
            }
        ]

    }
    {
        "id": 2,
        "name": "FR2607",
        "similar_items":[
        	{
                "item_main_id": 1,
                "item_detail_id": 2,
                "item": {
                    "id": 1,
                    "name": "FR1224"
                }
            }
        ] 

    }
    {
        "id": 3,
        "name": "FR0106",
        "similar_items":[
        	{
                "item_main_id": 1,
                "item_detail_id": 2,
                "item": {
                    "id": 1,
                    "name": "FR1224"
                }
            }
        ] 

    }
]

The Problem is i want to use Or Condition, first match with item_main_id and second match item_detail_id

0 likes
7 replies
reaz's avatar

In your relation definition , item_main_id is the foreign key linking two tables. So the linking is happening using this column name. Maybe you can use a foorloop

$items = Item::all();
foreach ($items as $item) {
        $items->similar_items = SimilarItems::where('item_main_id', $item->id)
                  ->orWhere('item_detail_id', $item->id)
                   ->get();
        }
automica's avatar

@faisalsharif As you are trying to get a list of related Item then you need to reference Item and use your similar_items table as the means to join it.

public function similarItems()
{
    return $this->belongsToMany(Item::class, 'similar_items', 'item_main_id', 'item_detail_id');
}

personally, I would change field name of item_main_id to item_id and item_detail_id tosimilar_item_id to make it clearer.

To match Laravel convention, table name should be item_item

faisalsharif's avatar

Dear Reaz

Thanks for message , your idea is good but costly , I have 6000 to 8000 products so foreach 6000 times makes cost

faisalsharif's avatar

Thanks for reply but not achieve my problem

the simple is that

Item A is similar to Item B

your is solution is perfect for above condition , but how can I achieve vice versa i.e

Item B is also similar to Item A

reaz's avatar

You can use paginate or chunk to get a smaller set of results. Depends on how you using the results, is it an api response or to blade views.

automica's avatar

@reaz

$items = Item::all();

This is not a good recommendation.

Also You filter your query before pagination otherwise you’ll get inconsistent number of results.

faisalsharif's avatar

@reaz

An API response

Actually, all data will be fetched at once then my ERP system works in offline mode

Please or to participate in this conversation.