CodeIgniter Forums
DataMapper ORM v1.8.0 - Printable Version

+- CodeIgniter Forums (https://forum.codeigniter.com)
+-- Forum: Archived Discussions (https://forum.codeigniter.com/forumdisplay.php?fid=20)
+--- Forum: Archived Libraries & Helpers (https://forum.codeigniter.com/forumdisplay.php?fid=22)
+--- Thread: DataMapper ORM v1.8.0 (/showthread.php?tid=37531)



DataMapper ORM v1.8.0 - El Forum - 05-20-2011

[eluser]Chillahan[/eluser]
Another inconsistency (hoping it's just a case of outdated documentation), where user guide says this:

Code:
For in-table foreign keys, the column must allow NULLs, because DataMapper saves the object first, and relationships later.

Yet in my test, I do have a non-NULL foreign key in the table, and it saved just fine! (other than the issue when saving again with the same value for the "unique" field) Is this no longer a concern?


DataMapper ORM v1.8.0 - El Forum - 05-20-2011

[eluser]WanWizard[/eluser]
@Chillahan,

In Datamapper, the column 'id' is required, MUST be called 'id', and must be an integer auto increment primary key. There is no way around it, the column name is hardcoded everywhere, and not easy to change (as you have noticed). This is on the roadmap though, probably for v2.0.

I'm not in favour for it though, it is against database design best practices to use data columns for primary keys, altough that's what you've been tought in school when dicussion normalisation.
If you use data columns, that means you hardcode the structure of your database into your application. Also, when you change the database stucture, you might have a migration nightmare on your hands as foreign keys might change,
You solve that by using an abstract field as primary key.

To answer your questions:
1) The field $row->id doesn't exist, you'll get a notice, and the value defaults to FALSE. $this->id != FALSE is TRUE, so the method it doesn't return FALSE.
2) You can't.
3) Datamapper uses the CI database library's transaction methods, to wrap it's operations in. This means you can not use DM transactions over multiple database operations. Use $this->db->trans...() instead to wrap it around multiple DM operations.
(some db engines, like MySQL, don't allow you to nest transactions. Starting a transaction will immediately commit the previous one).

As for the inconsistency:

If you create a new object, and you do $objectA->save($objectB), it will immediately add the ITFK to objectA if the relation is so that there is a one-to-many from A to B. However, if you just do $objectA->save(), there is obviously no relation to save, and the ITFK is set to NULL.


DataMapper ORM v1.8.0 - El Forum - 05-20-2011

[eluser]felix_[/eluser]
@WanWizard
ok i just added the validation rules with the labels to avoid the error messages.. works just fine
but i have another question
Code:
var $table ="Registrations";
    var $id;
    var $code;
    
    var $has_one = array("user");

    var $validation = array(
        'id' => array(
            "label" => "ID"
        ),
        'user' => array(
            "label" => "Registration User"
        ),
        'code' => array(
            "label" => "Code"
        ),
        'user_id' => array(
            "label" => "User ID"
        )
    );

Why i hav to add the rule user_id ??
if i miss this i will get the line errors with registration_user_id


DataMapper ORM v1.8.0 - El Forum - 05-20-2011

[eluser]WanWizard[/eluser]
Datamapper internally adds validation rules for all 'id' columns, to make sure they have the correct definition and value.

Until the recent Reactor change it wasn't an issue that there was no label defined, but the latest Reactor incarnation finds it necessary to overflow the logs with 'language string not found' errors. They only way around it is to actually define the label (but you may assign an empty string to it if you wish).


DataMapper ORM v1.8.0 - El Forum - 05-20-2011

[eluser]felix_[/eluser]
ok thanks for your help! Smile


DataMapper ORM v1.8.0 - El Forum - 05-20-2011

[eluser]Chillahan[/eluser]
[quote author="WanWizard" date="1305900855"]@Chillahan,

In Datamapper, the column 'id' is required, MUST be called 'id', and must be an integer auto increment primary key. There is no way around it, the column name is hardcoded everywhere, and not easy to change (as you have noticed). This is on the roadmap though, probably for v2.0.
[/quote]

I assumed this was the case. Note that it is still an abstract key (no data involved), it's just that this client required it to be named with the table name as part of it (and as part of ALL fields), which is one standard, although not my personal choice.

Would you recommend against just forking DM and changing the id throughout to be id OR tablename_id? I guess it probably isn't so easy, there's a LOT of code there.

Quote:To answer your questions:
1) The field $row->id doesn't exist, you'll get a notice, and the value defaults to FALSE. $this->id != FALSE is TRUE, so the method it doesn't return FALSE.

Doh, silly me - missed that, it's FALSE != FALSE. Knew there was something there with the id missing causing that.

[quote[
3) Datamapper uses the CI database library's transaction methods, to wrap it's operations in. This means you can not use DM transactions over multiple database operations. Use $this->db->trans...() instead to wrap it around multiple DM operations.
(some db engines, like MySQL, don't allow you to nest transactions. Starting a transaction will immediately commit the previous one).
[/quote]

I am confused - I thought the CI transaction did allow for grouping of operations? I am talking about multiple operations in one shot, btw, not across server requests. Just if I want to be sure a new record gets added to three tables, or none.

Quote:If you create a new object, and you do $objectA->save($objectB), it will immediately add the ITFK to objectA if the relation is so that there is a one-to-many from A to B. However, if you just do $objectA->save(), there is obviously no relation to save, and the ITFK is set to NULL.

I was just setting it to a default value (in this case, 1, but ideally it could be 0). I guess as long as I set the validation as required on the key, that would ensure I always save something as the foreign key value when I do a straight save() - albeit a bit of a hack, and making the foreign key requirement pointless, but would work.


DataMapper ORM v1.8.0 - El Forum - 05-20-2011

[eluser]WanWizard[/eluser]
[quote author="Chillahan" date="1305913425"]Would you recommend against just forking DM and changing the id throughout to be id OR tablename_id? I guess it probably isn't so easy, there's a LOT of code there[/quote]
It's going to be quite a job, as it requires changes throughout the code, but also to the relationship definitions (which also append '_id' to any foreign key you define). I've already started on this, but it's going to take a while.

Quote:I am confused - I thought the CI transaction did allow for grouping of operations? I am talking about multiple operations in one shot, btw, not across server requests. Just if I want to be sure a new record gets added to three tables, or none.
What I mean is that Datamapper allows you to enable transactions internally for it's database operations. That means that within the Datamapper method, the database call is wrapped in a transaction.[/quote]

If you do it manually, using the method documented here, it's not a problem as these are direct mappings to CI's transaction method ( so $object->trans_start() is identical to $this->db->trans_start() ). Sorry if my remark confused you.

Foreign keys should not be defined NOT NULL, as there are situation where Datamapper explicitly sets them to NULL, for example when deleting relations. If you use a DEFAULT value, you run the risk of creating a false relation. Using zero instead of NULL is relatively safe, unless zero is a valid 'id' value.


DataMapper ORM v1.8.0 - El Forum - 05-21-2011

[eluser]Chillahan[/eluser]
Thanks for the clarification on the transaction call, I think I was on the same page but it sounded like perhaps not.

Uggh, so that's too bad on the issue of "id". The database already exists so I cannot change the naming structure, unfortunately. It's looking like I'll just have to forego the nicer ORM implementation and just settle for the regular "active record" with perhaps some helper functions in the constructor.


DataMapper ORM v1.8.0 - El Forum - 05-21-2011

[eluser]WanWizard[/eluser]
Sorry.

Changing primary key behaviour is very complicated, and will likely break applications.

For example, when defining an advanced relationship you now define a key, and Datamapper will append '_id' to it. If that code is removed, you have to revise all your models and manually add '_id' to it to make them work again.

So it's definitely something for a major release change (i.e. Datamapper 2.0). I only need to find the time for it, I haven't had a lot spare lately...


DataMapper ORM v1.8.0 - El Forum - 05-22-2011

[eluser]Spir[/eluser]
Just to be sure. How would you declare a self relationship on a table?

I have one table called categories :

id
name
parent_id // would refer to the parent categorie

Here is my model:
Code:
class Category extends DataMapper {
    
    public $has_one = array(
        'parent_category' => array(
            'class' => 'category',
            'other_field' => 'parent',
            'join_self_as' => 'id_parent'
        )
    );
    public $has_many = Array(
        'child_category' => array(
            'class' => 'category',
            'other_field' => 'child',
            'join_self_as' => 'id_parent'
        )
    );
    
    public $table = 'categories';
}

Is that correct?