brandonwestcott / li3_relations

A Lithium PHP plugin designed to add support to li3 for relations on a Model to Model basis separate from connections
1 stars 2 forks source link

Defining nested relationships Fatal Error with Database connector #5

Open hibrid opened 12 years ago

hibrid commented 12 years ago

When calling a model like this:

$actions = Actions::find('all', array( 'with' => array( 'Masters' ) ));

The model has a defined relationship likes this:

public $hasMany = array( 'Masters'=>array( 'key' => array('id' => 'action_id'), 'with' => array( 'MasterConditions' ) ) );

And the MasterConditions model referenced above is configured like this:

public $belongsTo = array('Masters');

This throws the following Fatal error:

[10-Nov-2012 15:32:42 UTC] PHP Fatal error: Uncaught exception 'InvalidArgumentException' with message 'Invalid query typehasMany`.' in \libraries\lithium\data\source\Database.php:445 Stack trace:

0 \libraries\lithium\data\source\Database.php(298): lithium\data\source\Database->renderCommand(Object(lithium\data\model\Query))

1 \libraries\lithium\util\collection\Filters.php(202): lithium\data\source\Database->lithium\data\source{closure}(Object(lithium\data\source\database\adapter\MySql), Array, Object(lithium\util\collection\Filters))

2 \app\libraries\li3_relations\extensions\data\Model.php(206): lithium\util\collection\Filters->next(Object(lithium\data\source\database\adapter\MySql), Array, Object(lithium\util\collection\Filters))

3 \libraries\lithium\util\collection\Filters.php(183): li3_relations\extensions\data\Model::li3_relations\extensions\data{closure}(Object(lithium\data\source\database\adapter\MySql), Array, Object(lithium\uti in \libraries\lithium\data\source\Database.php on line 445`

I have solved the problem by doing the following code right after: $relation = $alternateRelations[$relationKey]->data();

//set the type to read of this is not a mongodb connection if(is_a($self,'lithium\data\source\Database')) { $relation['type'] = 'read'; }

Hoping to see if you have a better solution.

brandonwestcott commented 12 years ago

I have not had a chance to test in MySQL yet. We've only been using it for Mongo, Solr & custom data sources.

My goal is to to check the connection directly, and do the manipulations necessary. What is the purpose of $relation['type'] = 'read' in MySQL?

hibrid commented 12 years ago

Here is an example of what gets passed as the 'Query' object to \libraries\lithium\data\source\Database.php to the read method.

Here is the Actions model:

class Actions extends \li3_relations\extensions\data\Model {
    public $hasMany = array(

                            'Masters'=>array(
                                                'key'       => array('id' => 'action_id'),
                                                'with'      => array(
                                                    'MasterConditions'
                                                )
                                             ),
                            'Subscriptions'=>array(
                                                        'key'   => array('id' => 'action_id')    
                                                    )
                            );
    public $belongsTo = array('Systems');
}

Here is the Query object for the Actions model that is passed to the read method in \libraries\lithium\data\source\Database.php:

lithium\data\model\Query Object
(
    [_type:protected] => read
    [_map:protected] => Array
        (
        )
    [_entity:protected] => 
    [_data:protected] => Array
        (
        )
    [_autoConfig:protected] => Array
        (
            [0] => type
            [1] => map
        )
    [_config:protected] => Array
        (
            [conditions] => 
            [fields] => 
            [order] => 
            [limit] => 
            [page] => 
            [alternateWith] => Array
                (
                    [0] => Masters
                    [1] => Subscriptions
                )
            [model] => app\models\Actions
            [calculate] => 
            [data] => Array
                (
                )
            [alias] => Actions
            [source] => actions
            [offset] => 
            [name] => Actions
            [group] => 
            [comment] => 
            [joins] => Array
                (
                )
            [map] => Array
                (
                )
            [whitelist] => Array
                (
                )
            [relationships] => Array
                (
                )
        )
    [_methodFilters:protected] => Array
        (
        )
)

Here is the Query object for the Masters model defined in the Actions model:

lithium\data\model\Query Object
(
    [_type:protected] => hasMany
    [_map:protected] => Array
        (
        )
    [_entity:protected] => 
    [_data:protected] => Array
        (
        )
    [_autoConfig:protected] => Array
        (
            [0] => type
            [1] => map
        )
    [_config:protected] => Array
        (
            [key] => Array
                (
                    [id] => action_id
                )
            [default] => 
            [to] => app\models\Masters
            [name] => Masters
            [from] => app\models\Actions
            [fieldName] => masters
            [link] => key
            [fields] => 
            [constraint] => Array
                (
                )
            [conditions] => Array
                (
                    [action_id] => Array
                        (
                            [0] => 1
                            [1] => 2
                        )
                )
            [order] => 
            [limit] => 
            [page] => 
            [alternateWith] => Array
                (
                    [0] => MasterConditions
                )
            [model] => app\models\Masters
            [calculate] => 
            [data] => Array
                (
                )
            [alias] => Masters
            [source] => masters
            [offset] => 
            [group] => 
            [comment] => 
            [joins] => Array
                (
                )
            [map] => Array
                (
                )
            [whitelist] => Array
                (
                )
            [relationships] => Array
                (
                )
        )
    [_methodFilters:protected] => Array
        (
        )
)

The problem is that type should be read like the Actions query object but here its set to 'hasMany' and it ends up throwing an exception in the Database::renderCommand() method when it checks it against the Database::_strings property. The 'read' type is added in Database::__construct.

Another place we could add the statement I provided is in li3_relations\extensions\data\Model::bind() right after $connection = static::connection();

Thoughts?