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]
  • #586 / Feb 23, 2009 4:38pm

    OverZealous

    1030 posts

    @tdtank

    Nothing in my code should cause there to be more queries than before.  The piece you are using simply uses a different “join” table (no table, in this case).

    DataMapper has always run a query every time you call ->get().  Since each type of user is related differently, it is going to be a different join.

    There really isn’t a way in SQL to query multiple objects in different relationships into the same result set, especially without losing the “meaning” of the relationship.  So, if the same user is related as “editor” and “creator”, that user will be queried twice.

    I can look into seeing if there is a practical way of looking through the relationships and seeing if the same object is already loaded, but that probably won’t be terribly efficient, especially since these primary key queries.

    @DominixZ
    As it says in the manual, you can delete multiple relationships using one call.  However, that is completely unnecessary in your case, because calling $bookmark->delete() automatically deletes all relationships (also mentioned above, in red).  You don’t even have to ->get() the related items:

    $bookmark = ...
    // delete bookmark and all relationships (but not the related items themselves)
    $bookmark->delete();
  • #587 / Feb 23, 2009 6:22pm

    tdktank59

    322 posts

    Sounds good now I at least understand what its doing lol!

  • #588 / Feb 25, 2009 11:35am

    quasiperfect

    132 posts

    i’m new to datamapper, actually is my first use and i don’t understand something why the code

    $u = new User();$u->get_by_email('a');if ($u->exists()){echo 'k'}

    generates 2 queries

    SELECT * FROM `users` LIMIT 1 
    SELECT * FROM (`users`) WHERE `email` = 'a'
  • #589 / Feb 25, 2009 1:03pm

    tdktank59

    322 posts

    Ill try and awnser this but I may be wrong…

    It does 2 queries because the first one gets the user object setup/populated then the second query limits the results based on what you want to get.

  • #590 / Feb 25, 2009 1:24pm

    quasiperfect

    132 posts

    why use 2 queries ? when it could simply do

    SELECT * FROM (`users`) WHERE `email` = 'a' LIMIT 1

    i’m traing to understand if is a advantage using datamapper but if it uses more queries then normal code i don’t understand where’s the advantage

  • #591 / Feb 25, 2009 1:31pm

    tdktank59

    322 posts

    Well first off its in a fully managed object.

    Im not exactly sure id wait until Overzealous or someone else can answer your question.

    In my opinion it just makes everything easier as far as relations, management, validation etc…
    To lets say check a username to see if its already taken You can do this from any controller throughout the CI site. (this is just a basic example but it shows what im talking about.

    $u = new User();
    $u->check_username($username)
    or
    $u = new User();
    $u->username = $username;
    if ($u->check_username())
    {
    // No username exists
    }

    Then in the User model

    function check_username()
    {
    $u = new User();
    $u->where('username',$this->username)->get();
    
    // Check to see if the rest of the object was populated
    if ($this->id)
    {
    // Looks like the username already exists
    return FALSE;
    }
    else
    {
    // Looks like the username dosnt exist
    return TRUE;
    }
    }
  • #592 / Feb 25, 2009 3:07pm

    cupacup

    2 posts

    SOLVED!! The name of table was wrong. scopredmet_uporabniki is the right way, uporabniki_scopredmet wrong.


    Hello!

    I have following problem, when i want’t to save relations(has_many)

    Fatal error: Call to a member function num_rows() on a non-object in C:\projekti\iam\streznik\htdocs\system\application\libraries\datamapper.php on line 2560

    var dump of variable query

    Object CI_DB_mysql_result extends CI_DB_result (
      ->conn_id = Resource [mysql link persistent] ( Resource id #33 )
      ->result_id = Resource [mysql result] ( Resource id #76 )
      ->result_array = Array 0 (
      )
      ->result_object = Array 0 (
      )
      ->current_row = Integer ( 0 )
      ->num_rows = Integer ( 0 )
      ->row_data = Null
      CI_DB_mysql_result methods: 19 (
        ->num_rows();
        ->num_fields();
        ->list_fields();
        ->field_data();
        ->free_result();
        ->_data_seek();
        ->_fetch_assoc();
        ->_fetch_object();
        ->result();
        ->result_object();
        ->result_array();
        ->row();
        ->set_row();
        ->row_object();
        ->row_array();
        ->first_row();
        ->last_row();
        ->next_row();
        ->previous_row();
      )
    )

    the strange thing is that Kategorije is updated, but Uporabniki is not.
    the code I’am using is

    // Nov objekt
            $sco = new Scopredmet();
            $sco->naslov=$this->input->post('naslov');
            $sco->opis=$this->input->post('opid');
            $sco->barve=$this->input->post('tema');
            $sco->objavljeno=1;
            
            // NOv objekt kategorij
            $kategorija = new Kategorije();
            $kategorija->where('id', $this->input->post('kategorija'))->get();
            
            // NOv objekt uporabnikov
            $uporabnikio = new Uporabniki();
            $uporabnikio->where_in('id', $this->input->post('uporabniki_id'))->get();
            
            $sco->save(array($kategorija, $uporabnikio));


    Model Scopredmet

    class Scopredmet extends DataMapper {
        var $table = "scopredmet";
        var $has_one = array("kategorije" => "kategorije");    
        var $has_many = array("uporabniki" => "uporabniki");
        
        function Scopredmet()
        {
            parent::DataMapper();
        }
    }

    Model Kategorije

    class Kategorije extends DataMapper {
        var $table = "kategorije";
        var $has_many = array("scopredmet");
        var $validation = array(
        array(
            'field' => 'ime',
            'label' => 'ime kategorije',
            'rules' => array('required', 'trim', 'unique', 'min_length' => 3, 'max_length' => 45)
        ),
    );
        function Kategorije()
        {
            parent::DataMapper();
        }
    }

    Model Uporabniki

    class Uporabniki extends DataMapper {
        var $table = "uporabniki";
        var $has_many = array("scopredmet" => "scopredmet");
    
        function Uporabniki()
        {
            parent::DataMapper();
        }
    }

    CI is 1.7.1 and DM from OverZealous.com dated february 17.

  • #593 / Feb 25, 2009 4:12pm

    tdktank59

    322 posts

    The way ive been able to do it is save the object first then save the relations… Only way ive gotten it to work…

  • #594 / Feb 25, 2009 5:13pm

    OverZealous

    1030 posts

    If you are saving multiple, new objects, you always have to save the objects first.  Calling $obj1->save(array($obj2, $obj3)) will only save $obj1 to the database, and the relationships between $obj1 and $obj2, and $obj1 and $obj3.

    It has to be this way, or else DM would spend a lot of time checking to see if something needs to be saved to the database.  Also, you can save relationships to non-complete objects this way:

    $obj2->select('id')->get();
    $obj1->save($obj2);

    As for the previous discussion, about the multiple queries, it’s how the field names are looked up.  You’ll only see the LIMIT 1 query once per model, as DataMapper has to determine which columns are available on the table.  This is the standard ActiveRecord process.

    If your application needs so much speed that calling one, near-instantaneous query to look up the column names is too much, then you probably shouldn’t be using PHP, much less an ORM library.

    DataMapper and other ORM libraries are designed to make developing code easier and faster.  Most knowledgeable software developers will tell you that you should worry about application design and long-term management of code before you worry about fine-tuning for speed.

  • #595 / Feb 26, 2009 2:12am

    unsub

    43 posts

    just wanted to say, this is astonishing! fantastic stuff, really; it’s inspiring for a novice like me to see something like this!

    cheers, and thank you so much :D

  • #596 / Feb 26, 2009 4:23am

    quasiperfect

    132 posts

    thanks @OverZealous.com for u’r response.
    i’m not worried about one query but i didn’t understand why the query was run.
    like i said in my first post is my first encounter with datamapper and with orm in general.
    to be honest i only tested with 5-10 lines of code (busy with a project) that run queries one time per table so i didn’t see it dose that only one time.
    i was worried that it uses extra queries for every interrogation. i will test better next time

  • #597 / Feb 26, 2009 4:29am

    OverZealous

    1030 posts

    I completely understand! :cheese:
    Feel free to ask any other questions you might have.  You’ll find, once you get used to it, that DataMapper is incredibly powerful for what it is, and allows you to produce results surprisingly fast.  It does have limitations, and you’ll probably need to work around some of them, but several of use here are still helping to fine-tune it.

  • #598 / Feb 26, 2009 6:52pm

    tdktank59

    322 posts

    So just so we can get a good example of how to save a uncomplete object with an object.

    $d = New Dqip();
    $d->version                     = set_value('version');
    $d->title                       = set_value('title');
    $d->description                 = set_value('description');
    $d->demographics                = set_value('demographics');
    $d->impact_to_organization      = set_value('impact_to_organization');
    $d->automation_options          = set_value('automation_options');
    $d->resolution_approach         = set_value('resolution_approach');
    $d->re_extraction_schedule      = set_value('re_extraction_schedule');
    $d->conversion_impact           = set_value('conversion_impact');
    $d->presented_on                = set_value('presented_on');
    $d->estimated_completion_date   = set_value('estimated_completion_date');
    $d->estimated_count_manual      = set_value('estimated_count_manual');
    $d->estimated_count_auto        = set_value('estimated_count_auto');
    $d->estimated_count_not_valid   = set_value('estimated_count_not_valid');
    $d->save();
    
    $d = New Dqip();
    $d->where('title',set_value('title'))->get();
    
    $author = new User();
    $author->where('id',set_value('author'))->get();
    
    $dciu_staff_1 = new User();
    $dciu_staff_1->where('id',set_value('dciu_staff_1'))->get();
    
    $dciu_staff_2 = new User();
    $dciu_staff_2->where('id',set_value('dciu_staff_2'))->get();
    
    $data_source_1 = New Data_source();
    $data_source_1->where('id',set_value('data_source_1'))->get();
    
    $data_source_2 = New Data_source();
    $data_source_2->where('id',set_value('data_source_2'))->get();
    
    // Save the relations
    if ($d->save( array(  'data_source_1'=>$data_source_1,
                          'data_source_2'=>$data_source_2,
                          'author'=>$author,
                          'dciu_staff_1'=>$dciu_staff_1,
                          'dciu_staff_2'=>$dciu_staff_2) ))
    {
        $data['success'] = 'Created the DQIP';
    }
    else
    {
        $data['error'] = $d->error->string;
    }

    with your example above how would be the “other” way to do this. BTW above works.

  • #599 / Feb 26, 2009 7:12pm

    tdktank59

    322 posts

    edited: ignore this post…

  • #600 / Feb 26, 2009 7:25pm

    OverZealous

    1030 posts

    In your example, just add ->select(‘id’) in to your reference lookups.  What I mean by “incomplete” objects is that you don’t bother selecting the whole row.  You will still be able to save the relationship, as long as the object has the correct ID.

    I’m not sure why you would be seeing validation errors.  What fields exactly?  I don’t think I changed the validation fields any.  Are you sure that ‘required’ isn’t getting set on these fields?  Are you setting ‘required’ on the relationships?

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

ExpressionEngine News!

#eecms, #events, #releases