|
|
Want to know more about Packt's Article Network? Interested in contributing your article ideas? Please visit our FAQ for more information. See More BROWSE
All Titles WordPress Web Services SOA BPEL Web Graphics & Video Web Development RAW Portugues, Espanol, Italiano, French PHP/MySQL Oracle Open Source Networking & Telephony Moodle Microsoft & .NET Linux Servers jQuery Joomla! JBoss Java e-Learning e-Commerce Dynamics Drupal CRM Cookbook Content Management Beginner Guides Architecture and Analysis AJAX Future Titles Recently Published Titles |
Working with Simple Associations using CakePHP
There are basically 3 types of relationship that can take place between database tables:
The first two of them are simple as they don't require any additional table to relate the tables in relationship. In this article, we will first see how to define associations in models for one-to-one and one-to-many relations. Then we will look at how to retrieve and delete related data from, and save data into, database tables using model associations for these simple associations. Defining One-To-Many Relationship in ModelsTo see how to define a one-to-many relationship in models, we will think of a situation where we need to store information about some authors and their books and the relation between authors and books is one-to-many. This means an author can have multiple books but a book belongs to only one author (which is rather absurd, as in real life scenario a book can also have multiple authors). We are now going to define associations in models for this one-to-many relation, so that our models recognize their relations and can deal with them accordingly. Time for Action: Defining One-To-Many Relation
CREATE TABLE `authors` ( CREATE TABLE `books` ( <?php <?php <?php <?php What Just Happened?We have created two tables: authors and books for storing author and book information.
A foreign-key named author_id is added to the books table to establish the one-to-many relation between authors and books. Through this foreign-key, an author is related to multiple books, as well as, a book is related to one single author. By Cake convention, the name of a foreign-key should be underscored, singular name of target model, suffixed with _id. Once the database tables are created and relations are established between them, we can define associations in models. In both of the model classes, Author and Book, we defined associations to represent the one-to-many relationship between the corresponding two tables. CakePHP provides two types of association: hasMany and belongsTo to define one-to-many relations in models. These associations are very appropriately named:
In the Author model, an association attribute $hasMany is defined with the value Book to inform the model that every author can be related to many books. We also added a $belongsTo attribute in the Book model and set its value to Author to let the Book model know that every book is related to only one author. After defining the associations, two controllers were created for both of these models with scaffolding to see how the associations are working.
CakePHP Application Development
Retrieving Related Model Data in One-To-Many RelationOnce the associations are in place, we can retrieve related data very easily without any trouble. In fact, we don't need to do anything at all—CakePHP's ORM will automatically fetch all the related model data using association. We will work on the previous code-base to see how the related model data can be retrieved. Time for Action: Retrieving Related Model Data
<?php <?php foreach($authors as $author): ?> <?php <table> What Just Happened?The first line in the index() action of the AuthorsController sets the model attribute $recursive to 1. $this->Author->recursive = 1; This special attribute is an integer that specifies the number of levels we want our model to fetch associated model data in the next find('all') or find('first') operations. In the AuthorsController, we set it to 1 for the Author model. This means the subsequent Author->find('all') operation will return all associated model data that are related directly to the Author model. The result of the function call Author->findAll() is then stored in a variable $authors. The returned result is an array containing all authors and their book information. This array looks like the following: Array Every element of this array contains information about one particular author and his/her related books. Each of these elements has two associated arrays: one is 'an array' containing the author information and the other is 'an array of array' (containing multiple books data as Author to Book association is hasMany) containing information about the books related to that particular author. We can easily traverse through all the elements of this array and print out all the authors and their related books data. We passed $authors to the view file, and in the view file, we used two loops (first loop is to for each author and second loop is for each related book to this particular author) to print out the author and its related book information.
Similarly, in BooksController, Book->recursive is set to 1 before calling the Book->find('all') function. Book->find('all') function also returns a similar array. Every element of this array contains two associated arrays, one contains the book data and the other contains one (not multiple, as Book to Author association is belongsTo) related author data. The returned array looks something like the following: Array The result of Book->find('all') is forwarded to the view. In the view file, we looped through the array and printed out all books' information with their related authors' names. To have a better understanding of how $recursive works, let's assume:
We can now set $recursive to different values based on the amount of data we want back from a Author->find('all') call:
In this way, we can fetch out related data of multiple levels by setting the value of $recursive to our desired level. Always set $recursive = 0, if you don't need to fetch any associated model data. By default, $recursive is set to 1. In the last example, it was not required to explicitly set its value to 1. CakePHP Application Development
Saving Related Model Data in One-To-Many RelationAssociations can also make saving related data pretty easy. We will now create a simple program that can save a book and can relate the book with an author at the time of saving. We will add some code to the previous code-base to put in the save functionality. Time for Action: Saving Related Model Data
<?php <?php echo $form->create('Book');?>What Just Happened?In the add() action of the BooksController, we first checked if there is any form data sent back from the view. When no data is returned from its view, a form is displayed to take user input. We have text inputs inside the form to take book information. As well as, we have a select-list to select a related author. This select-list has options for all the authors, from where one single author can be selected. CakePHP model function generateList() is used to create this select-list. Author->generateList() returns an array with author's id=>name as key=>value pairs like the following: Array From or through a model class, all model classes related to that model are accessible. Like, Author model can be accessed through Book model like Book->Author and vice-versa. This function is very handy for creating HTML select tags. We passed the returned result from the function call Book->Author->generateList() to the view through $authors variable. In the view file FormHelper's input() method is used, $form->input('author_id') – this input() method cleverly creates a select tag with options for every author- where names are used as tag-labels and ids are set as tag-values. The output of $form->input('author_id') is something like the following: <select> When the submit button of the form is clicked, all form data is sent back to the BooksController's add() action. Then the form data is passed to the Book->save() function that stores the book data into the database and automatically relates the newly added book with the selected author (saves the selected author's id in the author_id field of books table). When the save operation is done, the controller redirects to index() action and the newly added book can be seen in the list of books. The prototype of the generateList() function looks like the following: generateList(string $conditions, string $order, int $limit, string $conditions, $order, and $limit parameters are just as we would use in the find() function. By default, the generateList() function takes id and name fields of the model respectively as keys and values of the returned array. We can change this behavior using $keyPath and $valuePath parameters. If we want to get an array of first 10 authors with id and last_name fields of the Author model as key/value pairs and is ordered by the last_name field, we could make use the $order, $limit, $keyPath, and $valuePath parameters like the following: $this->Author->generateList( Adding More than One Association of the Same TypeIn previous examples, the only association that the Author model has is a hasMany association with the Book model. This association was created by the following line of code: var $hasMany = 'Book'; Here, a string is used to define the hasMany association. It is also possible to do the same thing using an associative array like the following: var $hasMany = array( Likewise, for the Book model we can do the following: var $belongsTo = array( This alternative method is handy if we want to add more than one association of the same type or we need to customize some of the relationship characteristics. If we have another model Tutorial and our Author model also has a hasMany association with the Tutorial model, we can use the array approach to define these two associations in the Author model: var $hasMany = array( One-To-One RelationDefining associations for one-to-one relation is very much the same as defining association for a one-to-many relation. Let's look at an example to see how a one-to-one relation can be defined in models. Let's assume, we have a profiles table and the relation between the authors table and the profiles table is one-to-one. To establish this relation, we created a profiles table with a foreign-key author_id.
Now, in both of the model classes, Author and Profile, we have to define associations for this relation. The belongsTo association is always defined in the corresponding model of the table with the foreign-key and hence in the Profile table we have to define a belongsTo association. On the other hand, an author can only have one associated profile—to define the relation from Author model's perspective, we can use a hasOne association. To resemble this relation, in the Author model a $hasOne attribute should be defined: var $hasOne = array( As well as, a $belongsTo attribute should be defined in the Profile model: var $belongsTo = array( In both 'one-to-one' and 'one-to-many' relations, the model that has the foreign-key in its underlying table uses the belongsTo association. The only difference between these two relations is: in the other model, the hasOne association should be used instead of the hasMany. Customizing Association CharacteristicsDefining associations using array has another benefit—we can include some key-value pairs in the associative array to customize the relationship. A customized hasMany association that defines the relation between authors and books may look like the following: var $hasMany = array( Let's see how some of these key/value pairs can be used to manipulate a relation:
SummaryIn this article, we first learnt basics of simple relationships like one-to-one and one-to-many and then saw how to implicate them in models using $hasOne, $hasmany, and $belongsTo model attributes. Then, we saw how these associations make it easy to retrieve or save related model data. We also learnt how to define model relationship attributes as associated arrays to customize association characteristics and override the defaults. CakePHP Application Development
About the AuthorsAhsanul Bari is a web application developer from Dhaka, Bangladesh. After graduating from North South University with a bachelor's degree in Computer Science, he has been involved in developing various web applications for local businesses. At a very early stage of his career, he felt the need for tools and techniques to build structured and maintainable web applications. That is when he found out about CakePHP. It was love at first sight and he decided to use CakePHP for his future projects. He never had to look back, and from then on, he has been heavily using CakePHP for all kinds of projects. Most notably, using CakePHP, he developed an ERP solution for companies involved in urban and land development. Anupom Syam is a web application developer from Dhaka, Bangladesh. He started programming back in 1998 in C when he was a high school kid. In his early university years, he met Java and fell in love immediately. Through the years, he has become proficient in various aspects of Java (ME, SE, and EE). Early in his career, he was engaged mainly in building localized mobile applications. Over time, his interest in web technologies grew and he did not hesitate to jump onto the Web 2.0 bandwagon. Over the last five years, he has been working with different startups and building web/mobile applications. He currently works as a Development Engineer at Trippert, Inc. where he has been involved in developing a travel-based blogging system http://www.trippert.com (which is developed using CakePHP) as the lead back-end programmer. Books from Packt
|
TOP TITLES ![]()
|
| ||||||||