Showing posts with label model. Show all posts
Showing posts with label model. Show all posts

Wednesday, July 13, 2011

Model: User: Display Name

When adding a record that has a relationship of "belongs to" with another table as mentioned previously, CakePHP automatically lists the records of the other table using the display name of that model. By default that display name field is "name". However, if your field doesn't have a "name" field, such as the Users table, you can specify the display name manually in the model.

Edit app/models/user.php and add the following line:
    var $displayField = 'username';
This does not support multiple fields, for example if you wanted to combine first_name and last_name. In order to do this you need to use virtualFields in your model. Virtual fields allow you to access a created field, but you cannot save it.

Edit app/models/user.php and add the following line:
    var $virtualFields = array( 'full_name' => "CONCAT(User.first_name, ' ', User.last_name)");
then change the display field from username to full_name.

Thursday, November 4, 2010

Validate Model: User

Rule 1: Never trust user input
Rule 2: When in doubt, see rule 1

For every model you should create a validate variable which will be used to validate input fields. For our user model we need to verify that username and email are unique on creation.

Since validation can be quite complex, building the validation variable one field at a time can be helpful. For full details on data validation see http://book.cakephp.org/view/1143/Data-Validation

Edit /app/models/user.php and add
    var $validate = array(
        'username' => array(
            'alphanumeric' => array(
                'rule' => '/^[a-z0-9]{3,}$/i',
                'required' => true,
                'message' => 'Username must contain only letters and numbers.'
            ),
            'unique' => array(
                'rule' => 'isUnique',
                'message' => 'This username is already taken.'
            ),
            'minlength' => array(
                'rule' => array('minlength', 5),
                'message' => 'Username must be at least 5 characters.'
            ) 
        )
    );
Upload the file then browse to http://drug-ed.com/users/add and observe how the "Username" field label is bolded and followed by a red asterisk helping to identify the required aspect of that field. Test your validation rule by trying a 2 letter username, or one composed of special characters.

Now that you are sure that field validation is working properly, add the next field. Edit /app/models/user.php and add at the end of the validate array
        ),
        'email' => array(
            'email' => array(
                'rule' => 'email',
                'required' => true,
                'message' => 'You must enter a valid email address.'
            ),
            'unique' => array(
                'rule' => 'isUnique',
                'on' => 'create',
                'message' => 'This email address is already on record.'
            )
        )
    );
Notice the line 'on' => 'create' in the email validation. When editing a user the isUnique rule will fail because the user's email is already in the database! Changing it to only verify when you create an new user will prevent this problem.

Upload the file then browse to http://drug-ed.com/users/add to again verify it works as intended.

Model: App Model

The find() method, as used previously, returns not only the data from the table/model identified, but all related data as well. This is usually a good thing, but typically it returns far too many levels of data than is necessary.

Edit /app/views/users/index.ctp and add the following line to the end of the file then browse to http://drug-ed.com/users/ to see what is returned for just one record:
<?php print_r($user); ?>
It may look something like this:
Array ( [User] => Array ( [id] => 1 [slug] => admin [username] => admin [password] => test [first_name] => test [last_name] => test [email] => naidim@gmail.com [email_verified] => 1 [carrier_id] => 1 [cell_number] => 5205551234 [created] => 2010-11-03 21:12:40 ) [Carrier] => Array ( [id] => 1 [name] => Verizon PCS [extension] => vtext.com ) [Reminder] => Array ( ) )
By default it should contain only what the current view requires, only returning more if the Containable behavior is set.

To limit the find() method for all models, create /app/app_model.php This model overrides the default AppModel and allows you to control the functionality of all models.
<?php
class AppModel extends Model {
    var $recursive = -1;
    var $actsAs = array('Containable');
}
?>
Now browse to http://drug-ed.com/users/ and you should see something more like this:
Array ( [User] => Array ( [id] => 1 [slug] => admin [username] => admin [password] => test [first_name] => test [last_name] => test [email] => naidim@gmail.com [email_verified] => 1 [carrier_id] => 1 [cell_number] => 5205551234 [created] => 2010-11-04 21:12:40 ) ) 
Go back and remove that last line from /app/views/users/index.ctp.

For details on Containable behavior http://book.cakephp.org/view/1323/Containable and using Containable with paginate http://book.cakephp.org/view/1232/Controller-Setup

Don't forget to add var $actsAs = array('Containable'); to the appropriate model (or AppModel) before you try to use contain();

Thanks to Matt Curry

Wednesday, November 3, 2010

Update Model: Drug

As mentioned previously, to coordinate with the reminder model, add the relationship to the drug model. Edit /app/models/drug.php and add
    var $hasMany = array('Reminder');
Save and upload the file.

Update Model: Carrier

As mentioned previously, to coordinate with the user model, add the relationship to the carrier model. Edit /app/models/carrier.php and add
    var $hasMany = array('User');
Upload the file.

Update Model: User

As mentioned previously, to coordinate with the reminder model, add the relationship to the user model. In addition while each carrier can have many users, each user belongs to a carrier so indicate that as follows as well:

Edit /app/models/user.php and add
    var $hasMany = array('Reminder');
    var $belongsTo = array('Carrier');
Upload the file.

Like when a model belongs to another model, if the foreign key is not standard you need to explicitly define it. You can also explicitly define the class name if that isn't the default also.
    var $hasMany=> array(
        'Reminder' => array(
            'className' => 'Reminder',
            'foreignKey' => 'UniqueUserID'
        )
    );

Model: Reminder

Create /app/models/reminder.php
<?php
class Reminder extends AppModel {
    var $name = 'Reminder';
}
?>
Each reminder "belongs to" a user, and each user can "have many" reminders, so there is a one to many relationship between the two tables. To indicate this to Cake, add the following information below the $name variable:
    var $belongsTo = array('User');
In addition, each reminder has a one to many relationship with drugs, so it "belongs to" a drug. Add 'Drug' after 'User' in the above line.

When designing your database, ensure that each model that "belongs to" another model has the appropriate foreign key field. For example since each reminder belongs to a user, that user is identified by the key "user_id" in the reminder table. If you stray from convention (classname_id) you have to define the foreign key explicitly in your model.
    var $belongsTo => array(
        'User' => array(
            'foreignKey' => 'UniqueUserID'
        )
    );
Upload the file.

Model: Carrier

Create /app/models/carrier.php
<?php
class Carrier extends AppModel {
    var $name = 'Carrier';
}
?>
Upload the file.

Model: Drug

Create /app/models/drug.php
<?php
class User extends AppModel {
    var $name = 'Drug';
}
?>
Save and upload the file.

Model: User

Models provide the interface to the database. While the tables they refer to are named plurally, the models are named singularly.

Create /app/models/user.php
<?php
class User extends AppModel {
    var $name = 'User';
}
?>
If the primary key field of your table is not "id" then you need to add the variable $primaryKey, otherwise you can leave it out.
    var $primaryKey = 'unique_id';
If you didn't design your tables around CakePHP (why wouldn't you?) then you can explicitly specify the table name for your model here as well.
    var $useTable = 'table_name';
If you don't want a model to use a table, such as for display purposes only, or when pulling data from an external source, you can set the useTable variable to false.
    var $useTable = false;
Once you do that, you can set the schema for the non-table data with the _schema variable.
    var $_schema = array(
        'last_name' => array('type' => 'strong', 'length' => 50),
        'date_of_birth' => array('type' => 'date')
    );
Upload the file.