CodeIgniter Forums
DataMapper 1.6.0 - Printable Version

+- CodeIgniter Forums (https://forum.codeigniter.com)
+-- Forum: Archived Discussions (https://forum.codeigniter.com/forumdisplay.php?fid=20)
+--- Forum: Archived Libraries & Helpers (https://forum.codeigniter.com/forumdisplay.php?fid=22)
+--- Thread: DataMapper 1.6.0 (/showthread.php?tid=11358)



DataMapper 1.6.0 - El Forum - 04-25-2009

[eluser]jongliko[/eluser]
Hi, I'm new to Datamapper. I'm loving it ! But I'm stuck in a little work I'm trying to do. Hope some datamapper user can help me figure out the solution.

I have 4 tables Artistes, Videos, Styles, Types. Each of this tables is link with the three others with has_many.

A video can have many artistes, many styles (rock, jazz, thriller) and many types (movie, interview, concert, clip..).

I'm trying to show recursively my data starting with the type.

Code:
$types = new Type();
$types = $types->get()->all;
        
foreach($types as $type){
        
   echo '<h3>'.$type->nom.'</h3>';
        
   $styles = $type->style->get()->all;
            
   foreach($styles as $style){

      echo '<h5>'.$style->nom.'</h5>';
          
      $videos = $type->style->video->get()->all;
            
      foreach($videos as $video){
        
          echo $video->nom;
          echo '<br>';
                  
      }
   }
}

I can't figure out How to show the videos which are in a type and in a style.

The regular query would have been something like that :

Code:
SELECT
    videos.nom
FROM
    db.videos
    INNER JOIN db.types_videos
        ON (videos.id = types_videos.video_id)
    INNER JOIN db.types
        ON (types.id = types_videos.type_id)
    INNER JOIN db.styles_videos
        ON (styles_videos.video_id = videos.id)
    INNER JOIN db.styles
        ON (styles_videos.style_id = styles.id)
where styles.id = $id_style AND types.id = $id_type;


Ideally I wanted to show the Artist who have a video in this style and in this category before the videos of the artist, but I'm already stuck here with the videos.

Thanks for your help.


DataMapper 1.6.0 - El Forum - 04-25-2009

[eluser]OverZealous[/eluser]
@jongliko
What you want to use is DataMapper's where_related method. This method allows you to query based on the joined information:
Code:
$videos->where_related_type('id', $type_id);
$videos->where_related_style('id', $style_id);
$videos->get();

You can read more about the options for querying on related objects here. Just scroll down to Get (Advanced).

For example, if you already have the type loaded in, it could look like this:
Code:
$videos->where_related($type);
And that's it!


DataMapper 1.6.0 - El Forum - 04-25-2009

[eluser]qureshi[/eluser]
Hi,

I need help again.

Here is the scenario:
A user can have many links. He can associate those links with one or many verses. A verse thus can have many links. The following relation-tables exist in the DB: links_users, links_verses, users_verses.

I know how to get all links associated with a given verse, or a given user, but how do I get only those links associated with both verse and user at the same time?

Thanks for reading,

Nadeem Qureshi


DataMapper 1.6.0 - El Forum - 04-25-2009

[eluser]qureshi[/eluser]
Hi again,

I read the documentation more closely and this seems to work:
$user->link->where_related_verse('id', $verse->id)->get();

Is it possible to donate to the DataMapper project? I would like to. This tool is priceless!

Nadeem


DataMapper 1.6.0 - El Forum - 04-25-2009

[eluser]jongliko[/eluser]
@OverZealous Thanks for your help ! I was going crazy Smile . Now I really can start working with Datamapper.


DataMapper 1.6.0 - El Forum - 04-25-2009

[eluser]NachoF[/eluser]
Ok, I have run into a big problem... Im sorry to ask for help again but Im very stuck...
I am using DMZ cause I didnt want to create new tables for each relation.
I have Event, Type, Client
Event has one Type and one Client
Type has many Events
Client has many Events
...
my events table has id, client_id and type_id... after a form I call this method... which always throws me an error that says I should call set method when updating... but Im creating a bran new Event...
Code:
function send_event()
        {
        $e = new Event();
        $c = new Client();
        $t = new Type();
        $c->where('id','1')->get();
        $t->where('id','1')->get();
        $e->save(array($t,$c));            
        }
Just in case you are wondering, those queries do produce wanted results.. its just the "$e->save(array($t,$c));" that appears to fail for me... my form is done through ajax but I doubt that has anything to do with it .

Also, my tables are InnoDB and have foreign keys.


DataMapper 1.6.0 - El Forum - 04-25-2009

[eluser]OverZealous[/eluser]
@NachoF
I believe the issue is you are not setting any fields on Event.

DataMapper needs to have at least one field set to save. If you have an object that is using all default values, you'll have to either set one of those values, OR (as I have done), create a special column just to set a value for the purpose of saving. It could be a one-character, fixed-width column.

Note: This is not in the docs. I found this out the hard way, myself.

@qureshi
I'm glad you got it working. Just so you know, if you already have $verse looked up, you can save a little bit of work typing, and loading in classes, by using this format:
Code:
$user->link->where_related($verse->id);
DataMapper can then use the table information from $verse, instead of creating a new object!

I wish I could help you with info on donating, but stensi has disappeared since February :blank: .


DataMapper 1.6.0 - El Forum - 04-26-2009

[eluser]NachoF[/eluser]
[quote author="OverZealous.com" date="1240737592"]@NachoF
I believe the issue is you are not setting any fields on Event.

DataMapper needs to have at least one field set to save. If you have an object that is using all default values, you'll have to either set one of those values, OR (as I have done), create a special column just to set a value for the purpose of saving. It could be a one-character, fixed-width column.

Note: This is not in the docs. I found this out the hard way, myself.
[/quote]
Wow, you are good, I was never gonna figure that one out... there seems to be a problem still though... I have noticed that the way datamapper is set up is that it first creates the row with the data provided and then updates the row with the ids of the related fields... the thing is, if you have InnoDB relations set up mysql wont allow the creation of the row if the client_id and type_id arent provided in the same insert query (is there any config I can change to force that behaviour?).... Im using phpmyadmin with InnoDB tables to set up the relations.... heres an image that will help you understand what I mean by InnoDb relations...
http://img19.imageshack.us/img19/5315/relation.jpg
Do you think I should start using those "internal relations" instead of innoDb relations... I do it this way to protect my database?


DataMapper 1.6.0 - El Forum - 04-26-2009

[eluser]qureshi[/eluser]
Hi OverZealous,

Thanks for the tip. I'll be sure to try it out.

Sorry to hear that Stensi has disappeared. I hope he/she is safe and well.

I ran this code a few minutes ago within my "main" controller:
Code:
//Temp: relate translations to categories
    function relate(){
                    
                     //Get all categories
                     $categories = new Category();
                     $categories->get();
                    
                     //loop
                     foreach ($categories->all as $category):
                                      
                                     //Get verses
                                     $category->verse->get();
                                    
                                     //loop
                                     foreach ($category->verse->all as $verse):
                                                      
                                                     //Get translations
                                                     $verse->translation->get();
                                                    
                                                     //loop
                                                     foreach ($verse->translation->all as $translation):
                                                    
                                                     //relate translation and category
                                                     $translation->save($category);
                                                    
                                                     //clear the object data
                                                     unset($translation);
                                                    
                                                     endforeach;
                                                    
                                                     //clear verse
                                                     unset($verse);
                                                    
                                     endforeach;
                                    
                                     //clear category
                                     unset($category);
                                                                    
                     endforeach;
                    
                     }

However, as I saw it go on, it used up almost 400MB of memory. Is this normal, or is my code poorly written? i've also tried using the $object->clear() function instead of unset(), but no noticeable difference. I also noticed trough observing the table in phpMyAdmin that rows inserted per second drops from 2000 in the very beginning to 30 towards the end. Would you know why?

If it matters, I'm using an I7 920, 6GB DDR3 at 1600MHZ and a F1 SpinPoint hdd.

Thanks,

Nadeem


DataMapper 1.6.0 - El Forum - 04-26-2009

[eluser]OverZealous[/eluser]
@NachoF
That is just a limitation on how DataMapper looks at relationships. It cannot be changed without significantly altering the codebase.

I think I mentioned in my sparse DMZ docs that you cannot have NOT NULL on related_id columns. If that column allows NULLs, (and, I suppose, you set your foreign fields to allow 0 relationships), you won't get errors.

Alternatively, if you really want to avoid all of this, you can manually set the ids on the columns. It actually works just fine:
Code:
$object->related_id = $rel->id;
$object->save();
$object->related->get(); // will load in the related object

@qureshi
Why are you "unsetting" that variable? There's nothing to unset - it's just an object reference to an object that is still in memory (in the ->all array).

PHP has poor memory management, however, most users don't have trouble unless they are trying to process hundreds of thousands of rows. stensi did some tests earlier and didn't have trouble.

I don't know how many objects you are doing, and there is no way to know from a code snippet if the error exists here or in something else you are doing.

That being said, you could probably save a lot of memory by changing what you are doing. For some reasons you are apparently trying to save every category to every translation of every verse. But you are doing it in a round about way. Instead, why not do this?
Code:
$categories = new Cageory();
$categories->get();
$translations = new Translation();
$translations->get();
// or, to ensure that there is a related verse
// $translations->where_related_verse('id >', 0)->get();
foreach($translations->all as $tran) {
    $tran->save($categories->all);
}
This generates a whole lot less objects.