How can I handle unfound records?

I’ve built my app in CakePHP 5, and it’s all working basically fine, but now I want to handle cases like a user trying to access a page that doesn’t exist.

For example, currently in my admin area I have the route /admin/users/edit/{id}, which has the following controller method:

public function edit($id = null) {
  if(!$id) {
    $this->Flash->error(__('Page not found'));
    return $this->redirect(['action' => 'index']);
  }
  $user = $this->Users->get($id);
  if ($this->request->is(['patch', 'post', 'put'])) {
    $user = $this->Users->patchEntity($user, $this->request->getData());
    if ($this->Users->save($user)) {
      $this->Flash->success(__('User name updated'));
      return $this->redirect(['action' => 'index']);
    }
    $this->Flash->error(__('The user name could not be updated.  Please try again.'));
  }
  $this->set(compact('user'));
}

This works fine as long as the id passed in belongs to a user in the database. However, I want to handle cases where the id doesn’t exist.

Currently if I call the method with an incorrect id, I get the standard error page which looks like this:

I tried adding in the following:

if(!$user) {
$this->Flash->error(__('User not found'));
return $this->redirect(['action' => 'index']);
}
after the line $user = $this->Users->get($id); but I’m still getting the same page, presumably because the error is triggered in the get method.

I then tried to use a try… catch, but couldn’t make any sense of the documentation for creating Exception templates etc., and I’m not even sure whether I needed to do all that.

Could someone clarify how situations like this should be handled? Is there a ‘best practice’?

You get that “nice” error page because you are in debug mode.

If you disable debug mode and got to that page you get a different error page which is based on the templates/Error/error400.php

1 Like
try {
    $user = $this->Users->get($id);
} catch (RecordNotFoundException|InvalidPrimaryKeyException $ex) {
    $this->Flash->error(__('User not found'));
    return $this->redirect(['action' => 'index']);
}

With this version, you don’t even need the if(!$id) bit. You will need

use Cake\Datasource\Exception\InvalidPrimaryKeyException;
use Cake\Datasource\Exception\RecordNotFoundException;

at the top of the file.

1 Like

Oh, of course! I’d forgotten that debug mode displayed differently! Thanks!

Thank you, that’s helpful!