Love Fuel?    Donate

FuelPHP Forums

Ask your question about FuelPHP in the appropriate forum, or help others by answering their questions.
A dumb question about many-to-many models
  • Hi there,

    I know this may be a real simple question but I could not find an answer. Let's say I have a many-to-many relationship as follows:

    1. A student 'subscribes' to book(s)
    2. A book may be 'subscribed' to by many users.
    3. Models exist for 3 things: users, books and books_users.

    My question is: In which model do I specify the function for retrieving the books a certain user has 'subscribed' to along with the details.

    Thanks for your time.
  • Hello Khalid,

    there's actually just two models involved for this relationship, one being Model_User and the other being Model_Book. There is no need for a Model_Subscribers or Model_Book_User or alike because a many_many relationship uses a through_table (defined in many_many['subscribers']['table_through']). That's probably where you've got confused

    Side note: You can use a model for books_users if you want to store some more information on the relationship e.g. created_at or how many times the user has read the book. That's implemented in the OrmAuth package for users, roles, groups, user_permissions, role_permissions, group_permissions, and permissions. Here, {user,role,group}_permissions is both the through table of a many_many relationship as well as its own model because it stores the assigned actions.
  • I'm sorry, I still don't completely understand. From a database point of view, I understand that the table is required.

    1. Are you telling me that I don't need to define the model 'books_users'? I've scaffolded most of the system so I'm getting this directory structure for the model in question:

    model/books/user.php


    2. If I don't need this model, where do I specify the query?

    Thanks so far.
  • Harro VertonHarro Verton
    Accepted Answer
    Correct. You define the relations between the models, ORM is smart enough to know there is a junction or relation table (either determined from the model names, or because you specify the table in the relation).

    You only need the additional model if you also store attributes in the relation table, instead of only the keys. Which technically will turn your many-2-many into two one-2-many relations.

    For the query it's transparent:

    // get all students in class $class, and their book subscriptions for books published in 2014
    $result = Model_Student::query()->related('book')->where('class', '=', $class)->where('book.year', '=', '2014')->get();


  • Okay, I tried the following in the book model:

    public static function get_books_for_user($username) {
    $result = Model_Book::query()->related('user')->where('user.username','=',$username)->get();
    return $result;
    }


    But I get the following error:
    UnexpectedValueException [ Error ]:
    Relation "user" was not found in the model.


    Any ideas? Thanks so far.
  • Obviously, the error message means that you are trying to access a relationship that has not been defined on the model. To define relationships, you define them in any of the respective properties listed below
    protected static $_has_one = [];
    protected static $_has_many = [];
    protected static $_belongs_to = [];
    protected static $_many_many = [];

    After that, you can access these relationships using Model::query()->related(). Have a look at http://fuelphp.com/dev-docs/packages/orm/relations/intro.html for more info on relating models.
  • I have the following set in the 'book' model:
    protected static $_many_many = array(
    'users' => array(
    'key_from' => 'id',
    'key_through_from' => 'book_id',
    'table_through' => 'books_users',
    'key_through_to' => 'user_id',
    'model_to' => 'Model_User',
    'key_to' => 'id',
    'cascade_save' => true,
    'cascade_delete' => false,
    )
    );


    And the following in the 'user' model:
    protected static $_many_many = array(
    'books' => array(
    'key_from' => 'id',
    'key_through_from' => 'book_id',
    'table_through' => 'books_users',
    'key_through_to' => 'user_id',
    'model_to' => 'Model_Book',
    'key_to' => 'id',
    'cascade_save' => true,
    'cascade_delete' => false,
    )
    );


    Did I get something wrong here? Thanks for the help so far.
  • Your setup for the relations looks good. And I think it's just a typo thing. Look again at how you've defined the relationships and what you are calling in your query()-call ;)
  • I got it, Alhamdulillah. The problem was indeed a typo :), the edited answer is :

    $result = Model_Book::query()->related('users')->where('users.username','=',$username)->get();

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion