ExpressionEngine CMS
Open, Free, Amazing

Thread

This is an archived forum and the content is probably no longer relevant, but is provided here for posterity.

The active forums are here.

DataMapper 1.6.0

September 05, 2008 12:32pm

Subscribe [115]
  • #631 / Mar 06, 2009 9:38am

    OverZealous

    1030 posts

    With DataMapper, you never have to worry about the relationship (join) tables!  That’s the beauty of ORM!

    Simply delete one of the two related items, and all relationship data is automatically deleted!

    Also, if you want to just delete the relationship, you call:

    // member and region are already loaded
    $member->delete($region);
    // OR this also works
    $region->delete($member);

    What’s great about something like DataMapper is that you can worry much less about the database, SQL queries, and tables.  Once the structure is set up, a lot of the work is automagically handled.

  • #632 / Mar 06, 2009 10:42am

    Billy Patel

    284 posts

    So i can do

    $members = new Members();
    $members->delete_all()

    and it will automagically delete all from the relationship table?

  • #633 / Mar 06, 2009 10:45am

    OverZealous

    1030 posts

    Yes, except you have to get them first:

    $members = new Members();
    $members->get()->delete_all();

    I’m pretty sure that will work.

    Of course, that isn’t a very efficient way to completely truncate a table.  If you are doing this often, you might want to just run the queries by hand, I think you can call truncate() using normal CodeIgniter ->db methods.

  • #634 / Mar 06, 2009 10:46am

    Billy Patel

    284 posts

    Blimey… this thing is better than i thought. 😊

    cheers!

  • #635 / Mar 06, 2009 6:02pm

    wolffc

    14 posts

    I am having an issue that I have no idea how to handle.

    I’ll use sports to help explain my issue.  Say I have a league,team, and player models

    league has many teams
    teams have one league
    teams have many players
    players have one league
    players have one team

    $league = new League();
    $league->get_by_id(1);
    
    $league->team->get();
    //this will give me all the teams in a league
    
    $league->team->player->get()
    //this will give me players for the first team, but not all teams

    How can I fill all the teams with their players instead of just the first selected team?

    I want to avoid doing the code below

    foreach(&$league->team->all as $t)
    {
    $t->player->get();
    }

    Am I doing or thinking about this completely wrong?

  • #636 / Mar 06, 2009 6:09pm

    OverZealous

    1030 posts

    There isn’t currently a way to do what you want.  In reality, that would be somewhat complex SQL code, anyway, at the very least requiring a subquery.

    When you write $team->player->get(), you are asking DataMapper to give you all players that belong the team specified by $team.

    In other words, the foreach loop is your best bet.

    If you are feeling risky, you could try the poorly documented upgrade to DataMapper I posted a while back.  It contains the ability for in-table has_one joins, meaning your Player table could have ‘league_id’ and ‘team_id’ on it, and then you wouldn’t need the join tables at all.  Then your query looks something like:

    $player = new Player();
    $player->where_in('team_id', array($team1->id, $team2->id, etc))->get();

    Also, if you are including a join to leagues for players, why not just do this?

    $league->player->get();
  • #637 / Mar 06, 2009 6:28pm

    wolffc

    14 posts

    That makes sense.  I just need to make foreign keys for the id’s i need to relate back to.  Basically adding the league and team id to the player table.

    Probably the best solution for my situation.

    Thanks.

  • #638 / Mar 10, 2009 6:45pm

    tdktank59

    322 posts

    Allright I have the need to save multiple of the same relations… So now im just trying to find the right way to do it…

    /**
     * Join permissions to a role
     *
     * @param varhcar/array $permission, $key=>$value
     *  defaults to 'id' if you do not pass an array with $key=>$value
     * @param array $role - $key=>$value to get the role object
     * @param boolean $create_role TRUE/FALSE to create the role being passed
     * @return boolean TRUE on success only
     */
    public function join_permissions_role($permission, $role, $create_role=FALSE)
    {
        if ($create_role)
        {
            $this->create('role',$role);
        }
    
        $r = new Role();
        $r->where('id',$role['id'])->get();
    
        if(!is_array($permission))
        {
            // allow for single fields
            $permission['id'] = $permission;
        }
    
        foreach ($permission as $key => $val)
        {
            $p[$i] = new Permission();
            $p[$i]->where($key,$val)->get();
        }
    
        if ($r->save($p))
        {
            return TRUE;
        }
    }

    I have no clue if the $r->save($p) would even do what I want it to do in this case…
    Otherwise how would I save the same relationships over and over again with no limitations per say.

    BTW The demo covers multiple relations but not have to save multiple relations of the same type

  • #639 / Mar 10, 2009 6:50pm

    OverZealous

    1030 posts

    There are a couple of ways to save relationships where the field is not same as the model:

    // known type
    $myObj->save_creator($user);
    
    // unknown type
    $type = 'creator';
    $myObj->save($user, $type);
    
    // saving a whole bunch:
    $user->get();
    $myObj->save($user->all, 'assignedto');
    
    // saving many different kinds of objects at once
    $myObj->save(array(
        'editor' => $user,
        'creator' => $user,
        'assignedto' => $assigned_users->all
    ));

    Is this what you wanted?

  • #640 / Mar 10, 2009 6:54pm

    tdktank59

    322 posts

    not exactly…

    So ive got a Role and many permissions that are attached to a role.

    For example

    Administrator: (role)
    - Auth/Manage (permission)
    - Auth/Delete_user (permission)
    - Auth/Edit_user (permission)

    just for some examples.

  • #641 / Mar 10, 2009 7:13pm

    OverZealous

    1030 posts

    Neither the updated version of DM nor DM itself currently support information associated with the join table, which I have to assume is what you want.

    Right now, the closest you can get is to create a dedicated “relationship object”, as I think of them, that contains the two objects and the extra relationship info.

    I use this to connect Contacts with other Contacts, for example (like Company/Employee):

    class ContactRelationship extends DataMapper {
        has_one = array(
            'parent' => array(
                'class' => 'contact',
                'other_field' => 'related_contacts'
            ),
            'contact'
        );
        // add fields, etc
    }
    
    class Contact extends DataMapper {
        has_many = array(
            'contactrelationship',
            'related_contacts' => array(
                'class' => 'contactrelationship',
                'other_field' => 'parent'
            )
        );
        // etc
    }

    Table:

    contactrelationship
        id serial PRIMARY KEY,
        parent_id integer,
        contact_id integer,
        other_junk character varying,
    etc

    Usage:

    $contact = new Contact();
    $contact->get_by_id($id);
    $contact->related_contacts->join_related('contact', array('id', 'name'))->get();
    foreach($contact->related_contacts->all as $rel) {
        echo $rel->contact_name . ' [' . $rel->contact_id . ']';
        // change contactrelationship type
        $rel->type = 'Batman';
        $rel->save();
    }
    
    // If you need to edit the related contacts, try this slight hack
    $rel_contacts = new Contact();
    // this is the *field name* of the parent side of the relationship.
    $rel_contacts->where_related('contactrelationship', 'parent_id', $contact->id);
    $rel_contacts->join_related('contactrelationship', array('id', 'type'));
    $rel_contacts->get();
    foreach($rel_contacts->all as $rel_contact) {
        echo $rel_contact->name . ' is a ' . $rel_contact->contactrelationship_type;
        $rel_contact->is_happy = TRUE;
        $rel_contact->save();
    }

    I can’t provide too much more help than that. Alternatively, you might have to rethink your design.  Maybe you can use a dedicated model to keep track of more general permissions (which is how I do it).  It depends on your needs.

    I’ve actually been thinking about how to implement join table parameters for a while, but it always ends up making everything really complicated.

  • #642 / Mar 10, 2009 8:17pm

    tdktank59

    322 posts

    NO no no lol…

    Not what i ment…

    each of the word/word were the permissions…

    heres the structure lol

    Users -> join_roles_users -> roles -> join_permissions_roles -> permissions -> page and method

    where the only one not having a join_ table is permissions having
    id
    page_id
    method_id

    otherwise the rest are joined together

  • #643 / Mar 10, 2009 9:14pm

    OverZealous

    1030 posts

    You are going to have to take a moment and ask a clearer question.  In fact, you haven’t actually asked a question yet 😛

  • #644 / Mar 10, 2009 9:25pm

    tdktank59

    322 posts

    Same question as before… How to save multiple relations of the same type…

    So i have these tables:

    Roles
    id
    name
    description
    created_on
    updated_on

    join_permissions_roles
    id
    permission_id
    role_id

    permissions
    id
    method_id
    page_id
    no_restrict

    method
    id
    name
    description

    page
    id
    name
    description

    what im trying to do is set multipe permissions to 1 role.

    So for example

    p_id is permission_id just shorted and r_id is role_id
    <b>join_permissions_roles<b>
    id   p_id   r_id
    1       1       1
    1       2       1
    1       3       1
    1       4       1
    1       2       2
    1       4       2
    1       1       3

    How do I save multiple relations of the same type (permissions onto roles) in this case…

    The demo covers saving multiple with different classes

    heres the code

    /**
    * Join permissions to a role
    *
    * @param varhcar/array $permission, $key=>$value
    *  defaults to 'id' if you do not pass an array with $key=>$value
    * @param array $role - $key=>$value to get the role object
    * @param boolean $create_role TRUE/FALSE to create the role being passed
    * @return boolean TRUE on success only
    */
    public function join_permissions_role($permission, $role, $create_role=FALSE)
    {
        if ($create_role)
        {
            $this->create('role',$role);
        }
    
        $r = new Role();
        $r->where('id',$role['id'])->get();
    
        if(!is_array($permission))
        {
            // allow for single fields
            $permission['id'] = $permission;
        }
    
        foreach ($permission as $key => $val)
        {
            $p[$i] = new Permission();
            $p[$i]->where($key,$val)->get();
        }
    
        if ($r->save($p))
        {
            return TRUE;
        }
    }
  • #645 / Mar 10, 2009 10:55pm

    OverZealous

    1030 posts

    Are you just asking how to save a one-to-many relationship?  I mean, that’s what it looks like to me.  I thought that was covered.  You just do a ->save($obj) on each one, or ->save($array_of_obj) to save them all at once.  You can also do ->save($obj->all) if $obj contains the result of a query.

    ->save($object) just saves a relation to $object.  If the relationship is a has_many, it just adds it if the relationship doesn’t already exist.  If it is has_one, it replaces any existing relationship.

    My extended DM doesn’t change this, except it allows for no join table on the has_one side of relationships.

.(JavaScript must be enabled to view this email address)

ExpressionEngine News!

#eecms, #events, #releases