Tuesday, December 8, 2015

Custom Finder Methods, Part One

Custom finder methods in CakePHP "are the ideal way to package up commonly used queries, allowing you to abstract query details into a simple to use method."

The examples below use the MySQL employee demo database; after running the scripts to install the database, bake up some basic CRUD with:

bin/cake bake all --everything

This will provide the basis upon which to follow many of the tutorials on this site.

A Simple Finder on Name


Let's start with a finder method, defined in the model for the employees table, that will return employees based on their last name:

/src/Model/Table/EmployeesTable.php
...
    public function findByName(Query $query, array $options)
    {
        $query->where([
            'Employees.last_name' => $options['lname']
        ]);
        return $query;
    }

We've created a new function, "findByName" that compares last_name in the Employees table to a passed value ('lname') from the $options array.

In our employees controller, we need a corresponding method:

/src/Controller/EmployeesController.php
...
    public function named($lname = null)
    {
        $this->set('employees', $this->paginate(
            $this->Employees->find(
                'byName', 
                ['lname' => $lname])));
        $this->set('_serialize', ['employees']);
        
        if (is_null($lname)) {
            $this->Flash->error(__('No value passed for last name.'));
        }       

        $this->render('index');
    }

You'll notice that this is almost identical to the index method with the exception of the finder method.  We could have put this in index and executed it conditionally, but I thought it cleaner to have a separate method.

Following CakePHP's idea of "convention over configuration," our finder method - named "findByName," is evoked by calling "find('byName')".  We're passing the last name which will become part of the $options array.

If no name was passed, we're flashing an error message.

We'll need a view for this, but the view in this case is identical to the existing "index.ctp" for employees; for now, let's just use it.

You should now be able to see a list of employees with a given last name by passing the last name in the URL, such as:

http://localhost:8765/employees/named/Facello



If you call "named" without passing a value, you'll see our error message:



More Complex Finders


So far we've walked through the logic of a finder method and we've created a method that can be called from anywhere to return a list of employees by last name.

In part two of this tutorial, we'll produce a list of all employees by their department number.

No comments:

Post a Comment