Actions

Note

CRUD already provides the basic Index, View, Add, Edit and Delete actions, so you do not need to implement these on your own. You can find the documentation for these actions in the menu to the left.

Crud Actions are the backbone of the plugin, this is where most of the logic happens.

What Is An Action?

A Crud action roughly translates to a normal Controller action. The primary difference is that CRUD actions are made to be as generic and secure out of the box as possible.

You can consider a CRUD action as a more flexible PHP trait that fits nicely within the CakePHP ecosystem.

A nice added bonus is that if all your controllers share a generic controller action, you only have to unit test once, to test every controller in your application.

The Anatomy Of An Action

Below is the code for the Index Crud Action

In the next few sections we will walk through the code and explain how it works, and what every single line of code does. For each section, the relevant lines of code will be highlighted.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
namespace Crud\Action;

class Index extends BaseAction
{

    /**
     * Generic handler for all HTTP verbs
     *
     * @return void
     */
    protected function _handle()
    {
        $subject = $this->_subject();
        $subject->set(['success' => true, 'viewVar' => $this->viewVar()]);

        $this->_trigger('beforePaginate', $subject);

        $controller = $this->_controller();
        $items = $controller->paginate();
        $subject->set(['items' => $items]);

        $this->_trigger('afterPaginate', $subject);

        $controller->set(['success' => $subject->success, $subject->viewVar => $subject->items]);
        $this->_trigger('beforeRender', $subject);
    }

}

Class And Namespace

All build-in actions in Crud live in the Crud\Action namespace.

All actions in Crud, even your own, should inherit from the Crud\Action\Base class. This class is abstract and provides numerous auxiliary methods which can be useful for you both as a developer as an action creator.

Where you choose to put your custom Crud actions is up to you, but using src/Crud is a good place. Remember to namespace your action class accordingly.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
namespace Crud\Action;

class Index extends BaseAction
{

    /**
     * Generic handler for all HTTP verbs
     *
     * @return void
     */
    protected function _handle()
    {
        $subject = $this->_subject();
        $subject->set(['success' => true, 'viewVar' => $this->viewVar()]);

        $this->_trigger('beforePaginate', $subject);

        $controller = $this->_controller();
        $items = $controller->paginate();
        $subject->set(['items' => $items]);

        $this->_trigger('afterPaginate', $subject);

        $controller->set(['success' => $subject->success, $subject->viewVar => $subject->items]);
        $this->_trigger('beforeRender', $subject);
    }

}

Request Methods

Next is the method _handle. A Crud Action can respond to any HTTP verb (GET, POST, PUT, DELETE). Each HTTP verb can be implemented as method, e.g. _get() for HTTP GET, _post() for HTTP POST and _put() for HTTP PUT.

If no HTTP verb specific method is found in the class, _handle() will be executed.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
namespace Crud\Action;

class Index extends BaseAction
{

    /**
     * Generic handler for all HTTP verbs
     *
     * @return void
     */
    protected function _handle()
    {
        $subject = $this->_subject();
        $subject->set(['success' => true, 'viewVar' => $this->viewVar()]);

        $this->_trigger('beforePaginate', $subject);

        $controller = $this->_controller();
        $items = $controller->paginate();
        $subject->set(['items' => $items]);

        $this->_trigger('afterPaginate', $subject);

        $controller->set(['success' => $subject->success, $subject->viewVar => $subject->items]);
        $this->_trigger('beforeRender', $subject);
    }

}

You can treat the _handle() method as a catch-all, if your crud action wants to process all possible HTTP verbs.

An advantage of this setup is that you can separate the logic on a request type level instead of mixing all of the logic into one big block of code.

For example the Edit Crud Action implements _get(), _post() and _put() methods. The _get() method simply reads the entity from the database and passes it to the form, while _put() handles validation and saving the entity back to the database.

Events & Subject

All Crud actions emit a range of events, and all of these events always contain a Crud Subject. The Crud Subject can change its state between emitted events. This object is a simple StdClass which contains the current state of the Crud request.

The real beauty of Crud is the events and the flexibility they provide.

All calls to _trigger() emit an event, that you as a developer can listen to and inject your own application logic. These events are in no way magical, they are simply normal CakePHP events, dispatched like all other events in CakePHP.

You can for example listen for the beforePaginate event and add conditions to your pagination query, just with a few lines of code. Those few lines of code is what makes your application unique. The rest of the code you would normally have is simply repeated boiler plate code.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
namespace Crud\Action;

class Index extends BaseAction
{

    /**
     * Generic handler for all HTTP verbs
     *
     * @return void
     */
    protected function _handle()
    {
        $subject = $this->_subject();
        $subject->set(['success' => true, 'viewVar' => $this->viewVar()]);

        $this->_trigger('beforePaginate', $subject);

        $controller = $this->_controller();
        $items = $controller->paginate();
        $subject->set(['items' => $items]);

        $this->_trigger('afterPaginate', $subject);

        $controller->set(['success' => $subject->success, $subject->viewVar => $subject->items]);
        $this->_trigger('beforeRender', $subject);
    }

}

Boilerplate

Only the code that you would normally have in your controller is left now.

While these 3 lines seem simple, and the whole Crud implementation a bit overkill at first, the true power of this setup will be clear when your application grows and the requirements increase.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
namespace Crud\Action;

class Index extends BaseAction
{

    /**
     * Generic handler for all HTTP verbs
     *
     * @return void
     */
    protected function _handle()
    {
        $subject = $this->_subject();
        $subject->set(['success' => true, 'viewVar' => $this->viewVar()]);

        $this->_trigger('beforePaginate', $subject);

        $controller = $this->_controller();
        $items = $controller->paginate();
        $subject->set(['items' => $items]);

        $this->_trigger('afterPaginate', $subject);

        $controller->set(['success' => $subject->success, $subject->viewVar => $subject->items]);
        $this->_trigger('beforeRender', $subject);
    }

}

For example adding an API layer to your application later in time will be easy because you don’t need to edit all your applications many controllers.

Using Crud, it would be as simple as loading the API listener and everything would be taken care of. All validation, exceptions, success and error responses would work immediately, and with just a few lines of code.

This is because the powerful event system can hook into the request and hijack the rendering easily and effortlessly; something baked controllers do not offer.

Crud’s default actions

Crud has many actions built-in which come with the plugin.

  v: 4.4.0
Versions
latest
stable
4.4.0
4.3.5
4.3.4
4.3.3
4.3.2
4.3.1
4.3.0
4.2.4
4.2.3
4.2.2
4.2.1
4.2.0
4.1.4
4.1.3
4.1.2
4.1.1
v4.0.0
cake3
Downloads
On Read the Docs
Project Home
Builds
Downloads
On GitHub
View
Edit

Free document hosting provided by Read the Docs.