4

How do you check within the view template if the result object contains any entries?

(There was a similar question already, but this one is slightly different)

Take the CakePHP 3 blog tutorial for example. They show how to list all articles on one page:

// src/Controller/ArticlesController.php
public function index() {
  $this->set('articles', $this->Articles->find('all'));
}

And the view template:

<!-- File: src/Template/Articles/index.ctp -->
<table>
  <tr>
    <th>Id</th>
    <th>Title</th>
  </tr>
<?php foreach ($articles as $article): ?>
  <tr>
    <td><?= $article->id ?></td>
    <td>
      <?= $this->Html->link($article->title, ['action' => 'view', $article->id]) ?>
    </td>
</tr>
<?php endforeach; ?>
</table>

Disadvantage: if there are no entries in the database the HTML table is still rendered.

How can I prevent this and show a simple message like "Sorry no results" insteat?

In CakePHP 2 I used

if ( !empty($articles['0']['id']) ) {
  // result table and foreach here
} else {
  echo '<p>Sorry no results...</p>';
}

But since $articles is now an object this doesn't work anymore... Is there a new "short way" to check the result object? Or do you usally use another foreach first, like

$there_are_results = false;
foreach ($articles as $article) {
  if ( !empty($article->id) ) {
    $there_are_results = true;
    break;
  }
}
if ( $there_are_results == true ) {
  // result table and second foreach here
} else {
  echo '<p>Sorry no results...</p>';
}

Thanks for your hints.

Community
  • 1
  • 1
Oops D'oh
  • 941
  • 1
  • 15
  • 34

3 Answers3

24

You can use the iterator_count() function to know if there are results in the set:

if (iterator_count($articles)) {
 ....
}

You can also use the collection methods to get the first element:

if (collection($articles)->first()) {
}

Edit:

Since CakePHP 3.0.5 the best way to check for emptiness on a query or a result set is this:

if (!$articles->isEmpty()) {
    ...
}
  • Thank you very much, I appreciate your hints! All methods work, but the count-method is the shortest code snippet, even shorter as iterator_count. The collection-code needs to be modified a little bit to be useful: `if ( isset(collection($articles)->first()->id) ) { /*render table */ } else { /* no results */ }` – Oops D'oh May 05 '15 at 00:45
  • 3
    btw I implemented $query->isEmpty() just for you ;) https://github.com/cakephp/cakephp/pull/6483 It should be available in CakePHP 3.0.5 – José Lorenzo Rodríguez May 06 '15 at 19:38
1

I believe you can call $articles->count() from your template. (Check for 0)

Keylan
  • 325
  • 1
  • 12
0

Something I have been struggling for a while..

if(!$articles->isEmpty()) {
gives error on empty value
Call to a member function isEmpty() on null
<?php if(iterator_count($articles)) { ?>
Argument 1 passed to iterator_count() must implement interface Traversable, null given
<?php if (collection($articles)->first()) {?>
Only an array or \Traversable is allowed for Collection

I got to work, the problem if you render a different view in the controller $this->render('index'); for a function you should do that after the values has been set

gabrielkolbe
  • 145
  • 9