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.

[Deprecated] DMZ 1.6.2 (DataMapper OverZealous Edition)

November 23, 2009 11:54pm

Subscribe [46]
  • #436 / Mar 09, 2010 2:24pm

    GregX999

    39 posts

    I’ve hit (another) bump.

    I have a PressItem model that has_many PressImage models. I want to be able to “foreach” through all of the images that belong to a specific item, and I want to do it in a specific order given by an array of PressImage ids.

    So, with an example PressItem id of 2, an SQL query might be:
    SELECT * FROM pressimages WHERE pressimage.pressitem_id = 2 ORDER BY FIELD (pressimage.id,4,1,3,2);

    Can I do that with DMZ somehow? I’m not sure if using “order_by_func” is what I want, or if I need to use the “query” function like:

    $pressitem = new PressItem();
    $sql = "SELECT * FROM pressimages WHERE pressimage.pressitem_id = 2 ORDER BY FIELD (pressimage.id,4,1,3,2)"
    $pressitem->pressimages->query($sql);
    
    foreach($pressitem->pressimages){ ... }

    :grrr:

  • #437 / Mar 09, 2010 3:22pm

    OverZealous

    1030 posts

    @GregX999

    Out of curiosity, in what situation would you need an order that is not stored in the database?  It seems like the issue might be solved more correctly without using the MySQL-only ORDER BY FIELD clause.

    At any rate, you can try this:

    $pressitem = new PressItem($press_item_id);
    $pressitem->pressimage->order_by_func('FIELD', '@id',4,1,3,2, ' ');

    That might work.  You must include the last value, as stated in the manual.  Due to the fact that CodeIgniter requires ASC or DESC, it might not work.  If you need a dynamic list of ids to sort on, you can do this:

    $args = array('@id') + $ordered_ids;
    $pressimage->order_by_func('', array('FIELD' => $args), ' ');
    
    // Alternatively, this might be required instead
    $args = array('FIELD') + $args;
    $args[] = ' ';
    call_user_func_array(array($pressimage, 'order_by_func'), $args);

    Or, you might be able to just make your life simpler:

    $pressimage->order_by('FIELD (pressimage.id,4,1,3,2)', ' ');

    None of this has been tested, you might have to tweak it to get it working.

    FYI: You kinda confused me with the relationship stuff, as I thought this was a related item issue.  For future reference, you can add any query clause on top of a basic relationship query.

  • #438 / Mar 09, 2010 4:35pm

    GregX999

    39 posts

    I need to select the images in a specific order so I can iterate through them and update their “position” field. The position field is used to order them when they are being displayed. I’m using drag-n-drop sorting w/ AJAX so an admin can sort them, and when an item is drag-dropped, the new sequence is sent through AJAX. And since there are multiple pressitems, I only want to re-sequence the images that belong to the item being edited.

    So I ended up going with this:

    $pressimage->query("SELECT * FROM pressimages WHERE pressitem_id={$pressitem->id} ORDER BY FIELD(id,{$images_in_order})");
    
    $i = 1;
    foreach ($pressimage->all as $image) {
        $image->position = $i;
        $image->save();
        $i++;
    }

    I just couldn’t get any of the other things to work because of CI putting single quotes around everything.

    Greg

  • #439 / Mar 09, 2010 4:38pm

    OverZealous

    1030 posts

    @GregX999

    Just flip the problem around, this is by far more efficient, because you don’t need to sort the query at all:

    // assume $order is array of sorted IDs
    $order = array_flip($order);
    
    $pressitem->pressimages->select('id', 'position')->get();
    
    foreach($pressitem->pressimages as $pressimage) {
        $pressimage->position = $order[$pressimage->id];
        $pressimage->save();
    }

    Edit: added the select limiter to the query, to increase performance.

    Edit2:
    Hey, new PHP function for me: array_flip!

  • #440 / Mar 09, 2010 4:50pm

    GregX999

    39 posts

    Brilliant!! It works perfectly, and is SO much cleaner!

    I was unaware of array_flip() as well.

    The only change I made was:

    $pressimage->position = $order[$pressimage->id] + 1;

    So that the position field goes from 1 to X instead of 0 to X.

    Thanks!
    Greg

  • #441 / Mar 09, 2010 5:10pm

    OverZealous

    1030 posts

    So that the position field goes from 1 to X instead of 0 to X.

    Ah, good catch!  I think in my application I’m using 0-based sorting just so I don’t have to worry about it.

    I love PHP, I hate PHP.  I love that it has so much random stuff. 😊  I hate that so much of it is random.  😊

    Part of it is the frustration going from an OOP language (Java) where I can have a collection and instantly see all of the functions for an array in my IDE.  In PHP, you just have to already know the name, or guess it.  And, of course, while many of the array functions are array_{whatever}, but the some functions are just {whatever}.  Ach!

    If anyone is using the NetBeans IDE for development, the PHP Manual Search plugin is very useful.

  • #442 / Mar 10, 2010 9:12am

    NachoF

    171 posts

    Im not sure if this is DM related but… Im having a problem connecting to database… on my localhost I cant connect to postgresql database but I can connect just fine to my mysql database…. when I try with postgre I get a blank page immediately… here are my two configs so you can see exactly what I changed.
    This works

    $db['default']['hostname'] = "localhost";
    $db['default']['username'] = "root";
    $db['default']['password'] = "12345";
    $db['default']['database'] = "mydatabase";
    $db['default']['dbdriver'] = "mysql";
    $db['default']['dbprefix'] = "";
    $db['default']['pconnect'] = TRUE;
    $db['default']['db_debug'] = TRUE;
    $db['default']['cache_on'] = FALSE;
    $db['default']['cachedir'] = "";
    $db['default']['char_set'] = "utf8";
    $db['default']['dbcollat'] = "utf8_general_ci";

    This doesnt

    $active_group = "default";
    $active_record = TRUE;
    
    $db['default']['hostname'] = "localhost";
    $db['default']['username'] = "postgres";
    $db['default']['password'] = "12345";
    $db['default']['database'] = "mydatabase";
    $db['default']['dbdriver'] = "postgre";
    $db['default']['dbprefix'] = "";
    $db['default']['pconnect'] = TRUE;
    $db['default']['db_debug'] = TRUE;
    $db['default']['cache_on'] = FALSE;
    $db['default']['cachedir'] = "";
    $db['default']['char_set'] = "utf8";
    $db['default']['dbcollat'] = "utf8_general_ci";

    I wish it could at least give me some kind of error

  • #443 / Mar 10, 2010 5:43pm

    OverZealous

    1030 posts

    @NachoF
    This will have nothing to do with DMZ.  I use DMZ with PostgreSQL almost exclusively.

    Most likely you have PGSQL misconfigured for accepting IP connections.  Make sure you have TCP enabled, make sure your pg_hba file is set up correctly, double-check your port, etc.

    Again, DMZ doesn’t do anything special to connect to the databasem it’s all CodeIgniter there.  You’ll want to ask about this on a different forum if my suggestions below don’t help.

    I wish it could at least give me some kind of error

    That’s because CodeIgniter suppresses DB connection errors for some odd reason.  Edit the postgre_driver.php file and remove the @ from before pg_connect and pg_pconnect.  Then you’ll see connection errors.

    That stupid @ caused me no end of headaches when I thought my DB was timing out, and it was actually an intermittent DNS issue.

    Finally, if this is a production environment with more than a handful of users, I recommend looking into PGPOOL-II, which takes about 10 minutes to set up, and then don’t use pconnect, because you will have issues on busy servers.  DMZ 1.7.0 (which is basically done, I just need to update the docs, package it, and release it) has some tricks in place to really help cut down on the number of DB connections.

  • #444 / Mar 12, 2010 2:01pm

    hidechron

    3 posts

    Hi codeigniter forums o/

    I’m working on some relations, and i can’t figure how can i do a relation within a relation. Maybe that’s just wrong but it’s the best way I found.

    Here a schema to illustrate what i’m trying to do (used cakeapp.com, nice to vizualise db)
    http://uppix.net/b/0/4/60ea097e6eab821b9182465cc8ac6.jpg
    I’m simply trying to make the DMZ model of “games_users”.
    Basically it says “Users have this game in that category”.
    So I’ve done the obvious part:

    class User extends datamapper
    {
        var $has_many = array('game', 'category', 'tags');
        ...
    class Game extends Datamapper
    {   
        var $has_one = array('developer');
        var $has_many = array('user', 'tags', 'category');
        ...

    (I removed the non relevant relations nor in the screen for clarity.)

    And I browsed the really good DMZ documentation but i can’t figure at all if I can do something like this or even another way.

    Can I have some help here, please ?

  • #445 / Mar 12, 2010 5:51pm

    OverZealous

    1030 posts

    @hidechron
    I’m not sure what you want, but there’s two possible answers:

    If you only want one copy of each game per user, but want to assign different categories based on the user:
    You can use Join Fields to store the category on the join itself.  For example, add a category_id column to the join table, then you can include use column in your queries.  It’s not very elegant.


    If you are trying to allow a user to have several copies of the same game stored in different categories:
    DMZ only supports one relationship between two objects.  The solution is to create an interim model that handles the more complex connections:

    User has many User_categories
    User_category has one User

    User_category has one Category
    Category has many User_categories

    User_category has many Games
    Game has many User_categories

    User_category is simply an object to handle the connection.

    Then you can use Deep Relationships to build your query, like so:

    // list games for this user and category
    $games = new Game();
    
    $games->where_related('user_category/category', 'id', $_POST['category_id']);
    $games->where_related('user_category/user', $logged_in_user);
    
    // add in sorting, additional parameters, etc.
    $games->group_start(); // only needed if you are adding OR'd query params
    $games->like('name', $search);
    $games->or_like('description', $search);
    $games->group_end();
    
    $games->order_by('name');
    
    $games->get();

    That’s a single query that handles querying all games for a given user based on a specific category.  You can see how you can add additional query parameters as well.

    It can be a more complicated issue when adding and removing connections:

    // removing examples.  Adding is similar
    
    // easy first, remove the entire category
    $user_category = $user->user_category->where_related('category', 'id', $category_id)->get();
    // just delete the interim object, which removes all connections at once
    $user_category->delete();
    
    // removing a game from a category
    $game = new Game($game_id);
    $user_category = $user->user_category->where_related('category', 'id', $category_id)->get();
    // just break the connection
    $user_category->delete($game);
    
    // harder, remove all copies of a game from a user
    $game = new Game($game_id);
    $user_category = $user->user_category->where_related('game', $game);
    foreach($user_category as $uc) {
        $uc->delete($game);
    }

    Well, that became much more extensive than I had originally planned.

  • #446 / Mar 12, 2010 7:19pm

    hidechron

    3 posts

    Thank you, that helped a lot.

    At first I was simply aiming at your first solution, and although I already read the join_fields function, I still overlooked it, thinking it was like a SQL join, for absolutely no reason.

    But cause on the best scenario I wanted users to be able to catalog the game they played in the category they need, meaning a game could be added to different categories. (ex: Mario in -NES-, and also in -completed-)

    So I went for a solution more (or exactly?) like your second one.
    http://uppix.net/7/2/c/aba98b355728e69f0231a5ae074e1.jpg
    The join table named “categories_games” risk to end being really massive but since it’s only id’s, that may do it.

    But for now it’s late, I’ll study this more closely tomorrow hoping the light is getting closer 😊.

  • #447 / Mar 15, 2010 12:18am

    OverZealous

    1030 posts

    Version 1.7.0 has been just been released

    This is a major update to DMZ!

    Not only does it include these fantastic new features:
      • Automatic Localization - I just snuck that one in…
      • Amazingly easy Paged Queries
      • New methods for streaming query results
      • PHPDoc documentation has been added for almost every magic method, which can be used for code-hints in an IDE
      • A brand-new extension for finding the row of a given object or id
      • And a whole lot more features.

    But this version includes a staggering number of small performance improvements than, when added up, can reduce page processing time by as much as 50% (even on simple pages!), and reduce memory overhead by nearly as much, especially when combined the new get_iterated method!

    There also have been a variety of bug fixes, and tweaks throughout the code base.

    Make sure to check out the changelog — you won’t want to skip this update!

    PLEASE DISCUSS VERSION 1.7 HERE

    Download the Latest Version Here

      View the change log and the upgrade process
      Having issues? Please look through the Troubleshooting Guide & FAQs
      View the Complete Manual
      Search the Manual
      (Due to the server’s caching configuration, you may need to forcibly refresh your browser to see the changes in the manual.)

  • #448 / Mar 15, 2010 2:40pm

    Wazzu

    27 posts

    DMZ already uses LAST_INSERT_ID

    Sorry guys, but how do I get LAST_INSERT_ID after a save() call?
    I can find nothing in the user guide.

    Thanks very much

  • #449 / Mar 15, 2010 2:42pm

    OverZealous

    1030 posts

    @Wazzu

    $User = new User();
    $user->name = 'Bob Smith';
    $user->save();
    echo $user->id;
  • #450 / Mar 15, 2010 3:01pm

    GregX999

    39 posts

    Oooo… I’ll need to get v1.7.

    But, before I do, I have a question: Should this work?

    $x = $category->product->where('product.id', $product_id)->count();

    Thereby setting $x equal to the count?

    My Category model has:

    var $has_many = array('product')

    But I get the error:
    Fatal error: Class name must be a valid object or a string in /blaa/blaa/blaa/application/libraries/datamapper.php on line 1730

    Greg

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

ExpressionEngine News!

#eecms, #events, #releases