Welcome Guest, Not a member yet? Register   Sign In
self-referencing relationship is not working using datamapper
#11

[eluser]johnmerlino[/eluser]
Thanks for response.

I am trying to save multiple relations:


Expectations:
1) New Category record is created (let's call it subcategory but in reality no where is subcategory mentioned in database)
2) The new category gets auto incremented to categories table and is given values for controller, user_id, enabled_comments fields passed from the query string of a http post request via the php form
3) An existing category is searched (let's call it parent category but in reality no where is parent category mentioned in the database)
4) A new record is written to the categories_related_categories table where category_id refers to the primary key of the new category created and related_category_id refers to the id of the existing category we searched. Hence we create a many to many self-referencing relationship where a subcategory can have many categories and a parent category can have many subcategories
5) A category can have many zones and a zone can have many categories. A user has the option to select one or many zones from a multiselect dropdown. If user selects two zones (each of them have a name using a name field like 'main' or 'panel'), for example, then when the new category is written to the database, not only is a parent category established with it in the categories_related_categories table, but a many to many is established in the categories_zones table, where two records are created (if the user selects two options from multiselect), one record has the primary key of the new category with the one zone record selected from multiselect and the second record again has the primary key of the new cateogry with the other zone record selected from the multiselect.

So it's the subcategory that has the relation with the parent and the zone(s):

Code:
public function create(){
            $vanity_url = new VanityUrl();
            $vanity_url->where('url',$this->uri->segment(2))->get();
            $blogger = new User();
            $blogger->where('id',$vanity_url->user_id)->get();
                        
            /* self-referencing many to many */            
            $subcategory = new Category; //subcategory - we create a new one
            $subcategory->controller = $this->input->post('controller');
            $subcategory->enable_comments = $this->input->post('approved');
            $subcategory->user_id = $this->current_user()->id;
            
            $parent_category = new Category(); //parent category - we find via a search in the table
            $parent_category->where('controller',$this->input->post('parent_controller'))->get();
        //    $subcategory->save($parent_category);
            
            /* many to many - category has many zones :: zone has many categories */
            $zone = new Zone();
            $zones = $this->input->post('zones');

            foreach($zones as $z){
                switch($z){
                    case 'main':
                        $zone->where('name',$z);
                        break;
                    case 'panel':
                        $zone->where('name',$z);
                        break;
                }
            }
            $zone->get();
              
            $subcategory->save(
        array(
            'related_category' => $parent_category,
            $zone
       )
            
        }

But the above doesn't work. It correctly saves the relationship between the two categories in the categories_related_categories table. But it doesn't write anything to the categorie_zones table. It should be doing both.

So I did a little simple experiment:

Code:
$c = new Category();
            $c->controller = 'hi';
             $z = new Zone();
            $z->where('name','main');
            $z->where('name','panel');
            $z->get();
            $c->save($z);
            $c->check_last_query();
            //INSERT INTO `categories` (`controller`) VALUES ('hi')
            
            $c = new Category();
            $c->controller = 'hi';
             $z = new Zone();
            $z->where('name','main');
             $z->get();
            $c->save($z);
            $c->check_last_query();
            /*
            INSERT INTO `categories` (`controller`) VALUES ('hi')

            INSERT INTO `categories_zones` (`category_id`, `zone_id`) VALUES (109, 1)
            */

There's a glitch or something when trying to grab two records using the where function twice as in the first example. I want to select two zone records and associate them with the new categories record so two records would be created in categories_zones:

Code:
categories_zones
category_id  zone_id
1            1
1            2
allowing us to associate the one category with the two zones.

But as you can see, using where() twice to get two objects and then trying to associate it with the one categories object does not do this.
And I followed this documentation:

http://datamapper.wanwizard.eu/pages/save.html

Thanks for response.
#12

[eluser]johnmerlino[/eluser]
This does exactly what I want to happen:

Code:
$zones = $this->input->post('zones');

            foreach($zones as $z){
                switch($z){
                    case 'main':
                        $a = new Zone();
                        $a->where('name',$z)->get();
                        $subcategory->save($a);
                        break;
                    case 'panel':
                        $b = new Zone();
                        $b->where('name',$z)->get();
                        $subcategory->save($b);
                        break;
                }
            }

            $subcategory->save(
                array(
                'related_category' => $parent_category
                )
            );

But as you can see, it doesn't look nice that I have to call save three times. I'm sure there's a better way.

Thanks for response.
#13

[eluser]WanWizard[/eluser]
Assuming that zones is an array, you should be able to do
Code:
$a = new Zone();
$a->where_in('name', $zones)->get();
$subcategory->save( array($a->all, 'related_category' => $parent_category));
#14

[eluser]johnmerlino[/eluser]
Thanks for response, your alternative worked, although while the html element is a multiselect, it's not guaranteed that the user will select more than one item, but nevertheless zones itself will always be an array:

echo form_multiselect('zones[]',$divisions,'none');

It's just not guaranteed any elements will be passed into it.
#15

[eluser]WanWizard[/eluser]
If that's the case you need to validate it, since Datamapper calls CI's database class' where_in() method, that doesn't check for empty array's.
#16

[eluser]johnmerlino[/eluser]
Thanks for helpful response.




Theme © iAndrew 2016 - Forum software by © MyBB