EllisLab text mark
Advanced Search
27 of 31
27
   
DataMapper ORM v1.8.1
Posted: 15 January 2012 03:47 PM   [ # 401 ]   [ Rating: 0 ]
Joined: 2011-01-31
17 posts

Edit: Oops, double post. Thought it didn’t appear but it did on a new page…

 
Posted: 16 January 2012 01:45 AM   [ # 402 ]   [ Rating: 0 ]
Avatar
Joined: 2008-11-04
4489 posts

That doesn’t work (at least in your snippet) because $m1_1 and $m1_2 are new objects.

DataMapper needs a primary key to be able to save the relation, so save them first before attempting to save the relation (like you did for $m2).

 Signature 

Me: WanWizard.eu | My company: Exite | Datamapper: DataMapper ORM <= LOOKING FOR A NEW MAINTAINER!

 
Posted: 16 January 2012 01:58 AM   [ # 403 ]   [ Rating: 0 ]
Joined: 2011-01-31
17 posts

Thanks again grin

The snippet was pseudo code, not something I actually got in my code as it would not work in the most simple cases. The primary keys are there. Sorry for the misinformation.

So I’ve got table1, table2 and table1_table2, and model1 and model2, mapping on table1 and 2 respectively. In both table2 and table1_table2 the foreign key table1_id is specified. So how can i tell the system to save the relationship between model1 and model2 in the table table1_table2 (with no model) and not in the table table2?

I changed my example, still sort of pseudocode…

$m1_1 = new model1();
$m1_1->percentage = 5;
$m1_2 = new model1();
$m1_2->percentage = 50;
$m1_1->save();
$m1_2->save();

$m2 = new model2();

$m2->name = “test”;
$m2->save();

So, how do I save $m1_1 in $m2 (many to many, in the “in between” table)
and $m1_2 in $m2 (one to many)

$m2->save(array($m1_1,$m1_2));

 
Posted: 16 January 2012 02:22 AM   [ # 404 ]   [ Rating: 0 ]
Avatar
Joined: 2008-11-04
4489 posts

If it’s a many_to_many, why do you have a foreign key in table2?

DataMapper internally uses some optimisation to determine where the foreign key is located. This is because you can implement one_to_many’s with or without a relationship table.

It does that by checking if the related model contains the foreign key. If found, it will use it.

I’ve quickly checked the code, and as far as I can see, it only does this for has_one relations. This relation is defined as has_many in both models?

 Signature 

Me: WanWizard.eu | My company: Exite | Datamapper: DataMapper ORM <= LOOKING FOR A NEW MAINTAINER!

 
Posted: 16 January 2012 03:07 AM   [ # 405 ]   [ Rating: 0 ]
Joined: 2011-01-31
17 posts

I think we are having some communication problems grin Let me explain my situation more thorougly:

First, this is the only problem in my 40+ model application. The other models are all saving without problem.

I’ve got the situation where I have contractnumbers. Each contract number can have multiple sub-contracts. This is a one to many relationship.

At the same time I have a many to many relationship between the same models. A subcontract gets an additional discount when used in combination with one (or more contracts). So I have the following tables:

1. contract
- id
- contract name

2. subcontract
- id
- contract_id
- etc.

3. contract_subcontract
- contract_id
- subcontract_id
- percentage

Now, I defined the relationships as you suggested in your reply at the bottom of page 40.
So now I try to add some contracts to a subcontract, using the table contract_subcontract.

How do I save such a contract? Normally you would do something like $subcontract->save(array($contract->all)) (provided all contracts already have an id), but in my case the system does not know which one to fill:
contract_id in the subcontract model, or add a row to the contract_subcontract table. In my situation it just takes the contract_id in the subcontract table/model.

I hope I explained myself well enough this time grin

 
Posted: 16 January 2012 08:26 AM   [ # 406 ]   [ Rating: 0 ]
Avatar
Joined: 2008-11-04
4489 posts

Yes, I understand that.

And as I replied, if the relationship between subcontract and contract (this one because you save it this way) is a has_one, DataMapper will favour an in-table foreign key over the use of a relationship table.

The only way to work around is, it to define an advanced relationship for the relation in which subcontract.contract_id is used, in which you use a different column name, to avoid the autodetection of the ITFK.

If that specific relation is not a has_one, then either you have an issue with the definition of the parallel relationships (so DataMapper will choose the wrong one) or you’ve found a bug in DataMapper (which will require debugging to confirm this).

 Signature 

Me: WanWizard.eu | My company: Exite | Datamapper: DataMapper ORM <= LOOKING FOR A NEW MAINTAINER!

 
Posted: 16 January 2012 03:26 PM   [ # 407 ]   [ Rating: 0 ]
Joined: 2011-01-31
17 posts

Hi, thanks for your answer.

I solved it by defining an advanced relationship, as you suggested. Then I saved the objects by doing:

$model->save(array(“name_i_gave_relationship_in_model”=>$model2));

That last line was the thing I was looking for.

Regards,
Joost.

 
Posted: 16 January 2012 03:31 PM   [ # 408 ]   [ Rating: 0 ]
Avatar
Joined: 2008-11-04
4489 posts

Good to hear you’ve got it working. Thanks for the feedback.

 Signature 

Me: WanWizard.eu | My company: Exite | Datamapper: DataMapper ORM <= LOOKING FOR A NEW MAINTAINER!

 
Posted: 16 January 2012 06:41 PM   [ # 409 ]   [ Rating: 0 ]
Avatar
Joined: 2010-07-28
7 posts

I’m building an educational app which has lessons and student responses. The content for both is a series of blocks. In order to normalize the database, I have created 1 blocks table with a ‘type’ column and a ‘parent_id’ column. The ‘type’ column will contain either ‘LESSON’ or ‘RESPONSE’ and the ‘parent_id’ will reference the ‘id’ on either the lesson or response table , depending on the ‘type’ column.

Therefore, both the lesson and response objects have many blocks and each block has one parent of either lesson or response.

The other thing is that there is a sort/order column which describes what order the blocks should be displayed in.

Is this the sort of relationship that can be achieved easily by setting up the $has_one and $has_many variables, or am i better of splitting the blocks table into 2 e.g. ‘lesson_blocks’ and ‘response_blocks’.

/** EDIT **/

I am thinking it might be better to do away with the ‘parent_id’ and ‘type’ fields and instead created join tables for each type e.g. ‘lessons_blocks’ and ‘responses_blocks’?

 
Posted: 17 January 2012 02:21 AM   [ # 410 ]   [ Rating: 0 ]
Avatar
Joined: 2008-11-04
4489 posts

Your first solution is possible, but dangerous. DataMapper only knows the foreign key, but has no way of knowing to which parent table the record belongs. When selecting, you can use where_related() as a filter on ‘type’, but be careful when deleting related records, it will delete all records with a given foreign key.

Join tables is a better solution, it will keep your relations clean.

 Signature 

Me: WanWizard.eu | My company: Exite | Datamapper: DataMapper ORM <= LOOKING FOR A NEW MAINTAINER!

 
Posted: 17 January 2012 06:43 AM   [ # 411 ]   [ Rating: 0 ]
Joined: 2010-10-27
114 posts

I am building a takeaway finder that will find takeaways within a set distance of a uk postal code. What will happen is the user puts his/her postcode in an input box and clicks submit, the site then searches for takeaways near the user. But the catch is that this search is based on the individual takeaways delivery distance. So if a takeaway has a delivery distance of say 8 miles and the persons postcode is within 8 miles of the takeaway it will show in the results.

So far I have uk postcode database with lang and lat coordinates and also the takeaway database table holds the takeaways own postcode and its delivery distance but not the long and lat values of the takeaways postcode.

I have following sql query but im not sure how to implement something like this using datamapper?

SELECT id 6371 ACosCosRADIANSlatitude ) ) * CosRADIANS56.0062 ) ) *  Cos(        RADIANS( - 3.78189 ) - RADIANSlongitude ) ) + SinRADIANSlatitude ) ) *    SinRADIANS56.0062 ) ) ) AS Distance
 FROM postcodes
 HAVING Distance 
<= '10'
 
ORDER BY Distance 


Also would’nt mind a bit of advice on setting up the logic of the above takeaway finder

 
Posted: 17 January 2012 12:46 PM   [ # 412 ]   [ Rating: 0 ]
Avatar
Joined: 2008-11-04
4489 posts

If things get this complicated, create a method in your model, run a standard $this->db query, and convert the returned result set back to DataMapper objects:

public function mycomplicatedquery()
{
    $query 
$this->db->query('some sql here');

    if (
$query)
    
{
        $this
->_process_query($query);
    
}

    
return $this;

Do this only if the query is run on the models table, and if the result set includes at least the ‘id’ column.

 Signature 

Me: WanWizard.eu | My company: Exite | Datamapper: DataMapper ORM <= LOOKING FOR A NEW MAINTAINER!

 
Posted: 17 January 2012 06:42 PM   [ # 413 ]   [ Rating: 0 ]
Avatar
Joined: 2010-07-28
7 posts
WanWizard - 17 January 2012 02:21 AM

Your first solution is possible, but dangerous. DataMapper only knows the foreign key, but has no way of knowing to which parent table the record belongs. When selecting, you can use where_related() as a filter on ‘type’, but be careful when deleting related records, it will delete all records with a given foreign key.

Join tables is a better solution, it will keep your relations clean.

Thanks for your help! I ended up doing a bit of minor re-engineering in the db to use join tables which looks a lot cleaner.

Now i have a ‘blocks’ table with no parent_id or type columns. I then have my lessons and responses tables and join tables between those and the blocks table. This app is likely to grow and have other objects which require blocks related to them so it’s just a matter of creating that new join table.

 
Posted: 23 January 2012 05:04 AM   [ # 414 ]   [ Rating: 0 ]
Joined: 2011-01-31
17 posts

I’ve got a question that I can’t find in the documentation.

The situation is as follows. I have a table (B) that has two connections (1 and 2) to the same other table (C).

Situation:

table A
id
b_id

table B
id
c1_id
c2_id

table C
id
d_id

table D
id
code

Now I am trying to use a where_related, and tables B and C are in the middle if the query. How do I force it to take route 1 or 2 in the joins?

$t->where_related(‘A/B/C/D’,‘code’, ‘x’)

Is this possible when using the where_related at all?

 
Posted: 23 January 2012 09:29 AM   [ # 415 ]   [ Rating: 0 ]
Joined: 2011-01-31
17 posts

I’ve got a new issue, which could be a bug (or feature).
There are three models, they have the following relations:

A has one B (can be null)
A has many C
B has many A
B has many C
C has one B
C has one A

I fill this table by:
1. importing A without reference to B,
2. importing B and C
3. Update A with the references to B.

At step 3 datamapper generates strange queries, where it updates all other A’s with NULL that have the same B as the one we are about to add to the current A.

[6] => UPDATE `A` SET `B_id` = NULL WHERE `A`.`B_id` =  8 AND `A`.`id` <> 1
[7] => UPDATE `A` SET `B_id` = 8 WHERE `id` =  1

Is this behaviour as it should be? It seems to be enforcing that I only use a B once with an A.

 
27 of 31
27