Friends of Cake Search: Hide index results until form submit

I’m using the Friends of Cake Search plugin in my project, and it’s working great. I would, however, like the default view of my search page to be nothing but the search input form until the submit button is pressed. The default right now is to load everything and then filter based on the search criteria. Here’s the code for my search engine:

public function search()
    $query = $this->MissionLessons->find('search', [
        'search' => $this->request->getQueryParams()]
    ->contain(['Missions', 'ReqStatuses', 'Discrepancies', 'Engineers', 'Initiator']);

    $this->paginate = [
        'contain' => ['Missions', 'ReqStatuses', 'Discrepancies', 'Engineers', 'Initiator'],

    $this->set('missionLessons', $this->paginate($query));

I thought that wrapping the whole thing in if ($this->request->is('post') would do it, but then that caused problems in my search view, which is expecting the value of $missionLessons to be set. Adding if (isset($missionLessons)) didn’t help. Here’s the relevant code for the results view, without the form:

    <?php foreach ($missionLessons as $missionLesson): ?>
            <td class ="actions"><?= $this->Html->link(__($missionLesson->mission->mission_id), ['action' => 'view', $missionLesson->id]) ?></td>
            <td><?= h($missionLesson->req_status->status) ?></td>
            <td><?= $missionLesson->int_ext === 1 ? 'Internal' : 'External' ?></td>
            <td><?= h($missionLesson->owner) ?></td>
            <td><?= h($missionLesson->discrepancy->description) ?></td>
            <td><?= h($missionLesson->engineer->full_name) ?></td>
            <td><?= h($missionLesson->initiator->full_name) ?></td>
            <td colspan="7"><?= "Description: " . $missionLesson->description ?></td>
        <?php endforeach; ?>

Any ideas on how I can keep the values of $missionLessons hidden until after the user chooses some search criteria?

I think you were on the right track with checking for is('post'), and isset($missionLessons) should be the corresponding change in the template. I’d guess that one or both of your conditions did not encompass a large enough block of code. The check in the controller should wrap everything up to and including set('missionLessons'), and the check in the template should wrap (at least) the entirety of the table.

Note that search uses the PRG pattern.

I would suggest use the isSearch() function after calling the search finder.

$query = $this->MissionLessons
   ->find('search', ['search' => $this->request->getQueryParams()]);
   // ...

$data = $this->MissionLessons->isSearch() ? $this->paginate($query) : [];
$this->set('missionLessons', $data);

I think this wont work until some filter is filled, if you want to allow show all results use a queryParam as flag (sent by the form by default)

Thanks for the tip. When I try to use isSearch() in the manner you suggest, I get the following error:

Argument 1 passed to Cake\Utility\Inflector::tableize() must be of 
the type string, null given, called in 
/var/www/html/midb/vendor/cakephp/cakephp/src/View/Helper/PaginatorHelper.php on line 754

So even when I have if (isset($missionLessons)) in my view, it looks like it’s still expecting a value. Wrapping the controller code in `if ($this->request->is([‘get’, ‘post’]) got me the same result.

You’ve got some reference to the paginator (page links, maybe?) outside of what you’re excluding with the isset check.

A deeper dive on isSearch() got me what I wanted.

Rather than test for that in the controller, I put it in my view, using it to wrap the div that contains my results, thus:

<?php if ($this->Search->isSearch() { ?>
        <th><?= Paginator stuff ?></th>

        <?php foreach ($missionLessons as $missionLesson) : ?> 
            <?= results ?>
<?php  } ?>

Now, my search page loads with only the search options showing, and I only see the div when I submit a search. Thanks to both of you for the hints!