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

Why relationships model no working?

In micro not working relationships, Why they are ignored?

    namespace App\Models;

    use Phalcon\Mvc\Model;
    use Workers;

    class Accounts extends Model {
        public $id;

        public $login;

        public $worker_id;

        public function initialize() {
            $this->hasOne('worker_id', Workers::class, 'id', ['alias' => 'worker']);
        }
    }

Loader:

    $loader->registerNamespaces([
        'App\\Models'   => APP_PATH . $config->dirs->models,
    ]);

    $loader->registerDirs([
        APP_PATH . $config->dirs->controllers,
        APP_PATH . $config->dirs->models
    ]);

    $loader->register();

Returned ::find():

    id:"14"
    login:"login"
    worker_id: "1"


85.5k

Returned::find()->getRelated("worker"); ?



2.5k

Call to undefined method Phalcon\Mvc\Model\Resultset\Simple::getRelated()

Returned::find()->getRelated("worker"); ?

Dude ::find() return a Resultset Simple, you can use ::find()->current()->getRelated() or use ::findFirst() this method return a model or false. In first case then you can use Model::findFirst()->getRelated()

Good luck



2.5k
edited May '18
Uncaught Error: Call to a member function getRelated() on boolean in

I don't understand why.

Dude ::find() return a Resultset Simple, you can use ::find()->current()->getRelated() or use ::findFirst() this method return a model or false. In first case then you can use Model::findFirst()->getRelated()

Good luck



2.5k

I already learned this, but why do I have problems

its pretty well explained here https://olddocs.phalcon.io/en/3.0.0/reference/model-relationships.html

What problem? You need to access a a row, like a model from Model::find() to access related models. What's exactly your issue?



2.5k

I'm making a model connection, and it's just ignored, that's the problem. getRelated () produces an error.

What problem? You need to access a a row, like a model from Model::find() to access related models. What's exactly your issue?

edited May '18

Because you're calling getRelated() on a ResultSet, not a Model.

Notice the difference between the types returned by find() and findFirst() respectively.

/** @var Accounts[] $accounts */
$accounts = Accounts::find();
foreach($accounts as $account) {
    $worker = $account->getRelated('worker');
}

/** @var Accounts $account */
$account = Accounts::findFirst();
if($account) {
    $worker = $account->getRelated('worker');
}


43.9k

Hi,

out of topic:


$loader->registerNamespaces([
    'App\\Models'   => APP_PATH . $config->dirs->models,
]);

$loader->registerDirs([
    APP_PATH . $config->dirs->controllers,
    APP_PATH . $config->dirs->models
]);

you are registering your model directory é times

  • using namespace
  • using directory loader

I'm not sure that this is correct



2.5k

This is done, communications are still ignored. I use generally so: There is an api on the Micro, I send an inquiry via Axios to the server, and I get the records, the problem is that the records come without links

Hi,

out of topic:


$loader->registerNamespaces([
   'App\\Models'   => APP_PATH . $config->dirs->models,
]);

$loader->registerDirs([
   APP_PATH . $config->dirs->controllers,
   APP_PATH . $config->dirs->models
]);

you are registering your model directory é times

  • using namespace
  • using directory loader

I'm not sure that this is correct

Your example isn't really clear. You show code for Accounts which is related to Workers, but you show the results of Returned::find(). It's hard to see the connection.

However, I did notice one thing wrong with how you set up your relationship:

$this->hasOne('worker_id', Workers::class, 'id', ['alias' => 'worker']);

IsWorkers::class a constant? Does it map to "App\Models\Workers", because that's what you need there. I see you've used Workers, but hasOne() needs a string representation of the related class name. Simply putting "Workers" in there won't resolve to "App\Models\Workers" for the purposes of creating a relationship.

If you change your relationship to:

$this->hasOne('worker_id', "\App\Models\Workers", 'id', ['alias' => 'worker']);

then this code should work:

$Account = Account::findFirst() // or find() or whatever
$Account->worker;//should return an instance of the \App\Models\Worker class.


2.5k

Literally last night I learned that the model works, but it is not transmitted as a separate field obtained as a result of communication with Workers. I send the result generally through response-> setJsonContent. Only the Accounts model arrives, without communication Workers

Your example isn't really clear. You show code for Accounts which is related to Workers, but you show the results of Returned::find(). It's hard to see the connection.

However, I did notice one thing wrong with how you set up your relationship:

$this->hasOne('worker_id', Workers::class, 'id', ['alias' => 'worker']);

IsWorkers::class a constant? Does it map to "App\Models\Workers", because that's what you need there. I see you've used Workers, but hasOne() needs a string representation of the related class name. Simply putting "Workers" in there won't resolve to "App\Models\Workers" for the purposes of creating a relationship.

If you change your relationship to:

$this->hasOne('worker_id', "\App\Models\Workers", 'id', ['alias' => 'worker']);

then this code should work:

$Account = Account::findFirst() // or find() or whatever
$Account->worker;//should return an instance of the \App\Models\Worker class.


43.9k

if you want to get a resultset of Accounts ( == via find method) containing for each Account item its related Workers items, you can build your own response (as an array, using a foreach loop: https://forum.phalcon.io/discussion/18283/why-relationships-model-no-working#C55677)

I don't understand still your problem. Show us full code what you try to achieve. Yes it's not transmitted when you will just return $account only, phalcon doesn't lazy load related models, the query and model will be created once you access related model. If you need to get both account and worker in one query then use query builder and joins.



2.5k

Controller: public function Accounts() { $this->response->setJsonContent(['accounts' => Accounts::find()])->send(); } Model: public $id;

public $login;

public $password;

public $steam_guard;

public $worker_id;

public $steamid;

public $method_auth;

public function initialize() {
    $this->hasOne('worker_id', Workers::class, 'id', ['alias' => 'worker']);
}

And out: this.$axios.post('/admin/accounts') .then(({data}) => { console.log(data); this.accounts = data.accounts; }); console.log

And then, as you can see, there is no worker. Why?

I don't understand still your problem. Show us full code what you try to achieve. Yes it's not transmitted when you will just return $account only, phalcon doesn't lazy load related models, the query and model will be created once you access related model. If you need to get both account and worker in one query then use query builder and joins.

Because what i wrote previously when you do Accounts::findFirst() phalcon doesn't lazy load related models. If you want to get both accounts and worker you need to use query builder and make a join.



2.5k

that is, in the constructor without an ORM write the connection LEFT JOIN ...?

Because what i wrote previously when you do Accounts::findFirst() phalcon doesn't lazy load related models. If you want to get both accounts and worker you need to use query builder and make a join.



145.0k
Accepted
answer
edited May '18

Not sure what you are talking about, you need to use modelsManager service and use createBuilder method. Or you can use Accounts::query but i don't like it.



2.5k
edited May '18

Why empty

    $this->modelsManager->createBuilder()
                                    ->from(Accounts::class, 'account')
                                    ->leftJoin(Workers::class, 'worker.id = account.worker_id', 'worker')
                                    ->getQuery()
                                    ->execute();

This not empty, but here the names of objects in the console, like the namespace, not the aliases

    $this->modelsManager->executeQuery('SELECT * FROM App\Models\Accounts AS a LEFT JOIN App\Models\Workers AS w ON (a.worker_id = w.id)')

Not sure what you are talking about, you need to use modelsManager service and use createBuilder method. Or you can use Accounts::query but i don't like it.

Well not sure, but you didn't select any columns, don't remember if you need to do it or not.

Also from method accepts only one argument. If you want to use alias you need to do it like this: ->from(['account' => Accounts::class])



2.5k
edited May '18

Now it is displayed as a normal model, without a field with a Worker (model) $this->modelsManager->createBuilder() ->from(['account' => Accounts::class]) ->leftJoin(Workers::class, 'worker.id = account.worker_id', 'worker') ->getQuery() ->execute();

Well not sure, but you didn't select any columns, don't remember if you need to do it or not.

Also from method accepts only one argument. If you want to use alias you need to do it like this: ->from(['account' => Accounts::class])

You need to do ->columns('account.*,worker.*'). By default without columns argument it only selects columns from account.