CakePHP 2.x CookBook Chinese Version Chapter 7 Model - Saving Data_PHP Tutorial
WBOY
Release: 2016-07-14 10:08:40
Original
922 people have browsed it
save data
CakePHP will take a snapshot of the saved model data. The data to be saved is passed to the save() method of the model using the following basic format:
1 Array
2 (
3 [ModelName] => Array
4 (
5 [fieldname1] => 'value'
6 [fieldname2] => 'value'
7 )
8 )
Most of the time you don't need to worry about this format: CakePHP's FormHelper and the model's find method package all data in this format. If using other helpers, the data is also conveniently available in the form $this->request->data.
Here is an example of a controller action that uses the CakePHP model to store data into a database table:
1 public function edit($id) {
2 // Is there any form data being POST?
3 if ($this->request->is('post')) {
4 // If the form data can pass the verification and be saved...
5 if ($this->Recipe->save($this->request->data)) {
6 // Set session jump information and jump
7 $this->Session->setFlash('Recipe Saved!');
8 $this->redirect('/recipes');
9 }
10 }
11
12 // If there is no form data, find the edited recipe and assign it to the view.
When the save method is called, the data passed to it in the first parameter is verified by the CakePHP verification mechanism (see the Data Verification section for more information). If for some reason the data is not saved, check to see if it does not comply with certain validation rules. You can debug this situation by outputting Model::$validationErrors.
1 if ($this->Recipe->save($this->request->data)) {
2 // Processing logic after "save" is successful
3}
4 debug($this->Recipe->validationErrors);
Some other useful model methods related to saving:
Model::set($one, $two = null)
Model::set() can be used to place one or more columns of data into the model's data array. Useful when using a model with the ActiveRecord attribute provided by Model:
1 $this->Post->read(null, 1);
2 $this->Post->set('title', 'New title for the article');
3 $this->Post->save();
This example shows how to update and save a single column using ActiveRecord's set() method. You can also use set() to assign new values to multiple columns:
1 $this->Post->read(null, 1);
2 $this->Post->set(array(
3 'title' => 'New title',
4 'published' => false
5 ));
6 $this->Post->save();
The above example will update title and published columns and save them to the database.
This method saves data in array format. The second parameter allows to skip validation and the third parameter allows to provide a list of columns of the model to be saved. For added security, you can use $fieldList to limit the columns to be saved.
Annotations
If $fieldList is not provided, a malicious user can add additional columns to the form data (when you are not using SecurityComponent), and in this way change columns that cannot be changed.
The $params array can have the following options as its keys:
validate is set to true/false to allow/disable verification.
fieldList allows an array of columns to be saved.
callbacks Set to false to disable callbacks. Using 'before' or 'after' will only allow the specified callback.
More information about model callbacks can be found here
Tips
If you don't want the update column to be updated when saving some data, add 'updated' => false in the $data array.
Once saved, the object's ID can be obtained using the model object's $id property - which can be useful when creating new objects.
1 $this->Ingredient->save($newData);
2 $newIngredientId = $this->Ingredient->id;
Creation or update is controlled through the id column of the model. If $Model->id is set, records with this primary key will be updated. Otherwise, a new record is created:
1 // Create new record: id is not set or set to null
2 $this->Recipe->create();
3 $this->Recipe->save($this->request->data);
4
5 //Update record: id is set to a numeric value
6 $this->Recipe->id = 2;
7 $this->Recipe->save($this->request->data);
Tips
Don’t forget to call create() when calling save in a loop.
If you want to update a value rather than create a new record, you must ensure that the primary key column is passed to the data array:
This method resets the model's state to save new information. It doesn't actually create a new record in the database, but clears the preset Model::$id and sets a default value in Model::$data based on the database column default.
If the $data parameter is passed (using the array format described above), the model instance will be prepared to save this data (using $this->data).
If false is passed to this method instead of an array, the model will not actually initialize the columns according to the model structure that has not been set before, but will only reset the columns that have been set, and leave the unset columns. This is done to avoid updating the value of a column that is already set in the database.
Tips
If you want to insert a new row instead of updating an existing row, you must first call create(). This avoids conflicts with saves that have been called in callbacks or elsewhere.
Used to save the value of a single column. Before using saveField(), set the model ID ($this->ModelName->id = $id). When using this method, $fieldName only needs to contain the column name, not the model name and column.
For example, to update the title of a blog, you can call saveField in the controller as follows:
1 $this->Post->saveField('title', 'A New Title for a New Day');
Warning
You cannot stop updating columns when updating using this method, you need to use the save() method.
Update one or more records in one call. The records to be updated are identified by the $conditions array, and the columns and values specified by the $fields parameter are updated.
For example, to approve all bakers who have been members for more than one year, call the following update statement:
The $fields array accepts SQL expressions. Literals are quoted manually using Sanitize::escape().
Annotations
Even if the edit column present in the column is updated, it will not be automatically updated via the ORM. You must manually add it to the array you want to update.
For example, to close all tickets belonging to a specified customer:
1 $this->Ticket->updateAll(
2 array('Ticket.status' => "'closed'"),
3 array('Ticket.customer_id' => 453)
4 );
By default, updateAll() will automatically connect belongsTo associations of databases that support join. This connection can be prevented by temporarily binding the association.
This method is used to save multiple rows of the same model at the same time. Can have the following options:
validate: Set to false to disable validation, set to true to validate each record before saving, set to 'first' (this is the default) to check all records before any one is saved.
atomic: If true (default), all records will be saved in a single instruction. If the database/table does not support a single instruction, it needs to be set to false.
fieldList: Same as the $fieldList parameter of the Model::save() method.
deep: (since version 2.1) If set to true, associated data is also saved, see saveAssociated.
To save multiple records for a single model, $data needs to be a numerically indexed record array:
1 $data = array(
2 array('title' => 'title 1'),
3 array('title' => 'title 2'),
4 );
Annotations
We pass the numeric index instead of the Article key that $data would normally contain. When saving multiple records of the same model, the record array needs to be indexed using numbers rather than the keys of the model.
This method is used to save multiple model associations at once. Can have the following options:
validate: Set to false to disable validation, set to true to validate each record before saving, set to 'first' (this is the default) to check all records before any one is saved.
atomic: If true (default), all records will be saved in a single instruction. If the database/table does not support a single instruction, it needs to be set to false.
fieldList: Same as the $fieldList parameter of the Model::save() method.
deep: (since version 2.1) If set to true, associated data is also saved, see saveAssociated.
In order to save records while also saving records that have hasOne or belongsTo relationships with them, the data array looks like the following:
In order to save records while also saving records that have hasMany associated with them, the data array looks like the following:
1 $data = array(
2 'Article' => array('title' => 'My first article'),
3 'Comment' => array(
4 array('body' => 'Comment 1', 'user_id' => 1),
5 array('body' => 'Comment 2', 'user_id' => 12),
6 array('body' => 'Comment 3', 'user_id' => 40),
7 ),
8 );
In order to save records while also saving records that have a hasMany associated with them that are more than two levels deep, the data array looks like this:
If the save is successful, the foreign key of the main model will be stored in the id column of the related model, such as $this->RelatedModel->id.
Warning
Be careful when calling the saveAssociated method with the atomic option set to false. It returns an array, not a logical value.
Changed in version 2.1: You can now save data from deep associations (set with $options['deep'] = true).
In order to save records while also saving related records with hasMany association and deeply associated Comment belongsTo User data, the data array looks like the following: :
1 $data = array(
2 'Article' => array('title' => 'My first article'),
3 'Comment' => array(
4 array('body' => 'Comment 1', 'user_id' => 1),
5 array('body' => 'Save a new user as well', 'User' => array('first' => 'mad', 'last' => 'coder')) ,
The saveAll function is just a wrapper around the savaMany and saveAssociated methods. It examines the data and decides which type of data saving to perform. It looks at the data and decides what type of save to perform. If the data is a numerically indexed array, saveMany is called, otherwise saveAssociated is called.
This function has the same options as the previous two functions and is backwards compatible. It is recommended to use saveMany or saveAssociated according to the actual situation.
Save related model data (hasOne, hasMany, belongsTo)
When working with associated models, you must realize that the saving of model data is always done by the corresponding CakePHP model. If you save a new Post and its associated Comment, you need to use both the Post and Comment models during the save operation.
If there is no associated model record in the system (for example, if you want to save a new User and save the related Profile record at the same time), you need to save the main model or parent model first.
To understand how this works, imagine we have an action in a controller that handles saving the new User and associated Profile. The following example action assumes that sufficient data has been POSTed (using FormHelper) to create a single User and a single Profile:
As a rule, when it comes to associations with hasOne, hasMany, belongsTo, it's all about the key. The basic idea is to get the key from one model and put it into a foreign key column in another model. Sometimes this involves using the $id attribute of the saved model class, but other times it just involves the ID obtained from the hidden input of the form that POSTs to the controller action.
As a supplement to the above basic methods, CakePHP also provides a very useful method saveAssociated(), which allows you to checksum save multiple models in a short way. In addition, saveAssociated() also provides transaction support to ensure the integrity of the data in the database (for example, if one model fails to save, the other model will not be saved).
Annotations
For transactions to work properly in MySQL, the table must use the InnoDB engine. Remember, MyISAM tables do not support transactions.
Let’s see how to use saveAssociated() to save the Company and Account models at the same time.
First, you need to create forms for both Company and Account (assuming Company hasMany Account):
Look at how to name form columns for the Acount model. If Company is the main model, saveAssociated() expects the associated model (Account) data to be put into the array in the specified format. And has Account.0.fieldName which we need.
Annotations
The column naming above is required for hasMany relationships. If the association is hasOne, you have to use ModelName.fieldName for the associated model.
Now, you can create the add() action in CompaniesController:
1 public function add() {
2 if (!empty($this->request->data)) {
3 // Use the following methods to avoid verification errors:
That’s all the steps. Now the Company and Account models will be verified and saved at the same time. By default, saveAssociated will check all values passed in and then attempt to perform each save.
Save data via hasMany
Let’s take a look at how the data of the two models existing in the join table is saved. As shown in the hasMany Through (Joining Models) section, the join table is associated with each model using a hasMany type of relationship. Our example included the director of Cake School asking us to write a program that would allow it to record the number of days and grade a student had attended in a certain class. Here is the sample code:
1 // Controller/CourseMembershipController.php
2 class CourseMembershipsController extends AppController {
Cake will happily save many at once using a single saveAssociated call with this data structure, and assign the Student and Course foreign keys to CouseMembership. If we run the index action on the CourseMembershipsController, from find('all' ) is as follows:
1 Array
2 (
3 [0] => Array
4 (
5 [CourseMembership] => Array
6 (
7 [id] => 1
8 [student_id] => 1
9 [course_id] => 1
10 [days_attended] => 5
11 [grade] => A
12 )
13
14 [Student] => Array
15 (
16 [id] => 1
17 [first_name] => Joe
18 [last_name] => Bloggs
19 )
20
21 [Course] => Array
22 (
23 [id] => 1
24 [name] => Cake
25 )
26 )
27 )
Of course, there are many ways to work with connected models. The version above assumes you want to save everything immediately. There are also cases where you want to create Student and Course independently and later specify their association with CourseMembership. So you might have a form that allows selection of existing students and courses using a list or ID and two CourseMembership meta columns, for example:
Cake uses saveAssociated to push the Student id and Course id into CourseMembership.
Save related model data (HABTM)
Saving related models through hasOne, belongsTo, and hasMany is very simple: just fill in the ID of the related model into the foreign key column. After filling it out, just call the save() method on the model and everything will be connected correctly. Here is an example of the format of the data array to be passed to the save() method of the Tag model:
1 Array
2 (
3 [Recipe] => Array
4 (
5 [id] => 42
6 )
7 [Tag] => Array
8 (
9 [name] => Italian
10 )
11 )
You can also use this format in saveAll() to save multiple records and models associated with them with HABTM. The format is as follows:
1 Array
2 (
3 [0] => Array
4 (
5 [Recipe] => Array
6 (
7 [id] => 42
8 )
9 [Tag] => Array
10 (
11 [name] => Italian
12 )
13 )
14 [1] => Array
15 (
16 [Recipe] => Array
17 (
18 [id] => 42
19 )
20 [Tag] => Array
21 (
22 [name] => Pasta
23 )
24 )
25 [2] => Array
26 (
27 [Recipe] => Array
28 (
29 [id] => 51
30 )
31 [Tag] => Array
32 (
33 [name] => Mexican
34 )
35 )
36 [3] => Array
37 (
38 [Recipe] => Array
39 (
40 [id] => 17
41 )
42 [Tag] => Array
43 (
44 [name] => American (new)
45 )
46 )
47 )
将上面的数组传递给 saveAll() 将创建所包含的 tag ,每个都与它们各自的 recipe 关联。
Using the above code, a drop-down list (select) with multiple selections will be created, allowing multiple selections to be automatically saved to the Recipe that has been added or saved to the database.
What to do when HABTM gets complicated?
By default, when Cake saves a HABTM relationship, it will first delete all rows in the join table. For example, there is a Club with 10 Children associations. Update Club with 2 children. Club will only have 2 Children instead of 12.
Be aware that if you want to add more columns (build time or metadata) to a join table with HABTM it is possible, it is important to understand that you have a simple option.
The HasAndBelongsToMany association between two models is actually the abbreviation of three model relationships that have both hasMany and belongsTo associations.
Consider the following example:
Child hasAndBelongsToMany Club
Another way is to add a Membership model:
Child hasMany Membership
Membership belongsTo Child, Club
Club hasMany Membership.
These two examples are almost identical. They use the same named amount column in the database and the same amount in the model. The most important difference is that the "join" table is named differently and its behavior is more predictable.
Tips
When the join table contains extension columns other than foreign keys, you can prevent the value of the extension column from being lost by setting the 'unique' of the array to "'keepExisting'". Similarly, it can be considered that by setting ‘unique’ => true, the data of the extended column will not be lost during the save operation. See HABTM association arrays.
However, in more cases, it is simpler to build a model for the join table and set up the hasMany, belongsTo associations as in the example above, instead of using the HABTM association.
Data sheet
Although CakePHP can have non-database-driven data sources, most of the time, it is database-driven. CakePHP is designed to work with MySQL, MSSQL, Oracle, PostgreSQL and other databases. You can create tables in the database system you normally use. When creating a model class, the model will automatically be mapped to the established table. Table names are converted to plural lowercase, and words in multi-word table names are separated by underscores. For example, a model named Ingredient has a table named ingredients. The model named EventRegistration corresponds to a table named event_registrations. CakePHP will examine the table to determine the data type of each column and use this information to automate various features, such as form fields that are output in views. Column names are converted to lowercase and separated by underscores.
Use created and modified columns
By defining created and modified columns as datetime columns in the database table, CakePHP can identify these fields and automatically fill them in with the time the record was created in the database and the time it was saved (unless the data being saved already contains these domain value).
When the record is initially added, the created and modified columns will be set to the current date and time. When an existing record is saved, the modified column will be updated to the current date and time.
If $this->data contains updated, created, modified data (such as Model::read or Model::set) before Model::save(), then these values will be changed from $this-> data and is not updated automatically. Or use methods such as unset($this->data['Model']['modified']). It's always possible to override the Model::save() method to do this:
1 class AppModel extends Model {
2
3 public function save($data = null, $validate = true, $fieldList = array()) {
4 // Clear the modified field value before each save operation:
5 $this->set($data);
6 if (isset($this->data[$this->alias]['modified'])) {
http://www.bkjia.com/PHPjc/477776.htmlwww.bkjia.comtruehttp: //www.bkjia.com/PHPjc/477776.htmlTechArticleSaving data CakePHP will make a snapshot for saving model data. The data to be saved is passed to the model's save() method using the following basic format: 1 Array 2 ( 3 [ModelName] = Array 4 ( 5...
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn