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]
  • #121 / Jan 25, 2012 12:53pm

    WanWizard

    4475 posts

    You’ll have to do something about your platform.

    Even if this is going to work, DataMapper will not accept it. It needs the ‘id’ to be an integer, it uses casting (to int) or intval() at several places in the code.

  • #122 / Jan 25, 2012 12:57pm

    diZzyCoDeR

    25 posts

    balls.

    Thanks WanWizard.  Appreciate it.

  • #123 / Jan 26, 2012 5:55am

    Spir

    139 posts

    How would you sort by a join field value? Is that possible?

    $item->language->include_join_fields()->where('id', 1)->order_by('join_name', 'asc')->get();

    doesn’t seems to work. Any idea? Should I loop over my result to sort or could I sort using order_by method?

  • #124 / Jan 26, 2012 6:38am

    quasiperfect

    132 posts

    i have user and comment models

    class User extends DataMapper
    {
     var $table = 'users';
    
     var $has_many = array(
         'sent_comment' => array(
                'class' => 'comment',
                'other_field' => 'sender'
            ),
            'recived_comment' => array(
                'class' => 'comment',
                'other_field' => 'reciver'
            )
        );
    
        function __construct($id = NULL)
        {
     parent::__construct($id);
        }
    }
    
    class Comment extends DataMapper {
        var $table = 'comments';
        var $has_one = array(
            'sender' => array(
                'class' => 'user',
                'other_field' => 'sent_comment'
            ),
            'reciver' => array(
                'class' => 'user',
                'other_field' => 'recived_comment'
            )
        );
        var $has_many = array(
            'relatedcomment' => array(
                'class' => 'comment',
                'other_field' => 'comment'
            ),
            'comment' => array(
                'other_field' => 'relatedcomment'
            )
        );
    
        function __construct($id = NULL)
        {
     parent::__construct($id);
        }
    }

    the tables

    CREATE TABLE `users` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `username` varchar(15) NOT NULL,
      PRIMARY KEY (`id`),
      UNIQUE KEY `username` (`username`),
      UNIQUE KEY `id` (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    CREATE TABLE `comments` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `sender_id` int(10) unsigned NOT NULL,
      `reciver_id` int(10) unsigned NOT NULL,
      `text` text NOT NULL,
      PRIMARY KEY (`id`),
      UNIQUE KEY `id` (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    CREATE TABLE `comments_relatedcomments` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `comment_id` int(10) unsigned DEFAULT NULL,
      `relatedcomment_id` int(10) unsigned DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    CREATE TABLE `comments_users` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `sender_id` int(10) unsigned DEFAULT NULL,
      `sent_comment_id` int(10) unsigned DEFAULT NULL,
      `reciver_id` int(10) unsigned DEFAULT NULL,
      `recived_comment_id` int(10) unsigned DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

    i can add users without any problems

    $user_a = new User();
    $user_a->username = "user_a";
    $user_a->save();
    
    $user_b = new User();
    $user_b->username = "user_b";
    $user_b->save();

    how can i add a comment from user_a to user_b and save ?
    how can i add a comment from user_b to user_a as a replay to the previous comment and save ?

    edit : if anyone looked at the unedited version i corrected some errors so please look again

  • #125 / Jan 26, 2012 11:42am

    WanWizard

    4475 posts

    How would you sort by a join field value? Is that possible?

    Looking at the code, the DM version of order_by() always prefixes the field with the current table name, unless it is already prefixed.

    So ordering on a field in a join table should be possible if you prefix it with the alias of the join table.

    You could work around it by replacing the order_by() method by

    public function order_by($orderby, $direction = '', $escape = TRUE)
    {
     $escape and $orderby = $this->add_table_name($orderby);
     $this->db->order_by($orderby, $direction);
    
     // For method chaining
     return $this;
    }

    And then pass FALSE as third parameter if you don’t want to prefix the field with the table name.

    If this works for you, let me know and I’ll add it to the next release.

  • #126 / Jan 26, 2012 12:55pm

    Spir

    139 posts

    Many thanks for your great help WanWizard. It works like a charm. I actually ended working the other way around:

    $item = $language->item->include_join_fields()->order_by('items_languages.name', 'asc', FALSE)->get();

    Awesome 😊

    Also we could have something like this (maybe not as good in term of perf):

    public function order_by($orderby, $direction = '')
     {
      if (count(explode('.',$orderby)==0))
         $escape and $orderby = $this->add_table_name($orderby);
      $this->db->order_by($orderby, $direction);
    
      // For method chaining
      return $this;
     }
  • #127 / Jan 26, 2012 3:12pm

    WanWizard

    4475 posts

    Better then the extra parameter.

    In the end I did this:

    strpos($orderby, '.') === FALSE AND $orderby = $this->add_table_name($orderby);

     

  • #128 / Jan 29, 2012 1:12am

    Mark Price

    24 posts

    I’m having problems with the cascading deletion (auto cleanup) on one to many relationships. Rather than deleting the records in the relation table it is setting the foreign key to NULL. However, the auto cleanup works fine with my many to many relation tables.

    This could be a tricky situation because there could be times when you would want it to NULL the value. For instance you might want to delete a Country but not all of the Users associated to that Country and there are times when you could have child records that are dependent on a single parent record and when the parent is deleted the children are deleted as well.

    Is there a way to mark a one to many relationship as dependent or not?

  • #129 / Jan 29, 2012 5:41am

    WanWizard

    4475 posts

    Not at the moment. The next version will introduce a belongs_to relation, to indicate this dependency.

    As to your problem, from a technical point of view, there is no difference in cascading deletes between a one-to-many and a many-to-many. In both cases the record on the other side has the foreign key and must be deleted. In case of a one-to-many, that is the record itself, in case of a many-to-many it is the relationship record.

    You just do

    $parent = new Parent();
    $parent->get_by_id(1);
    
    $parent->delete();

    or are you doing something differently?

  • #130 / Jan 29, 2012 7:55am

    iScotts

    3 posts

    Hi everyone.. I am new to codeigniter and ORM’s so i am interested in trying this one. My question is, in order to use this must I already have existing tables in my DB? or can it create them for me from the definitions set in the models?

  • #131 / Jan 29, 2012 11:49am

    WanWizard

    4475 posts

    DataMapper doesn’t create tables, but then again it also doesn’t have any definitions set in the models… 😉

  • #132 / Jan 29, 2012 7:47pm

    Mark Price

    24 posts

    Not at the moment. The next version will introduce a belongs_to relation, to indicate this dependency.

    As to your problem, from a technical point of view, there is no difference in cascading deletes between a one-to-many and a many-to-many. In both cases the record on the other side has the foreign key and must be deleted. In case of a one-to-many, that is the record itself, in case of a many-to-many it is the relationship record.

    You just do

    $parent = new Parent();
    $parent->get_by_id(1);
    
    $parent->delete();

    or are you doing something differently?

    It is setting my foreign keys to NULL in my one to many relations but, I think Datamapper is supposed to and I would prefer that it delete these records.

    Here is my setup:

    class Countries_model extends DataMapper
    {
        public $table = "countries";
        public $has_many = array(
            'users' => array(
                'class' => 'users_model',
                'other_field' => 'country',
                'join_self_as' => 'country',
            ),
        );
    }
    
    class Users_model extends DataMapper
    {
        public $table = "users";
        public $has_one = array(
            'country' => array(
                'class' => 'countries_model',
                'other_field' => 'users',
                'join_other_as' => 'country',
            ),
        );
    }
    
    $Country = new Countries_model();
    $Country->get_by_id('1');
    $Country->delete();

    After doing some debugging and checking the condition in function delete() that is doing the update NULL this is what I get:

    // We have to just set NULL for in-table foreign keys that
    // are pointing at this object
    if($relationship_table == $object->table  && // ITFK
             // NOT ITFKs that point at the other object
             ! ($object->table == $this->table && // self-referencing has_one join
                in_array($other_model . '_id', $this->fields)) // where the ITFK is for the other object
            )
    {
    
    echo $relationship_table . '
    '; // outputs: users
    echo $object->table . '
    '; // outputs: users
    echo $this->table . '
    '; // outputs: countries
    echo $other_model . '
    '; // outputs: users
    print_r($this->fields); // outputs: array([0] => id [1] => country)
    exit;

    Shouldn’t the “!” be removed from the second part of the condition so that it reads:

    if($relationship_table == $object->table  && // ITFK
             // NOT ITFKs that point at the other object
             ($object->table == $this->table && // self-referencing has_one join
                in_array($other_model . '_id', $this->fields)) // where the ITFK is for the other object
            )
  • #133 / Jan 30, 2012 4:30am

    WanWizard

    4475 posts

    This code has been in DataMapper for as long as I can remember.

    Looking at the delete() method in general, I’m not happy with that code at all. Ideally, you want cascading deletes to work, period. No matter what kind of relationship it is, and no matter how deep it goes.

    Currently, if you have a self-relationship, it doesn’t delete. And if you have a parent-child-grandchild type of relation, it deletes the children when you delete the parent, leaving the grandchildren in an orphant state (due to the delete query on the relation, which doesn’t look further than the direct relation).

    Ideally, to do this properly, you have to fetch the related records, and call delete() on them, so they can cascade as well. Downside is that it might be a lot of instantiations and queries, and therefore slow, but I think in terms of database consistency, this is what you want.

    Also, when you disable cascading deletes now, Datamapper doesn’t do anything. This was done so that you could implement ON CASCADE on the table, but there is no way to say “I don’t want to delete, just break the relation”. Which is basically the difference between as “has” relation and a “belongs_to” relation.

    I’m not sure what should be done about this. I would prefer postponing this for 2.0, which will be a complete rewrite anyway.

  • #134 / Feb 01, 2012 4:23am

    Spir

    139 posts

    Some people on the IRC asked for help with setting CI 2.1.0 + HMVC + Datampper 1.8.2
    So I made a boostrap. Here is a link:
    http://www.mediafire.com/?0sxux8p46dvdduw

    Hope it helps.

  • #135 / Feb 01, 2012 8:05pm

    toadies

    8 posts

    Hello, I’m working on trying to create a has_many relations with multiple tables and I think I found a solution, but since I’m very new at this I want to see if this is really a realistic way of doing this.

    My tables

    customers ->
      id,
      first_name,
      last_name,
      ect….
    
    equipments ->
      id,
      equipment_type,
      equipment_group
    
    manufacturers ->
      id,
      name
    
    customers_equipments ->
      id,
      customer_id,
      equipment_id,
      model_name,

    What I want to acheive is a list of all equipment types and related manufacture / model for each customer_id.

    for example:

    [ equipment name ][manufacturer][model name]
      Pump              haywood       super pump
      Filter            Generic       1000
      Light             NULL          NULL

    I can do with with a SQL query, but I was trying to avoid that and use the great ORM I have learned about.  Here is my code.

    Customer, Equipment, and Manufacturer class has a $has_many relations with customers_equipments.

    customers_equipment.php model

    <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
    
    class Customers_equipment extends DataMapper {
    
     var $has_one = array('customer','equipment','manufacturer');
     var $has_many = array();
     
     var $validation = array();
    
     function __construct()
     {
      parent::__construct();
     }
     
     function getManufacturerText()
     {
      $this->manufacturer->get();
      
      return $this->manufacturer->name;
     }
    }

    the controller

    function index()
     {
      $c = new Customer();
      $c->get(1);
      
      $e = new Equipment();
      $e->get();
    
      echo "first name: " . $c->first_name . "
    ";
      foreach($e as $equip)
      {
       $c->customers_equipment->get_where(array('equipment_id' => $equip->id));
       
       echo "Equipment Type: " . $equip->equipment_type . " id: " . $equip->id . "
    ";
       echo "Manufacture Name: " . $c->customers_equipment->getManufacturerText() . "
    ";
       echo "Model: " . $c->customers_equipment->model_name . "
    ";
      }
     }

    The results is

    first name: Christopher
    Equipment Type: Pump id: 1
    Manufacture Name: Hayward
    Model: Turbo Jet
    Equipment Type: Booster Pump id: 2
    Manufacture Name: Pentair
    Model: Filter 10000
    Equipment Type: Filter id: 3
    Manufacture Name:
    Model:
    Equipment Type: Heater id: 4
    Manufacture Name:
    Model:

    I get my results, but I want to know if this is the best way or is there an easy way for ORM to do this for me.

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

ExpressionEngine News!

#eecms, #events, #releases