Search code examples
phpphalconvolt

Phalcon & Volt: Adding hasMany()/belongsTo() conditions, and counting linked rows


I have two tables in my database, form_settings and webmaster, that are on a one-to-many relationship, and this has been defined in their Models.

FormSettings.php

class FormSettings extends \Phalcon\Mvc\Model
{    
    public function initialize()
    {
        $this->hasMany('db_table', 'webmaster', 'db_table');
    }
}

Webmaster.php

class FormSettings extends \Phalcon\Mvc\Model
{    
    public function initialize()
    {
        $this->belongsTo('db_table', 'form_settings', 'db_table');
    }
}

In my Controller, I perform the following find() and pass it to the view:

ControllerBase.php

class ControllerBase extends Controller
{
    public function initialize()
    {
        $exhibitions = FormSettings::find(
            array(
                'form_type = "v" AND show_end_date > NOW() AND archived = "n"',
                'order' => 'db_table'
            )
        );

        $this->view->exhibitions = $exhibitions;
    }
}

And I know it's correctly linking rows from my webmaster table, as I have the following code in my View, and it displays webmaster_id values:

index.volt

{% for exhibition in exhibitions %}
    <li>
        {{ link_to('index/browse/' ~ exhibition.db_table, exhibition.db_table) }}
        <!-- testing below -->
        {% for webm in exhibition.webmaster %}
            {{ webm.webmaster_id }}
        {% endfor %}
        <!-- end testing -->
    </li>
{% endfor %}

My question is three-part:

  1. How can I only link webmaster rows that have a column extra_1 as not NULL?
  2. How can I count() the linked webmaster rows for each db_table (which is unique in form_settings)?
  3. How can I pass this information through to the View in my $exhibitions object so that I can echo the count() in Volt syntax?

Solution

  • Hey and first of all thank you for the nice question formatting.

    Excuse me for using examples that use my current database structure. But you can easily update your code.

    1) You can set additional parameters to the relation definition.

    $this->hasMany('id', 'Models\News', 'category_id', [
        'alias' => 'news',
        'reusable' => true, 
        'params' => [
            'order' => 'id DESC',
            'conditions' => 'extra_1 IS NOT NULL',
        ]
    ]);
    

    Please note the reusable above. When using it, the query runs only once per request. Considering you want to count records and iterate over them its a nice performance boost.

    2 + 3) Iterating over results in volt and counting:

    Controller code:

    $this->view->categories = \Models\NewsCategories::find();
    

    Volt:

    {% for category in categories %}
        {% if category.news|length > 0 %} // Do not print categories without articles
        <h3>Category #{{ category.id }} with total of {{ category.news|length }} articles.</h3>
        <ul>
        {% for item in category.news %}
            <li>News #{{ item.id }}</li>
        {% endfor %}
        </ul>
        {% endif %}
    {% endfor %}
    

    The above code in my case produces the following output:

    Category #4 with total of 4 articles.

    • News #3
    • News #4
    • News #5
    • News #7

    Category #5 with total of 1 articles.

    • News #1