Welcome Guest, Not a member yet? Register   Sign In
[Deprecated] DMZ 1.5.3 (DataMapper OverZealous Edition)

[eluser]PoetaWD[/eluser]
Me again... Tongue

I want to go down two levels of relationships. Is it possible ? What is the best way of doing it ?

Like, I have the object Document(), related to the object Document I have the Documenttype() """Type of Document: Like, Driver´s License""" and the Profile(). """Owner of the Document"""

Each Document() has many File(). Unlimited files associated with it.

I want to build a list with all the files and its related documents, easy job for now...

Code:
$obj = new File();
            
            $obj->include_related('document', array('stName'));
                        
            $obj->get();

            $data['objects'] = $obj->all;

Code:
+-------------+----------------------+--------------+-------------+
| Name        | Document Type        | Owner        | File        |
+-------------+----------------------+--------------+-------------+
| Copy1       | Driver´s Licence     | Bill         | copy1.jpg   |
| Copy2       | Driver´s Licence     | Bill         | copy2.jpg   |
| Anotherone  | Passport             | Bill         | an1.jpg     |
| test        | Driver´s Licence     | Jonh         | scan.jpg    |
| MyPass      | Passport             | Bill         | pass.jpg    |
+-------------+----------------------+--------------+-------------+

But how to also include the relationships of the documents ? Is there a way of doing it without having to create a relationship between the File(), Typeofdocument() and Profile() ?

In my example the Type of Document and the profile are only associated with the Document() and not with the file, which is being called this time.

Something like:

Code:
$obj = new File();
            
            $obj->include_related('document', array('stName'));

                        $obj->include_related_document('profile', array('stName'));
                        
                        $obj->include_related_document('documenttype', array('stName'));
                        
            $obj->get();

            $data['objects'] = $obj->all;


Can you point me in the right direction again ? Thank for the GREAT help... without you I would be stuck at the basics...

[eluser]OverZealous[/eluser]
Here's a couple of options:

1) Simple get() the related item for each parent item. This works well for small numbers of items. You can often use where_related($model, 'id', $model_id) to keep from loading too many levels of items.

2) If you are dealing with One-to-N relationships stored on the same table, you can sometimes load the related model in a roundabout way, like this:
Code:
// $user->document->doctype
$user->include_related('document', array('id', 'name', ..., 'doctype_id'));
foreach($user->all as $u) {
    $doctype = new Doctype();
    $doctype->get_by_id($user->document_doctype_id);
}

3) Often, for deep relationships, you'll just have to add some additional relationships in. It's not the cleanest solution, but it can be better than...

4) Hard-coding some SQL code into the query. Ex:
Code:
$user->include_related('document');
$user->db->join('doctypes_documents', 'doctypes_documents.document_id = documents.id');
$user->db->join('doctypes', 'doctypes_documents.doctype_id = doctypes.id');
$user->select('doctypes.name as doctype_name');
$user->get();
I don't recommend this, if possible, because it can be much harder to maintain later.

It would be impractical (currently) to attempt to perform multi-level includes. Someday I might try to code that, but that requires an awful lot of code.

[eluser]tolyx[/eluser]
I'm tearing my hair out over a problem which I simply don't understand.

I have two objects - a portfolio has many work_examples. I'm trying to save a new work_example against a portfolio. So my shortened controller code is...


Code:
// If an id has been provided
$portfolio = new Portfolio();
$portfolio->where('id', $portfolio_id);
$portfolio->get();


$work_example                    =    new Work_Example();

// Save the item
$work_example->image_file_name    =    $image_file_name;
$work_example->vimeo_id        =    $this->input->post('vimeo_id');
$work_example->description        =    $this->input->post('description');
                        
if ($work_example->save($portfolio))
{
            
    // Write a flash message
    $this->session->set_flashdata('message', 'The work example has been saved successfully.');
                
    // Redirect
    redirect(sprintf('admin/portfolios/work_examples/%d', $portfolio->id));
}

In my portfolio model...

Code:
var $table = 'portfolios';
    
var $has_one = array('carousel_item');
var $has_many = array('work_example', 'feature', 'discipline', 'case_study');

In my work example model...

Code:
var $has_one = array('portfolio');

(The portfolio_id is on the table, rather than a join table.)

So when the work example is saved, all fields save correctly other than the portfolio_id, which is 0. The portfolio has been retrieved successfully and I can echo the fields of the portfolio as expected. Saving using $portfolio->all makes no difference.

I also have validation on the work example that requires a portfolio, yet an error message is returned saying 'Portfolio is a required relationship'.

Any ideas?

[eluser]OverZealous[/eluser]
Have you checked to make sure that $portfolio is loading correctly? (->exists())

You cannot have an id of '0' for objects. A zero id is the same as empty(), which means a non-existant object to DataMapper. Please use auto-generated values. If you need to have special, system-only rows, try either using a special boolean column that is a flag (ex: 'is_system'), or using negative ids (I use the latter).

Have you verified that relationships are set up correctly on both objects?

It is almost certainly something wrong on your end. You might want to look through this forum, because I've answered this exact problem at least twice, I believe, and maybe a few times on the original DataMapper forum.

[eluser]tolyx[/eluser]
No everything is set up perfectly, but after a bit more debugging I discovered if I change the validation rules on the work_example from

Code:
var $validation = array(
                    
                    'vimeo_id'=>array(
                                    'label' => 'Vimeo ID',
                                    'rules' => array('integer')
                                ),
                    'description'=>array(
                                    'label' => 'Description',
                                    'rules' => array('trim')
                                ),
                    'sort_order'=>array(
                                    'label' => 'Sort order',
                                    'rules' => array('integer')
                                ),
                    'portfolio'=>array(
                                    'label' => 'Portfolio',
                                    'rules' => array('required')
                                )
    );


to

Code:
var $validation = array(
                    
                    'vimeo_id'=>array(
                                    'label' => 'Vimeo ID',
                                    'rules' => array('integer')
                                ),
                    'description'=>array(
                                    'label' => 'Description',
                                    'rules' => array('trim')
                                ),
                    'sort_order'=>array(
                                    'label' => 'Sort order',
                                    'rules' => array('integer')
                                )
    );

i.e. removing the 'portfolio relationship required' rule, it works perfectly, but I do need this rule.

Can you spot anything wrong there?

[eluser]bEz[/eluser]
@tolyx
What is the setting for the 'portfolio_id' in the 'work_example' table?

KEY NOTE: the 'portfolio_id' must allow "NULL" in order for the $work_example->save($portfolio)
to function properly, because i believe the 'work_example' record is saved before DMZ saves the 'portfolio_id' and this is by design. Phil, am I correct?

[eluser]tolyx[/eluser]
Well it was set to non-NULL, but that doesn't matter since the save is just an UPDATE (i.e. from 0 to whatever the id is). And as per my message earlier, removing the validation rule allows the work_example to be saved perfectly. So it seems something's gone awry in the validation... as though it is resetting the $portfolio object to NULL just as it is saved...?

This is 1.3.2 by the way.

[eluser]bEz[/eluser]
Quote:as though it is resetting the $portfolio object to NULL just as it is saved…?
correct, I believe this is the design of DMZ.
I had a similar issue where this was addressed (I believe in the datamapper thread).
Hopefully Phil has time to verify this.

[eluser]tdktank59[/eluser]
Your update broke something...

Heres whats happening

Query
Code:
$problem = new Problem();

$problem->join_related('member', array('name'));
$problem->join_related('status', array('name'));
$problem->join_related('owner', array('first_name', 'last_name'));
$problem->join_related('assigned_to', array('first_name', 'last_name'));

// create special query section
$search = '';
$sSearch = $problem->db->escape_str($sSearch);
foreach(array('`members`.`name`', '`members`.`sid`', '`problem_statuses`.`name`') as $col)
{
    if(!empty($search)) { $search .= ' OR '; }
    $search .= "{$col} LIKE '%{$sSearch}%'";
}

// note: calling directly on the db library, to bypass DataMapper.
$problem->db->where('(' . $search . ')');
$problem->where_in('id',$problem_id);

if ($source == 'inbox')
  $problem->where('assigned_to_id',$user_id);
else
  $problem->where('owner_id',$user_id);

if (isset($order)) $problem->db->order_by($order);
$problem->limit($iDisplayLength,$iDisplayStart);
$problem->get();

Error Message excerpt:
Quote:Unknown column 'problem_statuses.name' in 'where clause'

SELECT `problems`.*, `members`.`name` AS member_name, `status_problem_statuses`.`name` AS status_name, `owner_users`.`first_name` AS owner_first_name, `owner_users`.`last_name` AS owner_last_name, `assigned_to_users`.`first_name` AS assigned_to_first_name, `assigned_to_users`.`last_name` AS assigned_to_last_name
....

Model relationships are correct
Code:
// Problem Status
"status"              => array(   'class' => 'problem',
                                  'other_field' => 'status'),

// Problem
"status"        => array (  'class' => 'problem_status',
                            'other_field' => 'status'),
I have no idea what is making this happen but for some reason its adding status onto the front of problem_statuses...

[eluser]OverZealous[/eluser]
@tolyx, bEz
Yes, the NULL requirement is by design and clearly explained in the documentation. (Thanks, bEz, for tracking this down!)

@tdktank59
The update will affect some hard-coded SQL elements, like your `problem_statuses`. I'm sorry that it wasn't explained better.

Basically, if the class and the key don't match, the key will be appended to the table name on joins. This is to allow the same table to be joined multiple times.

For example: editor and creator both point to the same users table, so they would get joined as editor_users and creator_users, respectively.




Theme © iAndrew 2016 - Forum software by © MyBB