-1

Here is what the table might look like

Store

  • id
  • modelable_id
  • modelable_type
  • name
  • other columns

Shoe

  • id
  • sole_id (FK)
  • other columns

Cloth

  • id
  • jean_id (FK)
  • other columns

Bag

  • id
  • cover_id (FK)
  • other columns

The model relationships for the parent model and related models


class Store extends Model
{
    /**
     * Get the store <Cloth|Bag|Shoe>
     */
    public function modelable()
    {
        return $this->morphTo(__FUNCTION__, 'modelable_type', 'modelable_id');
    }
}

class Shoe extends Model
{
    /**
     * Get the store that owns the shoe.
     */
    public function store()
    {
        return $this->morphOne(Store::class, 'modelable');
    }
}

class Cloth extends Model
{
    /**
     * Get the store that owns the cloth.
     */
    public function store()
    {
        return $this->morphOne(Store::class, 'modelable');
    }
}

class Bag extends Model
{
    /**
     * Get the store that owns the bag.
     */
    public function store()
    {
        return $this->morphOne(Store::class, 'modelable');
    }
}

When a store model is retrieved i want it to use

sole_id in Shoe instead of id
jean_id in Cloth instead of id
cover_id in Bag instead of id

by default laravel expects the foreign keys to be named the same thing

3
  • 2
    You can customize the related column names when you define the relationships in your models using all the optional parameters. Aside from that, your question is unclear. Commented Jun 9, 2024 at 22:46
  • there is no way to specify the related column for all the related models has all the related models have different foreign keys Commented Jun 9, 2024 at 23:06
  • 1
    Read the documentation: laravel.com/docs/11.x/…. All of the morph<One|To|Many>() methods accept multiple arguments that allows you to override these columns if they differ from standard naming conventions. Since you didn't include any actual code in your question (i.e. your methods and usage of these relationships), there isn't much else we can help you with. Please edit your question and include more details if you want more/better help. Commented Jun 10, 2024 at 1:34

1 Answer 1

1

I understand what you're trying to do, but it's not a good idea.

The 4th parameter of the morphto method is $ownerKey. That is the parameter you want to change.

class Store extends Model
{
    public function modelable()
    {
        return $this->morphTo(__FUNCTION__, 'modelable_type', 'modelable_id', 'shoe_id');
    }
}

If you have a Store record that looks like this:

{
    ...,
    "modelable_type": "App\Models\Shoe",
    "modelable_id": 5,
    ...
}

Then the query you're going to make every time you load the modelable relationship will be

SELECT * FROM shoes WHERE shoes.shoe_id IN (5)

The problem? If your modelable_type is not "App\Models\Shoe", then the query stops making any sense. For example, if modelable_type was "App\Models\Cloth" instead, the query would still try to find a shoe_id column.

SELECT * FROM clothes WHERE clothes.shoe_id IN (5)

You could mitigate this by defining a different morphTo relationship for each modelable_type you're expecting to have but it's not going to be very pretty in the long term.


If your problem is caused by not having an id column in the shoes table, I'm afraid the only solution I can give that does not involve altering the definition of that table is adding a virtual id column.

Sign up to request clarification or add additional context in comments.

1 Comment

using virtual column that matches all 3 table is the solution i later went for in order to be in compliant with laravel conventions

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.