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

[eluser]cberk[/eluser]
I switched to DMZ from the original Datamapper and was pleased with how seamless the transition was. However, I am getting an error now that I wasn't getting before, and haven't been able to figure out why.

I have two models, and am using the related_min_size validation rule on one of them. Here are the relevant excerpts (MyDataMapper is just an extension class of DataMapper):

Code:
class State extends MyDataMapper {

    var $has_many = array("metro");

Code:
class Metro extends MyDataMapper {

    var $table = 'metros';
    
    var $has_many = array("state");

    var $validation = array(
        array(
            'field' => 'state',
            'label' => 'State',
            'rules' => array('min_size' => 1) // A metro must be associated with at least one state
        )
    );

When I try to update and save an existing metro (it already has a relationship to a state), I get the following error:

Quote:A PHP Error was encountered

Severity: Notice

Message: Object of class State could not be converted to int

Filename: libraries/datamapper.php

Line Number: 3205

It is referencing this function from DataMapper:
Code:
// --------------------------------------------------------------------

    /**
     * Min Size (pre-process)
     *
     * Checks if the value of a property is at least the minimum size.
     *
     * @access    private
     * @param    string
     * @param    integer
     * @return    bool
     */
    function _min_size($field, $size)
    {
        return ($this->{$field} < $size) ? FALSE : TRUE;
    }

It looks like DMZ is calling the normal 'min_size' validation rule rather than the 'related_min_size' function. Is this a problem with how I'm declaring my models, or is a bug?

[eluser]OverZealous[/eluser]
@cberk
I'm looking over the diff between DM and DMZ. I only made one relevant change to the validation routine, and that was to use $this instead of $this->model when checking for rules. This can't possibly be the issue.

No changes were made for how the validation routine decides between "related" and "normal" rules.

My guess is that your $has_many definition has a typo, because that is the only way I can see the validation routine loading the wrong rule.

If you can't find that kind of mistake, try outputting some tests from within the validation routine, specifically, check the output of $field and $related around line 999, which should be 'state' and TRUE, respectively. If those are not the values, then try outputting print_r($this->has_one) and print_r($this->has_many), to make sure that 'state' appears within one.

[eluser]cberk[/eluser]
I can't find a typo, so I ran the tests you suggested.

$field == 'state', but $related == FALSE.

print_r($this->has_many) yields a nested array: Array ( [state] => Array ( [class] => state [other_field] => metro [join_self_as] => metro [join_other_as] => state ) )

in_array('state', $this->has_many) returns FALSE.

The problem appears to be that the in_array function isn't able to find the state in the list. I'm not sure how to fix it though.

[eluser]cberk[/eluser]
From reading your code, it looks like you've converted the simple has_one and has_many arrays into more advanced ones, i.e. from single to multi-dimensional arrays. The PHP in_array function apparently has trouble with multi-dimensional arrays.

If I replace in_array() with array_key_exists(), I don't get that error anymore. This could be the solution, but I don't know what other parts of the file might also need to be updated.

[eluser]OverZealous[/eluser]
You are definitely correct. That's gotta be fixed. I'm searching my code to see if there is any other places I could have missed swapping out the in_array for array_key_exists.

Thanks for finding that, an update will be posted soon.

Update: OK the fixes have been posted, on the first post in this forum.

Those two spots were the only places I could see where I used the wrong function. Weird that I would miss just those two!

[eluser]cberk[/eluser]
I looked through it too, and couldn't find any other places with that problem. I haven't run into any other problems, and it seems to be working great now.

Thanks for your work on this version!

[eluser]OverZealous[/eluser]
I found a small bug where 'related' validation rules would show an error when using the in-table $has_one relationship columns.

Also, I made some small improvements to join_related(). These are:
* The $fields array is now optional. If you don't specify it, set it to NULL, or specify it as '*', all fields on the related object are included. (This might require creating a copy of the related object.)
* A third parameter, $append_name, allows you to override the default naming method. When ignored or set to TRUE, the model or $related_field is prepended to each field. If you set it to FALSE, nothing is prepended. Finally, you can set it to anything you want, and that will be prepended.
* If a field already exists on the current object (with the $append_name), that field will be skipped silently. This means you can call $post->join_related('user', '*', FALSE), and the id field will be the id value for $post, not user.

Examples:
Code:
// Post has one User
// User has fields id, firstname, lastname

$post->join_related('user')->get_by_id(1);
// This is the same as:
//   ->join_related('user', NULL)
//   ->join_related('user', '*')
echo($post->user_id);
echo($post->user_firstname);
echo($post->user_lastname);

$post->join_related('user', 'name')->get_by_id(1);
echo($post->user_name);

$post->join_related('user', '*', 'example')->get_by_id(1);
echo($post->example_id);
echo($post->example_firstname);
echo($post->example_lastname);

$post->join_related('user', '*', FALSE)->get_by_id(1);
// note: id will be ignored, since it already exists within $post
echo($post->firstname);
echo($post->lastname);

Not all of these features have been thoroughly tested, so let me know if anything doesn't work as expected.

You can download the latest copy from here.

Finally, I have some ideas I'm planning on adding to DMZ, and I thought I'd whet your appetites:

* Extensibility: I have a method figured out that will allow everyone to add simple extensions to DataMapper without editing the core file. This will allow us to share ideas (such as query caching, or converting an object into JSON). Also, the extensions can be enabled globally, or on a per model basis.
* Production Cache: When enabled, this feature will allow DataMapper to cache a lot of the dynamically generated data, including column names (removing one query per model for every request), and validation and relationship information. The idea will be that you can delete a single file to force DM to recreate the cache, or disable it (the default) while developing code.

[eluser]matt_n[/eluser]
Hello. This is all very impressive stuff, by the way. I'm just getting into developing and such, but am enjoying workig with codeigniter and DMZ.

I am, however hitting a bit of a snag with the self-referential relationships. i can only get it to work in one direction.

Let me explain: I'm trying to nest 'Sections', which might be used to define a website hierachy for instance, like a site map. So a section can belong to one other section, or none - denoting a top level section.

In my DB I have a sections table:

Quote:SECTIONS
id
label
parentsection_id

SQL:

Quote:CREATE TABLE IF NOT EXISTS `sections` (
`id` int(11) NOT NULL auto_increment,
`label` varchar(255) default NULL,
`parentsection_id` int(11) default NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;

--
-- Dumping data for table `sections`
--

INSERT INTO `sections` (`id`, `label`, `parentsection_id`) VALUES
(1, 'products', NULL),
(2, 'news', NULL),
(3, 'new products', 1),
(4, 'nice products', 1);

So, pretty simple site map - top level is 'products' and 'news'. Products has 2 child sections, 'new products' and 'nice products'.

Here's the section model:
Code:
class Section extends DataMapper {

    var $has_one = array(
        'parentsection' => array(
            'class' => 'section'
            
            
        )
        
    
    );
    var $has_many = array(
    
    'section' => array(
        'class' => 'section',
        'other_field' => 'parentsection'
    )
    
    
    );

    function Section()
    {
        parent::DataMapper();
    }
    
}

Now in the controller I can get the products section and echo out it's children like so:

Code:
function index()
    {    
        $section = new Section();
        $section->where('id',1)->get(); // Get the products section                
        $section->section->get(); // Get children of section
        
        foreach($section->section->all as $subsection)
        {
            echo 'Section '. $section->label . ' is the parent to the ' . $subsection->label. ' Section <br />';
        }    
    }

And it outputs:
Quote:Section products is the parent to the new products Section
Section products is the parent to the nice products Section

Unsurprisingly.

However I want to be able to say something along the lines of:
Code:
function newproducts()
    {    
        $section = new Section();
        $section->where('id',3)->get(); // Get the new products section                
        $section->parentsection->get(); // Get parent of section
        
        echo 'Section '. $section->label . ' is the child of the ' . $section->parentsection->label. ' Section <br />';
            
    }

Which I would expect to output:
Quote:Section new products is the child of the products Section

But instead I get a database error:


Code:
A Database Error Occurred

Error Number: 1054

Unknown column 'sections.section_id' in 'on clause'

SELECT `sections`.* FROM (`sections`) LEFT JOIN `sections` as section_sections ON `section_sections`.`id` = `sections`.`section_id` WHERE `section_sections`.`id` = '3'

At least I can get the children of a section, but I know I'll need to find out a section's parent, so I really need to get to the bottom of it! Any help, much appreciated. Thanks for your time one and all!

Matt

[eluser]OverZealous[/eluser]
@matt_n

You found a bug! I figured it out. Give me a couple of minutes, and I'll post the updated version.

(The bug, in case you are wondering, is a slightly complicated thing related to using both self-references and the new in-table $has_one relationships.)

[eluser]OverZealous[/eluser]
Update
Fixed a bug in that prevented both self-references and the new $has_one in-table columns from working together.

Download from here

@matt_n
Let me know if the new version works for you!




Theme © iAndrew 2016 - Forum software by © MyBB