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]
  • #376 / Dec 16, 2008 9:42pm

    OverZealous

    1030 posts

    The only way you can have multiple relationships with the same model / table is to either create virtual models (that use the same table, etc, but have a different model name), or to create an in-the-middle object that makes the extra connections.

    To handle the virtual user:
    Create a new model called, for example, Author:

    class Author extends User {
       var $table  = 'users';
    }

    Add a new “author_id” column to your join_<whatever>_users.  This is absolutely necessary.  Also, make sure that your “author_id” and “user_id” columns allow NULL!

    Modify any class that needs an author as well as a user by adding both to the $has_one or $has_many columns.

    Now you can look up your Authors using $obj->author->get().

    (I just wrote this off the top of my head, so you’ll probably find typos.)

    (Also, in the future, you might just want to describe your models, or maybe be a little more selective in what you post…)

  • #377 / Dec 16, 2008 9:49pm

    tdktank59

    322 posts

    i figured i was too general lol…

    But thanks thats i guess the problem im having so!!!

  • #378 / Dec 17, 2008 12:21am

    empoleon

    5 posts

    I’m getting an error I think is caused by the ‘singular’ function in inflector_helper.php

    DataMapper is changing my model’s singular name “Address” to “addres”

    Error Number: 1054
    
    Unknown column 'addresses_companies.addres_id' in 'on clause'

    The singular function accepts $str=“Address” as an argument and returns “addres”, with the last “s” missing.

    The ‘address’ Model:

    class Address extends DataMapper {
        
        var $table = 'addresses';
        
        var $has_one = array('company');
        
        function __construct()
        { 
            parent::DataMapper();
        }
        
    }

    The DataMapper user guide says (I think) that the inflector helper is not called if the $table var is set in the Model—which I’ve done.

    Quote:

    If you don’t supply the $table variable, DataMapper will automatically assume the table name is the same as your model name, in lowercase, with the letter s on the end (which will be the case most of the time).

    Since $table was set in the Model I thought DataMapper presumes the column in the joining table is the same as the Model name (Model: Address, Joining table column: address_id)

    Should I edit inflector_helper.php to handle singular words ending in “ess” or did I set this up wrong-?-hmm

  • #379 / Dec 17, 2008 12:26am

    OverZealous

    1030 posts

    Simpler solution:
    Add this to your model:

    $model = 'address';

    All set!

  • #380 / Dec 17, 2008 1:53am

    empoleon

    5 posts

    @overzealous—Yep, setting $model in the Model did the trick.  Now I don’t need to brush up on inflection science. Thx!

  • #381 / Dec 17, 2008 11:08am

    dmyers

    43 posts

    Is there any way to use datamapper not using Database Normalization with the Fifth normal form?

    Love datamapper but my customer already has there database setup. Adding the extra tables it’s going to fly with them.

    For example there user table joins to the roles table since each user can only be in 1 role.

    they join direct from users to roles using users.role_id -> roles.id.

    I noticed you can put in your own queries with $object_model->query($sql); but that kind-a makes datamapper’s other great features useless.

    Am I missing something or can this just not be done?

    Don Myers

  • #382 / Dec 17, 2008 12:41pm

    OverZealous

    1030 posts

    No, it can not be done with DM as is.  That’s how DM works — it requires a very strict database format.  Most ORM schemes do.

  • #383 / Dec 17, 2008 1:24pm

    dmyers

    43 posts

    No, it can not be done with DM as is.  That’s how DM works — it requires a very strict database format.  Most ORM schemes do.

    Ok that’s a bummer. I have used CakePHP’s ORM and CodeIgniter’s IgnitedRecord and both support joining tables without the “extra” table/overhead where it makes sense. I think Propel does it as well but I don’t want to tackle that at this time! I started to look into DataMapper because I like the validation (which is like CakePHP) and the fact they seem more like “objects” then CodeIgniter’s IgnitedRecord.

    Guess it’s back to IR for this project.

    Are there any others?

  • #384 / Dec 17, 2008 4:36pm

    Iverson

    153 posts

    It is a bug, but it’s in CodeIgniter 1.7.0.

    The the Installation Instructions in the DataMapper User Guide says before installing DataMapper you need to install the latest SVN version of the MySQL Driver.  The instructions on how to do that is in the Troubleshooting section.

    This will prevent the…

    A Database Error Occurred
    
    Error Number: 1054
    
    Unknown column 'table.*' in 'field list'

    ...type of error.

    This took me 3 days to figure out! AHHHHHHHHHHHHHHHHHHH!  :shut:  Thanks…

  • #385 / Dec 18, 2008 8:06pm

    tdktank59

    322 posts

    Allright so im still having issues

    Basically everything but getting to the user works… I can pull the user_profile but cant get to the user. But the trick is I need to have 2 “users” a contact and an updated_by (see image below)


    Heres the database layout for what im using

    http://img218.imageshack.us/img218/6756/viewtp1.png

    Heres my models for DM
    I would have copy pasted them but there’s a 6k word limit…
    http://421entertainment.com/models.zip

  • #386 / Dec 19, 2008 3:25am

    beemr

    160 posts

    I have used CakePHP’s ORM and CodeIgniter’s IgnitedRecord and both support joining tables without the “extra” table/overhead where it makes sense.

    Guess it’s back to IR for this project.

    Are there any others?

    I like the ActiveRecord_Class_Mod Development version.  Even though it hasn’t been updated in almost a year, it’s essentially feature competitive with the newer CI ORMs and even has an edge with its chained joins and “magic” like sum, concatenate, and count.  As for your main concern, has_one and belongs_to do not need a join table.  No validation, though, but CI’s config validation is a pretty good alternative.

    If you try it, please post your comparison v. IR.  I might be taking a look at IR for its nested set hierarchy feature.

  • #387 / Dec 19, 2008 6:15am

    ntheorist

    84 posts

    okay i’ve had some time so i’m making an attempt again to add join functionality to the new version of DM. It seems like i’m making some good progress, so i thought i’d post what i’ve got so far, to see if it works for anyone. It seems like it works better now than in my previous attempt, due to stensi’s great handling of statically storing model data.

    Anyway, I’m trying to work in these methods to allow joining relations (one and many) plus joining counts of ‘has_many’ relations in a single query, at the same time easily being able to use the where, order_by, and other query types. Additionally, even though its not 5nf, a lot of people seem to want to use foreign keys. And in some cases it makes sense, like having a generic set of keys on many models (i’ve got ‘created_by’ and ‘updated_by’ as foreign ‘user’ ids, but i don’t want to have to create two separate linking tables for each model that uses them)

    new methods are:

    join_related($model = NULL, $fields = array(), $alias = '', $count_many = TRUE)
    join_count($model) // Only works on has_many items
    join_key( $field_name = NULL, $model = NULL, $fields = array() )

    now instead of running get() on every relation, you just specifiy

    $user = new User();
    $user->join_related('userclass');
    $user->get();
    
    foreach($user->all as $u) 
    {
         echo $u->userclass->name; // Works just like you ran $u->userclass->get();
         echo $u->userclass->rank;
    }

    with join_related and join_key, you can speicify the fields (to cut down on db load), or leave it blank and all fields from the joined table will be included. The ID field is enforced in all cases. The join key function uses table aliasing to prevent name collisions, and turns the field into a model, so:

    $post = new Post();
    $post->get();
    echo $post->created_by; // echos '1', or whatever id the user is;
    
    $post = new Post();
    $post->join_key('created_by','user', array('id','username','email'));
    $post->get();
    echo $post->created_by->username; // echos the user's username
    echo $post->created_by->email; // you get the idear

    also i added

    where_count($relation, $value = NULL, $condition = '=');

    which, in conjunction with join_count, or join_related on a has_many item (with count_many set to TRUE), you can specify results based on number of relations

    $user = new User();
    $user->join_count('post');
    $user->where_count('post',10,'>');
    $user->get(); // Gets users with more than 10 posts

    there are a few additional functions as well in there. I changed the _to_object method to load_query_result(), which functions a bit differently, and i’ve had to rework several db methods, but now you can use where() and order_by() with relations that have been joined, just like regular fields

    $user->join_related('userclass','name'); // Joins userclass model with only id & name
    $user->where('userclass','admin','name'); // Selects where userclass.name = admin 
    $user->get();

    only thing is if the third parameter (field to search) in the where clause isn’t speicified, it assumes you’re searching against the id. The same thing goes for joined_key fields

    $user->join_key('created_by','user','username');
    $user->where('created_by','commandercool','username');
    $user->get(); // Gets users created by username 'commandercool';
    
    // or
    
    $user->join_key('created_by','user');
    $user->where('created_by',3); // Assumes ID
    $user->get(); // Gets users (fields id & username) created by user ID 3

    So, other than that, i also modified the _to_array() function to spit out a complete array with relations, has_many counts, and joined keys etc..

    All of this is done in single-query fashion as well. I know it’s adding some to memory consumption, etc, but i think it pays back in database performance. I was also trying to be careful not to mess with too much of the code, so everything else should work just fine. That being said, i also haven’t extensively tested it, and i’m sure more modifications might be needed in the remaining AR methods to account for the joins.

    I’m not going to post every one of the added vars, functions and changes I made, plus this is still a work in progress, so i’ll just attach the DataMapper file i’ve got so far and let anyone who wants to play with it, do just that.

    cheers,

    CC

  • #388 / Dec 19, 2008 5:06pm

    dmyers

    43 posts

    Thank you for taking the time to investigate foreign key joins. Your example of created_by and updated_by are perfect examples of why 5nf seems like a overkill. I will take the time tonight (and/or this weekend) to test this.

    D Myers

  • #389 / Dec 19, 2008 5:47pm

    ntheorist

    84 posts

    cool, let me know if it works for you and whatever probs you may run into, and please keep in mind it could be buggy in some cases.. i’m still testing it out and addressing things here and there.

    I agree, 5nf is demanding but is meant to make organization more efficient and less abstract, and i’m not trying to break away from that too much.

    That being said, key joins are useful, and i don’t think it’s betraying the original idea too much given that, 1) all key joins require the ‘id’ column, as enforced by DM table structure and 2) each join is to another datamapper model, which remains unknowing of the foreign key columns.

    anyway thx for the feedback, cheers

    cc

  • #390 / Dec 20, 2008 12:50pm

    Murodese

    53 posts

    Would something like the following work?

    $obj_list[] = $temp_obj->get()->all;
    $obj_list[] = $some_other_obj->get()->all;
    $obj_list[] = $and_another->get()->all;
    
    $obj = new Something();
    
    $obj->name = 'fred';
    
    $obj->save($obj_list);

    I’m building a crud form automator (very similar to Django’s) but checkboxes/multiple relations are frustrating me.

    e; obviously there’d be where clauses on the objects but you get the idea

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

ExpressionEngine News!

#eecms, #events, #releases