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 ORM v1.8.2

November 30, 2011 3:43pm

Subscribe [100]
  • #556 / Jul 14, 2012 5:03am

    WanWizard

    4475 posts

    Datamapper doesn’t support three-way relationships, so you can’t do this.

    You can work around that my making a model for the relationship table, and convert the many-to-many between users and friends to one-to-many’s with this new model. You can then make a one-to-many between the new model and relationships.

    You can then run your queries from the perspective of this new model. To make it easier you could add some helper methods to this new model, for example:

    public function all_friends_of_user($userid)
    {
        // get the friends of this user as friend model objects
        $this->where('user_id', $userid)->include_related('friend', NULL, TRUE, TRUE)->get();
    
        // $this->friend now contains all related friends
        return $this;
    }
  • #557 / Jul 14, 2012 6:31am

    coldKingdom

    30 posts

    Datamapper doesn’t support three-way relationships, so you can’t do this.

    You can work around that my making a model for the relationship table, and convert the many-to-many between users and friends to one-to-many’s with this new model. You can then make a one-to-many between the new model and relationships.

    You can then run your queries from the perspective of this new model. To make it easier you could add some helper methods to this new model, for example:

    public function all_friends_of_user($userid)
    {
        // get the friends of this user as friend model objects
        $this->where('user_id', $userid)->include_related('friend', NULL, TRUE, TRUE)->get();
    
        // $this->friend now contains all related friends
        return $this;
    }

    Thank you for a quick answer!

    I ended up with the code

    $friends = new Friend();
    $friends->select('friend_id');
    $friends->where('user_id', $id);
    $friends->where('approved', '1');
    $friends->include_related('user', array('first_name', 'last_name'));
    $friends->include_related('relationship', array('title'));
    $friends->get();
  • #558 / Jul 16, 2012 7:41pm

    coldscooter

    50 posts

    Hi, is there a why to quickly check if there are any changes to the stored values while making a save on a model object?

    I basically want to intercept the save() method in the model and do a check to see if there are any changes.

    Thanks in advance.

  • #559 / Jul 17, 2012 2:47am

    WanWizard

    4475 posts

    No. But Datamapper does this check internally, and won’t run an UPDATE query if nothing has changed.

    It does that by doing:

    // Convert this object to array
    $data = $this->_to_array();
    
    // Prepare data to send only changed fields
    foreach ($data as $field => $value)
    {
     // Unset field from data if it hasn't been changed
     if ($this->{$field} === $this->stored->{$field})
     {
      unset($data[$field]);
     }
    }
    
    // Only go ahead with save if there is still data
    if ( ! empty($data))
    {
     // Update existing record
     $this->db->where('id', $this->id);
     $this->db->update($this->table, $data);
    }
  • #560 / Jul 17, 2012 4:30am

    To Doctor WanWizard,

    Its a very nooby question to ask but kindly tell me why should i migrate to datamapper rather than using the built in CI active record ?
    Cuz i found the development time in DM to be far more than the CI’s AC(which is a query builder actually).

    thank you and waiting for your reply…...........

  • #561 / Jul 17, 2012 5:09am

    WanWizard

    4475 posts

    Short answer: if that is the case then you’re doing something wrong. 😉

    Most common mistake: use Datamapper as a glorified query builder. I see this happen with (probably) most people that use an ORM, maybe not supprising as most documentation hints at using it that way.

    What I mean with that is that you have code like this in your controller:

    $u = new User();
    $u->where_related('project/task/status', 'label', 'completed')->get();

    which basically isn’t much different then using a normal QB, albeit probably less complex as the ORM will abstract the complex joins behind it.

    Instead, you should still use the Model as intended in the MVC architecture, which is to abstract your data interaction away from your controller. So given the exampla above, your model should contain a method like

    public function get_by_project_status($status = 'completed')
    {
        // reset the current object
        $this->clear();
    
        // run the query
        $this->where_related('project/task/status', 'label', $status)->get();
    
        // return the object for chaining
        return $this;
    }

    and then in your controller use

    $u = new User();
    $u->get_by_project_status('open');

    Note that this is just an example, you’d probably will make the methods a bit more generic, and you might include some post-processing as a well (for example array conversions for dropdowns)...

  • #562 / Jul 17, 2012 6:15am

    cahva

    662 posts

    Hi,

    I have a REALLY annoying problem with identifiers. This might not be DM related but maybe someone can shed some light because I’m frustrated as hell.

    I have multiple sites, they are CI 1.7.2 and use the same symlinked system and application(for most parts) directories so no conflicts with different versions.

    When running this on 2 different sites(both with same DM(1.8.0) and CI). It has lots of other stuff going on before this(subqueries etc.) but this is the relevant one:

    echo $products->order_by_func('IF', '@special_price IS NOT NULL, special_price, price', $pr_data['order_dir'])->where('active',1)->get_sql();

    Working site gives this:

    SELECT products.*, products_description.name AS products_description_name, products_description.description AS products_description_description, products_description.key AS products_description_key, products_description.language_id AS products_description_language_id, tax.amount AS tax_amount, (SELECT product_specials.price
     FROM (product_specials)
     WHERE `product_specials`.`customer_group_id` = '1'
     AND product_specials.product_id =products.id
     AND  (
      (
     `product_specials`.`date_start` = '0000-00-00'
     OR `product_specials`.`date_start` <= '2012-07-17'
     )
     AND  (
     `product_specials`.`date_end` = '0000-00-00'
     OR `product_specials`.`date_end` >= '2012-07-17'
     )
     )
     LIMIT 1) AS special_price
    FROM (products)
    LEFT OUTER JOIN products_description products_description ON products.id = products_description.product_id
    LEFT OUTER JOIN tax tax ON tax.id = products.tax_id
    WHERE `products_description`.`language_id` = 1
    AND `products`.`active` = 1
    ORDER BY IF(special_price IS NOT NULL, special_price, products.price) asc

    Non-working site gives this:

    SELECT `products`.*, `products_description`.`name` AS products_description_name, `products_description`.`description` AS products_description_description, `products_description`.`key` AS products_description_key, `products_description`.`language_id` AS products_description_language_id, `tax`.`amount` AS tax_amount, (SELECT `product_specials`.`price`
     FROM (`product_specials`)
     WHERE `product_specials`.`customer_group_id` = '1'
     AND product_specials.product_id =products.id
     AND  (
      (
     `product_specials`.`date_start` = '0000-00-00'
     OR `product_specials`.`date_start` <= '2012-07-17'
     )
     AND  (
     `product_specials`.`date_end` = '0000-00-00'
     OR `product_specials`.`date_end` >= '2012-07-17'
     )
     )
     LIMIT 1) AS special_price
    FROM (`products`)
    LEFT OUTER JOIN `products_description` products_description ON `products`.`id` = `products_description`.`product_id`
    LEFT OUTER JOIN `tax` tax ON `tax`.`id` = `products`.`tax_id`
    WHERE `products_description`.`language_id` = 1
    AND `products`.`active` = 1
    ORDER BY IF(`special_price` IS NOT NULL, `special_price`, `products`.`price)` asc

    The actual error will come from the last ORDER BY line with `products`.`price)`. But the non-working query also has identifiers all over the place and this is puzzling me. Database, datamapper and other configs are identical so what possibly could cause this kind of behaviour?

    I’ve made the fix stated here also but it has no effect to the identifiers at all and working site works without the fix no problem.

     

  • #563 / Jul 17, 2012 6:50am

    WanWizard

    4475 posts

    Datamapper’s order_by() is an alias for $this->db->order_by(), all escaping happens in the CI database layer.

    So either both applications use a different system folder (using different database code) or you’re using two different database drivers (and there is a difference in escaping between both). I can’t think of any other reason why this could happen.

  • #564 / Jul 17, 2012 10:12am

    cahva

    662 posts

    I found the problem! Files were exactly the same so it was not that.

    In the other site I used “bestsellers”-addon, which had this in the model(non-datamapper):

    $this->db->select("COUNT(product_id) pr_count,product_id",false)->order_by('pr_count','DESC')->limit($limit)->group_by('product_id');

    The earlier query worked for the other site as this little line has the “false” set as second parameter in the select method and from this query on, the rest of the queries are affected and are without(or are MOSTLY without) identifiers.

    Maybe time to upgrade CI(and DM) for our eCommerce maybe? 😊

  • #565 / Jul 19, 2012 1:40pm

    coldscooter

    50 posts

    I’m having trouble using include_related().

    If i’m doing something like:

    $user->include_related(‘address’);

    I get results only for users that have a address record. But i would like to see all users even if they have no address record, and just show null values if the address is missing.

    Could someone help?

  • #566 / Jul 19, 2012 2:24pm

    WanWizard

    4475 posts

    It does a ‘LEFT OUTER’ join, and that can’t be changed (it’s hardcoded).

    Reason for it is that you’re asking for users with a related address.

  • #567 / Jul 19, 2012 3:05pm

    coldscooter

    50 posts

    I having an issue when running a GET() after having run a SAVE().

    After the save we then want to use the same object to run an additional query, with a new where array.

    What i’m finding is, after the save, there are lots of additional ‘where’s added to the object so that once i reuse the object for a new GET, I end up with malformed sql statement.

    Is this a bug? Am i able to reuse the object without creating a new one?

    [edit:]
    I’m running a where_related before the SAVE(). Example:

    $this->users->where_related('comment', 'id', $this->current_user->id);
    $this->users->save($some_object);
    
    $this->users->include_related('blog_posts')
    $this->users->where(array('id'=>1));
    $this->users->get();

    [edit:]
    Sorry, i’ve realised that this issue was being caused by having incorrect relationships set up in the model. Apologies for the hasty post.

  • #568 / Jul 23, 2012 9:50am

    Netstrike

    6 posts

    Hi, it’s possible to load a datamapper model into a library?
    How can i do?

    Tnx
    Ettore

  • #569 / Jul 23, 2012 11:01am

    WanWizard

    4475 posts

    Datamapper comes with it’s own autoloader, so this will work anywhere:

    // load a datamapper model
    $model = new Modelname();
  • #570 / Jul 23, 2012 2:23pm

    Netstrike

    6 posts

    I have tried it, but the result is (in the error log of apache):

    PHP Fatal error:  Allowed memory size of 33554432 bytes exhausted (tried to allocate 65488 bytes) in C:\\Users\\netstrike\\Desktop\\UniServer\\www\\Project\\application\\third_party\\datamapper\\bootstrap.php on line 358, referer: http://localhost/

    ... the 358 line in the bootstrap file doesn’t exist… the bootstrap have only 91 lines…

    The library enter in loop ad reload itself…

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

ExpressionEngine News!

#eecms, #events, #releases