EllisLab text mark
Advanced Search
1 of 53
1
   
[Deprecated] DMZ 1.5.3 (DataMapper OverZealous Edition)
Posted: 28 April 2009 04:21 PM   [ Ignore ]
Avatar
Joined: 2008-10-08
1039 posts

This is an outdated version.  Please see the newer version here.

Thanks goes to stensi, for providing such an amazing code base to work on.

DataMapper OverZealous Edition 1.5.3

DataMapper (DM) is an Object-Relational Mapper that builds on ActiveRecord.  Data is loaded from database tables into objects, and relationships can be managed through simple, easy-to-read functions.

DataMapper OverZealous Edition (DMZ) adds several important features to DM, enhancing it’s usage, usually without requiring any code changes.

To install DMZ over DataMapper, the (fairly simple) upgrade process is described here.

DMZ offers these features and more over the original DataMapper:
  • In-table foreign keys
  • Multiple relationships to the same model
  • Better self references
  • Add fields from a related model into one query
  • Update, view, and query extra columns on join tables
  • A shareable extension mechanism, including:
      • Easy creation of HTML forms,
      • Processing posted input,
      • Converting to-and-from JSON, CSV, and arrays, and
      • Query caching

Version 1.5.3:
Recommended for a few minor bugfixes, and one semi-major one with include_related.

Core Changes
• Modified the way _to_object and query processing works, significantly, by merging all query processing code into one new function (_process_query).

Bug Fixes
• Fixed bug that completely broke include_required’s ability to automatically add all fields.
• Fixed bugs with get_rules not being called correctly for related queries and validate->get() queries.
• Invalid relationship queries now show an error instead of silently failing.
• Fixed typo in Troubleshooting where the word ‘related’ was supposed to be ‘required’.

Download the Latest Version Here

  View the change log and the upgrade process
  Having issues? Please look through the Troubleshooting Guide & FAQs
  View the Complete Manual

 Signature 

Phil DeJarnett
  OverZealous Creations, LLC

 
Posted: 28 April 2009 04:31 PM   [ Ignore ]   [ # 1 ]   [ Rating: 0 ]
Avatar
Joined: 2008-02-16
138 posts

Fantastic work OverZealous and well done for Stensi for starting the origional project.

I have PM you OverZealous if you fell I can help.

[OES]

 Signature 

weblee.co.uk - Web Development Blog
Screencasts - CI Screencasts.

 
Posted: 28 April 2009 10:02 PM   [ Ignore ]   [ # 2 ]   [ Rating: 0 ]
Joined: 2008-07-14
58 posts

Cool OverZealous. Have been using DMZ for sometime now and its extra functionality is awesome smile

 
Posted: 29 April 2009 12:32 AM   [ Ignore ]   [ # 3 ]   [ Rating: 0 ]
Joined: 2009-04-02
200 posts

I have decided to repost my question here cause Im pretty sure the answer to what Im looking for has to do with dmz more than datamapper

Could you help me with this query please??...
Heres my structure:

clients have many events
event has one client
events have one receipt
receipt has one event
receipts have many payments
payments have many receipts

I want to get every payment of a client in a single query… is it possible?
lets assume client id=1… I have tried many queries but I can never seem to get it done.

 
Posted: 29 April 2009 12:54 AM   [ Ignore ]   [ # 4 ]   [ Rating: 0 ]
Avatar
Joined: 2008-10-08
1039 posts

@NachoF
Short answer, no.  I recommend that you relate Clients directly to Payments, and keep track of them that way.  It looks like, from the names, these are written to but not updated.  Since every Payment has a single Client, just add client_id to your Payments table, and add the Client whenever you INSERT a payment.

Longer answer:
Yes, you can, but you have to basically write your query by hand.  And you’ll probably end up with weird duplications, due to the many-to-many between Receipts and Payments.
How I have done that, before I wrote DMZ, is to use this trick:

// note: adding the joins directly to the DB class
$payments->db->join('payments_receipts''payments.id = payment_receipts.payment_id');
$payments->db->join('receipts''receipts.id = payment_receipts.receipt_id');
$payments->db->join('events''receipts.event_id = events.id');
$payments->where('events.client_id'$client->id);
$payments->distinct()->get(); 

However, I highly recommend against this.  It becomes hard to maintain and it’s awkward to read.  Storing the client_id on Payments will also be an order of magnitude (or two) faster to query.

Also, I’m curious why payments are many-to-many to receipts?  There can be more than one receipt per payment?

Finally, you should go back and edit (delete with a note) your comment on the DM 1.6.0 board, to avoid cross-posting.

 Signature 

Phil DeJarnett
  OverZealous Creations, LLC

 
Posted: 29 April 2009 02:27 AM   [ Ignore ]   [ # 5 ]   [ Rating: 0 ]
Joined: 2009-04-02
200 posts
OverZealous.com - 29 April 2009 04:54 AM

@NachoF
Short answer, no.  I recommend that you relate Clients directly to Payments, and keep track of them that way.  It looks like, from the names, these are written to but not updated.  Since every Payment has a single Client, just add client_id to your Payments table, and add the Client whenever you INSERT a payment.

Longer answer:
Yes, you can, but you have to basically write your query by hand.  And you’ll probably end up with weird duplications, due to the many-to-many between Receipts and Payments.
How I have done that, before I wrote DMZ, is to use this trick:

// note: adding the joins directly to the DB class
$payments->db->join('payments_receipts''payments.id = payment_receipts.payment_id');
$payments->db->join('receipts''receipts.id = payment_receipts.receipt_id');
$payments->db->join('events''receipts.event_id = events.id');
$payments->where('events.client_id'$client->id);
$payments->distinct()->get(); 

However, I highly recommend against this.  It becomes hard to maintain and it’s awkward to read.  Storing the client_id on Payments will also be an order of magnitude (or two) faster to query.

Also, I’m curious why payments are many-to-many to receipts?  There can be more than one receipt per payment?

Finally, you should go back and edit (delete with a note) your comment on the DM 1.6.0 board, to avoid cross-posting.

Ok, dont worry…. my entity relation cannot be modified… my teacher is crazy…the reasoning behind the many to many relation is that suppose a client has two pending events to be charged for… I have to give him the option to with just one payment pay those two receipts…. see?... you can pay for the event in different payments but in the end only get one receipt per event…. yet with one payment you can pay for more than one event.
Anyway, my query has been done in steps…
first get all the events of the client
then loop through them and get the receipts for each event and for each receipt loop and get the payments… its confusing but it seems to work so far….

 
Posted: 29 April 2009 02:38 AM   [ Ignore ]   [ # 6 ]   [ Rating: 0 ]
Avatar
Joined: 2008-10-08
1039 posts

One thing I forgot to mention that might save you a query is to use where_related() to reduce the number of queries.

Example (assumes Events has a client_id field):

// get all receipts for the customer
$receipts = new Receipt();
$receipts->where_related_event('client_id'$client->id)->select('id')->get();
$receipt_ids = new array();
foreach(
$receipts->all as $r{
    $receipt_ids[] 
$r->id;
}
// get all payments that belong to one of the receipts
$payments = new Payment();
$payments->where_in_related_receipt('id'$receipt_ids)->distinct()->get(); 

This should get all of the payments, distinctly, that are related to the client, in just 2 queries.

The nice thing about this is that you can still sort the payments list all at once.

Let me know if the above code works, since I typed it off the top of my head.

 Signature 

Phil DeJarnett
  OverZealous Creations, LLC

 
Posted: 30 April 2009 07:07 PM   [ Ignore ]   [ # 7 ]   [ Rating: 0 ]
Joined: 2008-07-14
58 posts

Heres a tricky one

(example only - purpose is a little iffy raspberry)

User has many Invoice
Invoice has one User


I need to be able to get all the invoices, ie

$i = new Invoices();
$i->get(); 


But somehow order those invoices by the name field of each user.


Is something like that at all possible?

Hmm, hope thats clear.

Thanks in advance ;P

Cheers

 
Posted: 30 April 2009 09:11 PM   [ Ignore ]   [ # 8 ]   [ Rating: 0 ]
Avatar
Joined: 2008-10-08
1039 posts

It’s easy with DMZ™!

You simply do this:

$i = new Invoices();
$i->join_related('user', array('name'));
$i->order-by('user_name');
$i->get(); 

Tada!  grin

 Signature 

Phil DeJarnett
  OverZealous Creations, LLC

 
Posted: 30 April 2009 10:45 PM   [ Ignore ]   [ # 9 ]   [ Rating: 0 ]
Joined: 2009-04-02
200 posts

Im confused with join_related.. whats the difference between it and include_join_fields?

 
Posted: 30 April 2009 10:46 PM   [ Ignore ]   [ # 10 ]   [ Rating: 0 ]
Joined: 2008-07-14
58 posts

OH rite! Ofcourse! Over looked that a bit

Thanks again OverZealous smile

 
Posted: 30 April 2009 10:56 PM   [ Ignore ]   [ # 11 ]   [ Rating: 0 ]
Avatar
Joined: 2008-10-08
1039 posts

@NachoF
join_related:
Join fields from a related class.  In other words, I can include the name field of the model Group while querying my Users.  This allows you to get information from related models all in one query.  It’s really useful when querying data for a table, because you avoid running many queries to pull in all the data.

Join related includes the specified fields as <related_field>_<column_name>.  You specify which related model in the first parameter, and which columns using the second parameter.

include_join_fields:
This allows you to include fields that are stored on a join table.  In this case, you might want to track how many times a specific user has viewed a specific post, or something similar.  You related the user like normal, but you can include extra columns on the join table that you can query, view, and update using where_join_field, include_join_fields, and set_join_field respectively.

I had already create join_related when I added the join table methods, so the names are a little confusing.  I didn’t want to rename it, because it would break code (or require rewrites).

If I did rename it, I might rename it include_related_fields to make it consistent with the other one.  (I might even make the second parameter optional, although that is not very efficient.)

 Signature 

Phil DeJarnett
  OverZealous Creations, LLC

 
Posted: 02 May 2009 02:40 PM   [ Ignore ]   [ # 12 ]   [ Rating: 0 ]
Joined: 2009-04-22
15 posts

Hi OverZealous,

I’m using DMZ now. Thanks for creating it!

Here is problem:

Category 1:
A

B

C


Category 2:
A

C

D


Category3:
C

D

B

I want to get the elements that appears in:
1) Both Category1 and Category3.
2) All categories.

How do I accomplish this?

Nadeem Qureshi

 
Posted: 02 May 2009 03:15 PM   [ Ignore ]   [ # 13 ]   [ Rating: 0 ]
Avatar
Joined: 2008-10-08
1039 posts

You didn’t mention if items could appear in no category.  If they must appear in some category, then you can just do $elements->get();

The best way is to use where_in_related(), which is part of the core DataMapper.

$category1 = ...
$category2 = ...
$elements->where_in_related_category('id', array($category1->id$category2->id));
$elements->distinct->get(); 

To get all items in all categories (assuming the above isn’t true), just do this:

$elements->where_related_category('id >'0)->distinct()->get(); 

That should get all items where there is a related category.  Adding the distinct prevents DM from having to parse the same item multiple times.

 Signature 

Phil DeJarnett
  OverZealous Creations, LLC

 
Posted: 02 May 2009 03:33 PM   [ Ignore ]   [ # 14 ]   [ Rating: 0 ]
Joined: 2009-04-22
15 posts

You’re awesome, Man! grin I’ll try that out!

What would I do if I wanted elements that had no category?

Nadeem

 
Posted: 02 May 2009 03:36 PM   [ Ignore ]   [ # 15 ]   [ Rating: 0 ]
Joined: 2009-04-22
15 posts

Also,

Is there difference between $element->save($category) and $category->save($element)?

 
1 of 53
1