We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

hasMany relationship not working

I have pasted both model class and resultset, please help me to findout why not working

namespace Yesse\Model;

use Phalcon\Mvc\Model;
class Account extends Model {
    public function initialize() {
        $this->setSource( "accounts" );
        $this->hasMany( 'id', 'Yesse\Model\AccountDomains', 'accounts_id' );
    }
}

use Phalcon\Mvc\Model;

class AccountDomains extends Model {

protected $id;
protected $account_id;
protected $username;

public function initialize() {
    $this->setSource( "account_domains" );
    $this->belongsTo( "account_id", "Yesse\Model\Account", "id", array( 'alias' => 'accountDomains' ) );
}

}

Phalcon\Mvc\Model\Resultset\Simple Object
(
[_result:protected] => Phalcon\Db\Result\Pdo Object
    (
        [_connection:protected] => Phalcon\Db\Adapter\Pdo\Mysql Object
            (
                [_eventsManager:protected] => 
                [_descriptor:protected] => Array
                    (
                        [adapter] => Mysql
                        [host] => 127.0.0.1
                        [username] => root
                        [password] => 123
                        [dbname] => yesse
                    )

                [_dialect:protected] => Phalcon\Db\Dialect\Mysql Object
                    (
                        [_customFunctions:protected] => 
                        [_escapeChar:protected] => `
                    )

                [_connectionId:protected] => 0
                [_sqlStatement:protected] => 
                [_sqlVariables:protected] => 
                [_sqlBindTypes:protected] => 
                [_transactionLevel:protected] => 0
                [_transactionsWithSavepoints:protected] => 
                [_pdo:protected] => PDO Object
                    (
                    )

                [_affectedRows:protected] => 
                [_type:protected] => mysql
                [_dialectType:protected] => mysql
            )

        [_result:protected] => 
        [_fetchMode:protected] => 2
        [_pdoStatement:protected] => PDOStatement Object
            (
                [queryString] => SELECT `accounts`.`id`, `accounts`.`name`, `accounts`.`username`, `accounts`.`created_at` FROM `accounts`
            )

        [_sqlStatement:protected] => SELECT `accounts`.`id`, `accounts`.`name`, `accounts`.`username`, `accounts`.`created_at` FROM `accounts`
        [_bindParams:protected] => 
        [_bindTypes:protected] => 
        [_rowCount:protected] => 2
    )

[_cache:protected] => 
[_isFresh:protected] => 1
[_pointer:protected] => 0
[_count:protected] => 2
[_activeRow:protected] => 
[_rows:protected] => Array
    (
        [0] => Array
            (
                [id] => 1
                [name] => demo
                [username] => demo
                [created_at] => 2016-04-27 00:00:00
            )

        [1] => Array
            (
                [id] => 2
                [name] => demo2
                [username] => demo2
                [created_at] => 2016-04-27 00:00:00
            )

    )

[_row:protected] => 


85.5k

i am not expert of those reletionships, but did you call $result->getAccountDomains(); ?



4.9k

I tried, it does not work -> Fatal error: Call to undefined method Phalcon\Mvc\Model\Resultset\Simple::getAccountDomains()

edited Apr '16

You have:

$this->hasMany( 'id', 'Yesse\Model\AccountDomains', 'accounts_id' );

While in AccountDomains you have protected $account_id;

Also

array( 'alias' => 'accountDomains' )

this should be in

$this->hasMany( 'id', 'Yesse\Model\AccountDomains', 'accounts_id' );

i guess

Here

$this->belongsTo( "account_id", "Yesse\Model\Account", "id", array( 'alias' => 'accountDomains' ) );

Alias should be account i think for example



4.9k

I tried it does not worked

class AccountDomains extends Model {

public function initialize() {
    $this->setSource( "account_domains" );
    $this->belongsTo( "accounts_id", "Yesse\Model\Account", "id", array( 'alias' => 'accountDomains' ) );
}
}

class Account extends Model {

public function initialize() {
    $this->setSource( "accounts" );
    $this->hasMany( 'id', 'Yesse\Model\AccountDomains', 'accounts_id', ['alias' => 'account' ] );
}

}

edited Apr '16

Did you even read what i wrote ?

In class AccountDomains you have:

$account_id;

But in relations you have accounts_id

$this->hasMany( 'id', 'Yesse\Model\AccountDomains', 'accounts_id', ['alias' => 'account' ] );
$this->hasMany( 'id', 'Yesse\Model\AccountDomains', 'accounts_id' );


4.9k

I have this whole classes, still not working

 class Accounts extends Model {

    protected $id;
    protected $name;
    protected $username;
    protected $created_at;

    public function initialize() {
        $this->setSource( "accounts" );
        $this->hasMany( 'id', 'Yesse\Model\AccountDomains', 'accounts_id', ['alias' => 'accounts' ] );
    }

}

    class AccountDomains extends Model {

    protected $id;
    protected $accounts_id;
    protected $domain;

    public function initialize() {
        $this->setSource( "account_domains" );
        $this->belongsTo( "accounts_id", "Yesse\Model\Accounts", "id", array( 'alias' => 'accountDomains' ) );
    }

}
edited Apr '16

What exactly is not working ? Can you provide some sample what are you accessing/finding ?

Fatal error: Call to undefined method Phalcon\Mvc\Model\Resultset\Simple::getAccountDomains()

Yes this is true beacause there is no such a method.

If you want to select all Accounts with all AccountDomains you need to use modelsManager beacause you need to join related records:

$accounts=$modelsManager->createBuilder() //got from di
->columns(['AccountDomains.*','Accounts.*'])
->from(['Accounts'=>'Yesse\Model\Accounts'])
->leftJoin('Yesse\Model\AccountDomains', null, 'AccountDomains')
->getQuery()
->execute();

Also you should name Accounts as Account, and AccountDomains as AccountDomain. Beacause they are single entity of single record. They don't store collection of Accounts and of AccountDomains.



4.9k

[queryString] => SELECT accounts.id, accounts.name, accounts.username, accounts.created_at FROM accounts this sql string it generated, i expecting it with joins

goal is to get all domains in account

So as i just wrote above. You need to tell phalcon to select them with join. It's pretty obvious. Doesn't it ? Accounts::find() just find accounts.



4.9k
edited Apr '16

I'm getting error

$robot = new Accounts();
$accounts = $robot->get( 'modelsManager' )->createBuilder() //got from di
        ->columns( ['AccountDomains.*', 'Accounts.*' ] )
        ->from( ['Accounts' => 'Yesse\Model\Accounts' ] )
        ->leftJoin( 'Yesse\Model\AccountDomains', null, 'AccountDomains' )
        ->getQuery()
        ->execute();

print_r( $accounts );

Fatal error:  Uncaught exception 'InvalidArgumentException' with message 'Parameter 'alias' must be a string' in E:\owned\yesse\public\index.php:38
Stack trace:
#0 [internal function]: Phalcon\Mvc\Model\Manager->getRelationByAlias('Yesse\\Model\\Acc...', false)
#1 [internal function]: Phalcon\Mvc\Model->_getRelatedRecords('Yesse\\Model\\Acc...', 'get', Array)
#2 E:\owned\yesse\public\index.php(38): Phalcon\Mvc\Model->__call('get', Array)
#3 E:\owned\yesse\public\index.php(38): Yesse\Model\Accounts->get('modelsManager')
#4 [internal function]: Closure->{closure}()
#5 E:\owned\yesse\public\index.php(50): Phalcon\Mvc\Micro->handle()
#6 {main}
  thrown in E:\owned\yesse\public\index.php on line 38

Or you can use simpler:

$accounts=Accounts::query()
    ->leftJoin('Yesse\Model\AccountDomains')
    ->execute()

But i would recommend to specify columns which you need from each model. You should use full objects only for updating related records IMHO. If it's for displaying then select columns and get rid of hydration.

$robot = new Accounts(); $accounts = $robot->get( 'modelsManager' )

What is this ?



4.9k

I used to get di service modelsManager

edited Apr '16
$robot = new Accounts(); $accounts = $robot->get( 'modelsManager' )

But $robot is not di ! It's just model without method get. By di i meant depedency injector container.

edited Apr '16

If you are using 2.1.x:

$modelsManager=$this->getDI()->get('modelsManager');
$modelsManager->createBuilder() //got from di
->columns(['AccountDomains.*','Accounts.*'])
->from(['Accounts'=>'Yesse\Model\Accounts'])
->leftJoin('Yesse\Model\AccountDomains', null, 'AccountDomains')
->getQuery()
->execute();

If 2.0.x then you need to add use ($app) in micro function(perhaps you already have it) and then:

$modelsManager=$app->getDI()->get('modelsManager');
$modelsManager->createBuilder() //got from di
->columns(['AccountDomains.*','Accounts.*'])
->from(['Accounts'=>'Yesse\Model\Accounts'])
->leftJoin('Yesse\Model\AccountDomains', null, 'AccountDomains')
->getQuery()
->execute();

You can also use shorthand $app->modelsManager / $this->modelsManager but i don't like it.