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

Query builder "alias" parameter

Hi.

Let us assume a simple situation in which, for example, we want get "articles" by referring to the model and using the built-in "find" method. Morover, for the "articles" we would like to include the model of the "authors" of the article.

In this situation, the code would look like:

$articeles = \Models\ArticlesModel::find([
    'joins' => [
        'Models\Authors',
        'author.id = [Models\Articles].fk_author',
        'author',
        'inner'
    ],
    'columns' => [
        '[Models\Correspondences].*',
        'author.*'
    ],
]);

I understand that we can also use the "createBuilder" method from the shared "modelsManager" service and use the parameter "models", but then we do not refer to the selected model class. I would still like to use the model class and the "find" method.

Unfortunately, in this situation, the main model we refer to appears in the object "models\Articles". Object of result shows:

Object Phalcon\Mvc\Model\Row (
->models\Articles (public) = Object Models\Articles extends Abstr\Models\AbstractArticles (
     Models\Articles methods: (98) (
       ->initialize();
       ->validation();
       ->setId();
      ...
 ->author = Object Models\Authors extends Abstr\Models\AbstractAuthors (
     Models\Authors methods: (98) (
       ->initialize();
       ->validation();
       ->setId();
      ...
 )

It is not easy to appeal to him because it would be necessary to use:

$articles->getFirst()->{'models\Articles'};

In addition, you probably can not refer from the Volt template in this way.

In this situation, it would help to add the "alias" parameter to the builder. This parameter would be used as an alias for the main model to which we refer. In this way, it would replace "models\Articles" with the definition of "articles". For example:

$articeles = \Models\ArticlesModel::find([
    'alias' => 'article',
    'joins' => [
        'Models\Authors',
        'author.id = [Models\Articles].fk_author',
        'author',
        'inner'
    ]
    ...
]);

Result:

 Object Phalcon\Mvc\Model\Row (
 ->article = Object Models\Articles extends Abstr\Models\AbstractArticles (
     Models\Articles methods: (98) (
       ->initialize();
       ->validation();
       ->setId();
      ...
 ->author = Object Models\Authors extends Abstr\Models\AbstractAuthors (
     Models\Authors methods: (98) (
       ->initialize();
       ->validation();
       ->setId();
      ...
 )

I was able to overwrite the built-in method "getPreparedQuery". Works as it should. The zephir method would look like this:


    /**
     * shared prepare query logic for find and findFirst method
     */
    private static function getPreparedQuery(var params, var limit = null) -> <Query> {
        var builder, bindParams, bindTypes, transaction, cache, manager, query, dependencyInjector;

        let dependencyInjector = Di::getDefault();
        let manager = <ManagerInterface> dependencyInjector->getShared("modelsManager");

        /**
         * Builds a query with the passed parameters
         */
        let builder = manager->createBuilder(params);

        if isset params["alias"] {
            builder->from([params["alias"] => get_called_class()]);
        } else {
            builder->from(get_called_class());
        }

        if limit != null {
            builder->limit(limit);
        }

        let query = builder->getQuery();

        ...

Please consider the proposal.

Regards Przemyslaw

Hi it's a good idea, create NPR and share your idea in github repo

Good luck