@Buso
Search for arrays in the manual. The first result is your answer. 😉
Perfect! Thanks Phil
This is an archived forum and the content is probably no longer relevant, but is provided here for posterity.
The active forums are here.
March 14, 2010 11:43pm
Subscribe [104]#256 / May 14, 2010 11:43am
@Buso
Search for arrays in the manual. The first result is your answer. 😉
Perfect! Thanks Phil
#257 / May 14, 2010 1:53pm
Sorry for stupid question, but is possible to get “dropdown” from DMZ?
#258 / May 14, 2010 4:11pm
@housecor
I wouldn’t replace the $validation array. Most likely this will lead to unexpected results, because of the manipulation that happens on that array. Also, DMZ only uses the first validation array for the object. That array is cached for the session, and is used to set up all further objects.
One way to handle sometimes-required objects is to add a custom _required method to your object. This method can then decide whether a field is required or not. (This may cause issues if you have other rules, and those other rules fail if the field is empty.)
It is a small problem if you need fields that are only sometimes required, because DMZ skips running the rest of the validation if the field is not required. I might look at adding a special rule, ‘is_required’, that allows an object to determine whether a field is required based on context. That might be awhile, though.
#259 / May 14, 2010 5:35pm
Thanks Phil! To clarify, I’m not actually replacing the validation array - I’m merely adding some additional fields *before* the constructor is called. (I changed my example code above to reflect this). Since I’m still setting up the validation array before the constructor is called, I don’t see how this could cause any issues. The technique is working great for me thus far, but as the author, if you still think I’m headed for trouble, please let me know.
BTW - Excellent work on DMZ! I really enjoy working with it and your documentation is superb.
#260 / May 14, 2010 9:57pm
@housecor
That still might not be doing what you want! 😊
The reason is that DMZ replaces the $validation array (along with some other parameters) from the statically cached copy! So, if you load in, say, a User model, however the validation array is configured at that moment is how all future Users are configured until the end of the HTTP request.
Hence my thoughts above. I’m liking the idea of a is_required function more and more, though. I am actually thinking about different ways to implement it, than my original idea, though.
#261 / May 16, 2010 2:02am
I’ve read the documentation on advanced relationships and I’m struggling.
Here is my set up. I have a classifieds area on my site that allows people to submit multiple photos.
I wanted to be able for a classified to have one main image and multiple others.
I was going to do this with just a flag in the join table, but a fellow developer said it might be easier to just directly reference the main photo directly in the classifieds table.
How would I set up the relationships for classifieds and photos where classifieds can have one main photo and multiple other photos?
This is one of several iterations I’ve tried with the result of unable to relate error messages.
Photo Relationships:
// Insert related models that Photo can have more than one of.
var $has_many = array(‘classified_all’ => array(‘class’ => ‘classified’, ‘other_field’ => ‘photo’),
‘classified_main’ => array(‘class’ => ‘classified’, ‘other_field’ => ‘mainphoto’));
Classified Relationships:
// Insert related models that Classified can have just one of.
var $has_one = array(‘classifiedtype’, ‘user’, ‘mainphoto’ => array(‘class’ => ‘photo’, ‘other_field’ => ‘classified_main’));
// Insert related models that Classified can have more than one of.
var $has_many = array(‘photo’ => array(‘class’ => ‘photo’, ‘other_field’ => ‘classifield_all’));
#262 / May 16, 2010 6:02pm
@someoneinomaha
Personally, I would use join_fields as you originally intended. This ensures that if you delete all photos, you also delete the primary. The section on join_fields in the manual covers the three basic methods that work with them.
If you want to have multiple relationships instead, then I would do it like this:
class Classified {
$has_many => array('photo');
$has_one => array('mainphoto' => array('class' => 'photo', 'other_field' => 'classified_main');
}
class Photo {
$has_many => array(
'classified',
'classified_main' => array('class' => 'photo', 'other_field' => 'mainphoto')
);
}
// Table classifieds_photos
id
classified_id
photo_id
classified_main_id
mainphoto_idThen you have to save the main photo in two ways:
$classified = new Classified();
// TODO: set fields, save photos, etc.
$relations = array(
'photo' => array($photo1, $photo2, $photo3),
'mainphoto' => array($photo1)
);
$classified->save($relations);Also, if you delete the mainphoto, it has to be deleted twice:
$classified->delete_mainphoto($photo1);
$classified->delete($photo1);Some of these problems are alleviated with using the join field. The JF has it’s own minor problems, as well.
#263 / May 16, 2010 11:42pm
Thanks for the reply Phil… I appreciate it.
So I think one of the areas I have set up incorrectly is I have the database structured like:
Photos:
id
label
path
etc…
classifieds_photos:
id
photo_id
classified_id
classifieds:
id
blah blah…
mainphoto_id
Would there be no way to set up the dual relationship between photos and classifieds with this db setup?
Thanks.
#264 / May 16, 2010 11:58pm
@someoneinomaha
That should work perfectly. If you use the relationship settings I had before, you can safely use mainphoto_id. Honestly, it’s how I would configure the tables. It just slipped my mind.
Using a join field still might be better, but it’s up to you which you prefer.
#265 / May 17, 2010 9:49am
Hi,
This is the first project im working on, where i am using dmz. I tried Doctrine and Rapidmapper, but they didn’t quite meet my needs as well as dmz seems to. DMZ has already helped me alot when im working with quite complex relations, but what i didnt find from the user manual, is how to work with collections inside collections inside collections…
Do you always have to go with foreach loops, e.g. if i want to create invoices based on every transaction that has been made in the past 24 hours, and get the related data to this invoice, do i have go like this:
$transactions = new Transaction();
// Get all the transactions created in the past 24h
$transactions->where("HOUR( TIMEDIFF( NOW( ) , `transactions`.`created` )) < 24")->get();
foreach($transactions as $transaction) {
//Get all related data
$transaction->invoice->get(); //Transaction has one invoice
$transaction->invoice->invoice_line->where('gl_account_id',3000)->or_where('gl_account_id',3002)->get(); //Invoice has many invoice_lines
foreach($transaction->invoice->invoice_line as $invoice_line){
$invoice_line->gl_account->get(); //Invoice_line has an gl_account
}
$transaction->person->get(); //..
$transaction->person->some_related_info->get(); //..
$transaction->company->get(); //..
$transaction->company->billing_account->get(); //..And if thats not all the relations, it just seems like there is a better way to do these things, i just haven’t really figured it out. I have tried with the include_related, but e.g. if the invoice table has an in-table foreign key for an transaction, then i cant do this
$t = new Transaction(); $t->include_related('invoice',null,false,true); // This has all the values as null of related invoice object
$i = new Invoice(); $i->include_related('transaction', null, false, true) // This worksI guess i’m just a bit confused about the correct usage with collections of collection.
Any help or guiding is really appreciated (and i have read the user manual many times already)
Thank you!
#266 / May 20, 2010 12:04am
I did end up deciding the join was the best way to go… but this is the SQL I think is necessary to generate the results I need.
select c.*, p.id as photo_id, p.label, p.path, p.caption, p.phototype_id from classifieds c
LEFT OUTER JOIN (classifieds_photos cp JOIN photos p ON (cp.photo_id = p.id AND cp.is_main = 1))
ON c.id = cp.classified_idI want a list of all classifieds along with the main photo (if one exists).
There’s no way to generate this via an Active Record / DMZ method, right?
#267 / May 20, 2010 1:02am
@someoneinomaha
There’s no way in ActiveRecord (and DMZ is based on AR) to do compound joins.
You can build the query without the compound join, however, DMZ won’t let you select fields from $has_many tables. This might work, however:
$c = new Classified();
$c->select(...);
$c->select('photos.id as photo_id');
$c->select('photos.label');
// etc
$c->where_join_field('photo', 'is_main', 1);
$c->get();If that doesn’t work, you might need to forcibly include the photo table, like this (which is a really nasty hack):
$c->where_related('photo', 'id !=', 0);That should allow classifieds with no photos to work, since id will be NULL in those cases.
This is another case where I think I can change the core of DMZ, and allow include_related even when working with a $has_many join. I’ll look into it.
#268 / May 20, 2010 10:30am
After reading through my last post a few times i realized it was quite a mess. So now i’m trying to be a bit more clear with my questions.
1. When i am fetching records and have has_many relation, can i include all children for a record somehow? e.g. $parent->include_many_related(‘child’)->get();
2. If i get all parents $parents->get(); //100 parents,
Can i get every parents children without a for loop? e.g. $parents->all->child->get();
or do i always have to go like this: foreach($parents as $parent){$parent->child->get()};
(i know i could go like $children->include_related(parent)->get() but if i have to go the other way?)
3. When i am querying for objects, can i check if in the middle of a query if the object has a related item? e.g. $parent->where_has_related(‘child’)->get();
Thanks in advance.
#269 / May 20, 2010 10:40am
@j0nxiest
1. No. But you can’t really do that with straight SQL, either. However, you can sometimes turn it around, by querying on the many side of the relationship, and grouping or sorting the results.
2. Same as above. You have to loop. (It’s only three lines of code!) If you want it in one query, just like above, you have to start from the many side.
3. $parent->distinct()->where_related(‘child’, ‘id IS NOT NULL’)->get();
DMZ is just a wrapper on SQL. If you can’t easily do it in SQL, you can’t easily do it in DMZ. (Some things are always a little more difficult in DMZ, too.)
#270 / May 20, 2010 6:58pm
Hey all, hopefully a quick question…
I want to retrieve a collection of objects using get(), then access a specific one of them (ie: the first).
I want to do this but it doesn’t work. (Assuming there are multiple “red things”.)
$thing = new Thing();
$thing->where('color', 'red')->get();
echo $thing[0]->name;Is there a way to access specific objects in the collection? Specifically, the first one. I can do a “foreach” on $thing, but I can’t do $thing[0].
Greg