Solved thread

This post is marked as solved. If you think the information contained on this thread must be part of the official documentation, please contribute submitting a pull request to its repository.

Model::find()

Hallo to everyone, i have a model with a simple relation

Username: Id,Name,Email,...

UsernameOptions: Id,User_Id,Key,Value

When i am using now $result=Username::findFirst() i get all the Username´s entries. but not the options. There i have to call it like result->usernameOptions. Is there a way do avoid the lazy loading and load already all relations with the "Username::findFirst() and/or Username::find()"?

Thanks Pat



48.4k
Accepted
answer

You can overload the static method Model::findFirst and Model::find to first do the normal find and then to perform an action right after that. It will require a non-basic understanding of working with PHP static scopes.

Also you can have it be automatically done in the afterFetch model event but then it will fire the query N times, once for each record.



3.1k

You should use the query builder for this: https://docs.phalconphp.com/en/latest/api/Phalcon_Mvc_Model_Query_Builder.html

Then you can find the results in the row returned and setup the hierarchy. There's an issue filed for the functionality you're looking for: https://github.com/phalcon/cphalcon/issues/1117



48.4k

Why are you specifically recommending the query builder over PHQL style? I see it that it is just a preference and it doesn't resolve his issue either way. The issue is just a dream today and doesn't help him.

thanks for your answers. i am using now afterFetch and it is working. but i have one last question. if i am defining a column set, there is no relation anymore to the UsernameOptions

Username::find(array('columns'=>'id'));

and if i am using something like this, i get an error that the alias is not working. i tried it with the right alias, and the full namespace/model class.

Username::find(array('columns'=>'id,UsernameOptions.value'));

is there another way i have to do it?



48.4k

If you select just a single column then it will be returning a complex resultset intead of a simple one. That means that it isn't a model record anymore. You need to accept all * fields to recieve a model.



48.4k

Maybe I misread your last question. You are asking for records from two fields but you need to have a join condition and to first even select the other table with the appropriate join, ex; LEFT, RIGHT. I like using the normal query.

hey dschissler, thanks for your answer anyway. i will describe it a litte bit more percise.

I have following code: A Model User which has normal data like username, email,... and 3 other relations.

class User extends Model
{

    /** Initialize method for model.*/
    public function initialize()
    {
        $this->setSource($this->tableName);
        $this->hasMany('id', __NAMESPACE__ . '\UserRole', 'authuserentity_id', array('alias' => 'UserRoles', 'foreignKey' => array('action' => Relation::ACTION_CASCADE)));
        $this->hasMany('id', __NAMESPACE__ . '\Option', 'user_id', array('alias' => 'Options', 'foreignKey' => array('action' => Relation::ACTION_CASCADE)));
        $this->hasMany('id', __NAMESPACE__ . '\Protocol', 'user_id', array('alias' => 'Protocols', 'foreignKey' => array('action' => Relation::ACTION_CASCADE)));

    }
    ....

so if i am using

$model = User::find();
foreach($model as $user){
    $options = $user->getOptions();
}

i will receive the Options.

now i just wanna have the field for example id of the User Model and only the field value of the Option Model. but ther i dont know how to add the columns from the relations. I dont think i need to add a extra join because the relation is already defined!?

$model = User::find(array('columns'=>'id,?value?'));

thanks for your time. pat



48.4k
edited Dec '15

There are many ways to get data in Phalcon and I'll give you the style that I like to use.

use Phalcon\Mvc\Model\Query;

// I like to use this approach because some types of aliases currently fail for much more complicated queries.
$User = "Namespace\\User";
$Option = "Namespace\\Option";

// With implicit joining disabled
$phql = "SELECT User.id, Option.value FROM $User User JOIN $Option Option ON User.id = Option_user.id";

// With implicit joining enabled based on defined relationship to automatically fill in the "ON" condition
$phql = "SELECT User.id, Option.value FROM $User User JOIN $Option Option";

$query = new Query($phql, $di);
// The result will be a complex resultset, meaning not models.
$results = $query->execute();

Also apologies if it doesn't work because I didn't actually run this code.

[edit] I'll add that I only use this style if I'm doing joins because it allows the PHQL to be easily expanded into complicated nested queries.

edited Dec '15

thanks dschissler with phql i already tried it and it is working. but i was just wondering if its also somehow possible over the normal "find" function. tried already many ways but with everything i got the error that the module or alias could not be found.

but in that case i will switch to phql :)



48.4k

I don't know if there is a way to join tables using Model::find.

but in that case i will switch to phql :)

When you use Model::find you are also using PHQL but only as a condition fragment.



48.4k

There is also a way to define an alias for a namespace for the entire system and that is more concise then saving it as a variable like $User = "Namespace\\User"; for each Query. So perhaps try that if you are finding that the queiries are looking clumsy.

Well there is no something like partial model in phalcon orm like in doctrine.