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]
  • #766 / Apr 23, 2009 9:34pm

    OverZealous

    1030 posts

    @Peet86
    Sorry, I just don’t know how to help you here.  Most likely the only way you are going to get DataMapper (or DMZ) to work with what you want is to change your structure, or rethink your design.


    @nmac
    You can perform normal ActiveRecord-like queries with DM and DMZ.  DMZ lets you include fields that are not on the table (such as “COUNT(column) as column_total”), and you can use the normal group_by to group your query rows.

    I’m not sure you will benefit much speed by trying to do this, however, unless your DataBase is on another server and not connected to the same LAN.  Remember that the counting is done on the server either way.

    I really think just calling $tag->article->count() will be pretty fast, easier to read, and save you the headache of maintaining a custom command if things get changed later.

  • #767 / Apr 23, 2009 9:54pm

    nmac

    8 posts

    Phil,
    thanks for the reply, really appreciated.
    I think I have a standard query that will give me what I want, but I think I have lost my way in terms of using it with DMZ?
    Here is what I have…

    // test function
            function test()
            {
                // Trying to get all tags with a count of their use in articles.
                $t = new Tag();
                $sql = "SELECT tags.tag, count(articles_tags.id) as thecount FROM tags
                LEFT join articles_tags
                ON articles_tags.tag_id = tags.id
                GROUP BY tags.id
                ORDER BY thecount";
                $t->query($sql); 
                
                foreach ($t->all as $tag)
                    {
                        echo $tag->tag . '::'.$tag->thecount .            '
    ';
                        // hmm not quite?
                    }
            }

    The query itself seems to be right, in that when I run it in phpmyadmin I get what looks about right. But the code above is flawed? Do you have an example of using a custom count field in a result?
    Cheers
    N.
    [EDIT] ok, some more fiddling, and the addition of the id for tags and I seem to be on to it.

    $sql = "SELECT tags.id, tags.tag, count(articles_tags.id) as thecount FROM tags
                LEFT join articles_tags
                ON articles_tags.tag_id = tags.id
                GROUP BY tags.id
                ORDER BY thecount";

    If there is an easier way using DM/DMZ notation, any ideas would be great!!
    Thanks again!
    N.

  • #768 / Apr 23, 2009 9:56pm

    warrennz

    56 posts

    Forcing DM(Z) to save instead of deciding of save or update is required? I need to keep old relationships for historys sake. Eg user is on subscription x, then upgrades to subscription y, then later downgrades to subscription x again. Typically DM(Z) will UPDATE the original relationship with subscription x. Where as I want to keep 3 seperate records of those relationships.

    I was thinking I could add a secondary method force_save(). This would set $this->force_save = true and then simply call $this->save() as per normal. In the _save_related() method just check for the flag and decide depending on that flag status?

    Can anyone foresee any major problems with doing that?

  • #769 / Apr 23, 2009 10:24pm

    camporter1

    22 posts

    If I have a DataMapper class named ‘Profile’, and I also have a controller named ‘Profile’, will this cause problems?

  • #770 / Apr 23, 2009 10:31pm

    camporter1

    22 posts

    Actually, it does cause problems. How might I specifically ask for one or the other? Or maybe I should rename my controller to make things easier?

  • #771 / Apr 23, 2009 10:40pm

    warrennz

    56 posts

    @camporter1

    You’re correct. If you have a controller or a library named the same as your model, they are called first.

    Typically I rename my controllers and then use URI routing to keep URI’s nice and pretty.

  • #772 / Apr 23, 2009 11:26pm

    OverZealous

    1030 posts

    @nmac
    When you are running custom queries in DM, you always must include the id column.  DataMapper uses the ID as the index for the all array.

    What happens otherwise is you only get one result, since they all have the “id” of null

    @warrennz
    No, you never have to force DM to update instead of insert.  If you have specified a relationship as has_one, then there can only be one copy of that relationship.  That’s the point of has_one.  If you want multiple relationships, then use has_many.

    If you need to keep track of just one older, I recommend creating a second has_one to manage it (DMZ makes this extremely easy, and you just need to add another column.)

    If you need multiple relationships, then you’ll need to either create a dedicated model to represent those relationships, or use DMZ and join_fields to manage those relationships.

    With DMZ, you can set the relationship up as has_many, then add one or more columns on the join table.  You can then query against those columns.  There’s an example in my document of how to use it to keep track of who’s seen an alarm that is assigned to multiple users.

    @camporter1
    Just to clarify what is happening, PHP doesn’t have classpaths, so every class is identified uniquely by its name.  This is why most DM users use “Object” for the model and “Objects” for the controller.  It still looks good, and is easy to read.  It’s only a problem if you have “Moose” or “Deer” models. 😉

  • #773 / Apr 23, 2009 11:37pm

    warrennz

    56 posts

    @OverZealous

    Mhmm, its a little tricky. I originally wanted it to force insert, not force update. But basically I had a 1:N relationship but need to be able to insert the exact same relationship time and time again. If my user id was 1, and my item id was 2, that would typically create an update on the second time I ran a save(); (or no action) as that relationship would have existed already. I needed it to insert every time regardless of existing identical relationships.

    But as always, thanks again 😛

  • #774 / Apr 23, 2009 11:39pm

    naren_nag

    81 posts

    Is it possible to reset your data, or set up a temporary database, and try inserting 200 items (via code, of course).  Just to see if it is repeatable?

    Do you have any related validaters?

    Can you manually insert another row into the table?

    As warrennz mentioned, turn on CodeIgniter’s profiling, and look at the exact queries being run.


    Ok guys,

    I just woke up ... and I have a plan:

    1. Rewrite the controller (well, not totally rewrite, but you get the idea 😊
    2. Add 200 records (via code)
    3. See if the problem comes up again.

    Expect to hear from me sometime in the next 24 hours. I’m off on a holiday to a place called Goa in India—beaches etc. and will be coding from there.

  • #775 / Apr 23, 2009 11:43pm

    OverZealous

    1030 posts

    @warrennz
    I recommend using a dedicated model to track those, then.  The problem with what you are doing is that there is no way for DataMapper to tell each row apart, since it only uses model1_id and model2_id.

    By having a dedicate model, you can track each relationship multiple times.  Of course, it can make queries trickier, but if you are using DMZ, they might work pretty well (using same-table has_one fields).

    Good luck, and please let me know what you decide to do!

    @naren_nag
    I’m jealous of your holiday with beaches 😛

  • #776 / Apr 23, 2009 11:47pm

    warrennz

    56 posts

    @OverZealous
    Mhmm, that makes alot of sense. It’s almost as if I don’t need a 1:N rel. I mean, there is one account, and many items attached to it which is technically 1:N. However I would only EVER be accessing the most recent one, or in any case only ever accessing 1 depending on passed date values.

    So maybe despite the obvious 1:N rel I should just do 1:1 ? Would that be back practice?

    Mhmm

    Beaches are good 😊

  • #777 / Apr 24, 2009 12:00am

    OverZealous

    1030 posts

    @warrennz
    I don’t have an answer to whether that would work for you or not.  In my experience, the best thing to do is to only store the information that you need to store.  The more data and relationships you store, the more complex maintenance will be.

  • #778 / Apr 24, 2009 12:04am

    warrennz

    56 posts

    Yea

    The app I’m creating is a usercp for the ISP I work at. The customer needs to be able to login and essentially go back in time and see what their account was like at that time (eg what plan they were on,speed/datacap etc). So, the items (plans) need to be stored historically. So I’mm not too sure how I could store any less data but I definitely hear what you’re saying. Some of the relationships that currently exist are a bit of a nightmare, hehe - will have to go back and some point and have a bit of a clean up

    Ta

  • #779 / Apr 24, 2009 12:13am

    OverZealous

    1030 posts

    I think one good, clean solution is to do what I said above, about having a dedicated object to store the relationships.

    Say this:
    You have Users, Plans, etc.

    Create a model called PlanLog (or whatever).  PlanLog has single relationships to User and Plan, as well as a start and end date.  (Edit: I forgot to mention, User and Plan have many relationships to PlanLog.)

    Optionally, don’t store an end date on the current one, so you can quickly look it up { $planlog->where('enddate', NULL) }.  Alternatively, store the most recent directly on User, as described at the bottom.

    You can also create relationships to any other changes you need to track historically.

    Then to get the history (using DMZ), you can do something like this:

    $pl = $user->planlog;
    $pl->join_related('plan', array('id', 'name', 'speed', 'cap'));
    // repeat for anything else you need to print out
    
    $pl->order-by('enddate DESC');
    $pl->get(); // you can paginate like normal, here
    
    // $pl->all should have all of the changes, ordered by date
    // $pl->plan_name, $pl->plan_speed, etc, will contain plan info

    That solves the problem nicely, I think, and you can still get the latest fairly quickly.  If you need, go ahead and store the most plan directly on the User model.  Since it is stored as a $has_one, it will automatically replace any old ones.  Then just add a new PlanLog for every change.

  • #780 / Apr 24, 2009 12:47am

    warrennz

    56 posts

    @OverZealous
    Thanks a bunch, your replys are invaluable. I’ll have a go at it next time I’m working on it.

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

ExpressionEngine News!

#eecms, #events, #releases