Tag archives for model

CakePHP: implementing custom validation objects

Today I would like to share with you a really simple problem about model validation.

What to do if you need to share some custom validation logic between multiple models?

Continue reading »

Posted in CakePHP | Leave a comment

BackboneJS Declarative Events

Today I merged into my BackboneKIT project a piece of code from backbone.declarative GitHub page to implement declarative events into Views. Continue reading »

Posted in BackboneJS | Leave a comment

Learning CakePHP 2.1
Controller/Model/Datasource

Today I wrote a simple didactical application to send mail from a form: just a test case to play with some CakePHP components:

  • Forms
  • CakeEmail class
  • Model’s Validation
  • Datasource

In this article I will cover some development steps starting from the controller ending on datasource.

Sending mail via CakeEmail will be cover in a second article.

What I want is…

  1. A form with some fields: from, subject, message box
  2. A simple controller logic to handle the form by using a CakePHP Model
  3. A simple validation logic using Model’s $validate property
  4. A datasources to implement the Model’s save() action by sending email

The Form Controller:

The FormController is very easy. It’s job is to:

  1. display a form
  2. handle a post response saving it with a Model
  3. display a thank-you page

At the beginning, before to talk about the datasource, we build a basic Form Model configured to do not use the database:

// App/Model/Form.php
class Form extends AppModel {
    public $name = 'Form';
    public $useTable = false;
}

So our controller would be something like this:

// App/Controller/FormController.php
class FormController extends AppController {

    public $name = 'Form';

    public function index() {}

    public function thankyou() {}

}

Methods index() and* thankyou()* are now empty…  We will implement the index() late in this article but the thankyou() method only exists to display a view with a text message to confirm that the message was sent!

The Form View:

// App/View/Form/index.ctp
echo $this->Html->tag( 'h2', 'The Form' );

echo $this->Form->create();
echo $this->Form->input( 'email' );
echo $this->Form->input( 'subject' );
echo $this->Form->input( 'message' );
echo $this->Form->end('Send Message');

By using FormHelper building forms becomes a silly task! We do not need any HTML anymore!

FormHelper::input() is a very nice method that write a wrapper, a label, the input and even the error messages produced by a validation logic.

NOTICE: FormHelper isn’t able to recognise field’s type by now: it treats all fields like standard text inputs… but we want message field to display as a textarea!

Just wait some minutes… When we will set up our Datasource we will describe fields properties so FormHelper will be notified about each field type.

The Controller: build out Post logic

Now we can step into the FormController::index() method and implement some logic to handle post data sent by the View::form the form using Form Model to perform a save action.

  1. check if there is any post request using CakeRequest object
  2. save post data with our Form Model
  3. if success redirect the client to a thank page
// App/Controller/FormController.php -> index()
if ( $this->request->is('post') ) {

    if ( $this->Form->save($this->request->data) ) {

        $this->redirect(array(
            'controller'    => 'Form',
            'action'        => 'thanks'
        ));

    }

}

NOTICE: We don’t know how Form Model treat post data. We don’t care about it in Controller level: we will cover this problem ad Model and Datasources level. This way you can split application logic into several layers focusing out attention at one layer at time. Nice!

NOTICE1: At this time form submitting does not work! It throw a Datasource Missing Error because our model is linked with no datasources! It does not know how to save data! We will fix this problem by creating a custom Datasources for this model.

The Model: Validation!

It’s time to expand our model’s code to implement some validation logic.

With CakePHP is easy to setup some validation rules for the model:

// App/Model/Form.php (inside the Form class)
public $validate = array(
    'subject' => 'notEmpty',
    'email' => 'email'
);

There is an entire chapter on CakeBook about Model’s validation rules… It is a easy-to-powerfull system to ensure our data is ok before send it to the save() method!

Now if we send an empty form we obtain some alert messages:

NOTICE: by now a validated form still throw a Datasource Missing Error… but we are next to build the Datasources and solve this problem!

The Datasource!

It’s time to teach our App how to save a validated form: we want form data be sent via mail!

1. Configure our database:
Datasources are database access layers. CakePHP provide a ready to use datasources for mysql and you configure it in database.php config file… so it’s easy to understand how to configure our custom datasource:

// App/Config/database.php
public $form = array(
    'datasource' => 'FormSource'
);

This is a custom configuration object intended to be used by a Model (next paragraph). The key “datasource” define the class to use with. Other keys are configurations passed to the constructor of this class.

FormSource is the name of our custom Datasource. You are next to learn aout it’s creation!

2. Use it in our FormModel:
Now we can remove $useTable property form the model and setup a $useDbConfig one:

public $useDbConfig = 'form';

With this rule all read/write actions of Form Model will be handled by our custom FormSource Datasource.

3. Start to create the datasource!

FormModel Datasource is a simple PHP class who contains properties and business logic on how access data.

// App/Model/Datasource/FormSource.php
class FormSource extends DataSource {
    protected $_schema = array(
        'forms' => array(
            'email' => array( 'type'=>'string' ),
            'subject' => array( 'type'=>'string' ),
            'message' => array( 'type'=>'text' )
        )
    );

    public function listSources() {
        return array('forms');
    }

    public function describe( $model ) {
        return $this->_schema['forms'];
    }
}

Because of a CakePHP Model is intended to relay to a tabular data our Datasource needs to expose a $_schema property that teach CakePHP what kind of data the source is able to handle. This is a simple fields list handled by our class.

Each field contain details about it’s type, dimension and other informations just like a table field property set.

In this simple example we define the “message” field to be a “text” field so FormHelper is able to render it as a textarea automagically. Other fields are defined as string so they are rendered as simple text inputs.

NOTICE: only detailed fields will be available to the Datasource actions!

NOTICE1: our fields are wrapped into a “forms” array. “forms” will act as a virtual table name so Models who uses this datasource needs to sets up their $useTable property to prevent errors:

// App/Model/YourModel.php
$useTable = 'forms';

NOTICE2: Our Form Model does not need this configuration because it’s name “Form” and it’s related table name “forms” follow CakePHP naming conventions!

Now if we reload our form page we will obtain a textarea for the message field:

DataSource Actions

Each DataSource needs to define how to handle data in one or more data access actions:

  • read
  • create
  • update
  • delete

In this article we create a very basic create() action. This action will only return a “true” value acting as all logic success. In the next article we will implement this logic for email sending!

// App/Model/Datasource/FormSource.php
public function create( $model, $fields = array(), $values = array() ) { return true; }

This way a validated form will always be saved by the model… Now let’s create the thank you page!

Thank You Page!

When a validated form is successfully saved controller‘s logic redirect to a thankyou() action. This is an empty action… it only needs a view to be displayed!

// App/View/Form/thankyou.ctp
echo $this->Html->tag( 'h2', 'Message was sent!' );
echo $this->Html->tag( 'p', 'We really thank you for sending us a feedback!' );
echo $this->Html->link( 'Send another message &raquo', array( 'controller'=>'form' ), array( 'escape'=>false ));

NOTICE: Using the HtmlHelper to output simple tag it can seem a waste of resources… but it is cleaner than closing and reopening php brackets and it can easy handle localized strings with the *__()* function!

Bibliography:

Fully Functional Example:

You can download a fully functional example from my GitHub repo:
https://github.com/thepeg/LearningCakePHP

Look at the “form_mail_01″ example.

Continue Reading!

Sending mail via CakeEmail is the continuation of this article.
In that post we use CakeEmail class to implement our FormSource::create() method with mail sending ability!

Posted in CakePHP | 4 Comments

Swedish Greys - a WordPress theme from Nordic Themepark.