mpdc mpdc - 3 months ago 49
PHP Question

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?


Answer

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