You are here: cakephp » loading multiple models into one controller and setting them
Loading multiple models into one controller and setting them
- Written By
- Shadow
- Submitted At
- 2010-03-01 15:24:06
- Num Views
- 885
- Category
- CakePHP
|
I have a question.. Say you have a controller with a function called home. In this controller I need to load and set images, details, titles etc from about 5 different tables, to display randomly on page load. How would I go about it? By Shadow @ 2010-03-01 15:24:06
|
|
Ok let's work with 3 tables as after that you would just duplicate the rest of the code for more. Tables: Book, DVD, Games In your controller create a function called getRandomProducts function getRandomProducts($itemCount = 1){ //gets all the models which you are going to need to use to pull info from the database $this->loadModel('Book'); $this->loadModel('Dvd'); $this->loadModel('Game'); //this fetches all the fields in the tables Book,Dvd,Game and sets to $books,$dvds,$games $books = $this->Book->findAll(); $dvds = $this->Dvd->findAll(); $games = $this->Game->findAll(); //loops through the books rows and pulls the id,title and sets the type to books for($i = 0; $i < sizeof($books); $i++){ $newRow['id'] = $books[$i]['Book']['id']; $newRow['title'] = $books[$i]['Book']['title']; $newRow['type'] = 'books'; $allRows[] = $newRow; } //loops through the dvd rows and pulls the id,title and sets the type to dvd for($i = 0; $i < sizeof($dvds); $i++){ $newRow['id'] = $dvds[$i]['Dvd']['id']; $newRow['title'] = $dvds[$i]['Dvd']['title']; $newRow['type'] = 'dvds'; $allRows[] = $newRow; } //loops through the games rows and pulls the id, title and sets the type to games for($i = 0; $i < sizeof($games); $i++){ $newRow['id'] = $games[$i]['Game']['id']; $newRow['title'] = $games[$i]['Game']['title']; $newRow['type'] = 'games'; $allRows[] = $newRow; } //now we have a variable called $allRows which has all products in book,dvd and games with their id and type //you can print_r($allRows) here to see what the structure looks like //we now need to get the amount of products we have so that we can give that number to the php //random function to know we want a value between 0 and the number of products seeing that //our $allRows array will start with 0 and end at the number of products we currently have. //our minimum value is zero because our allRows array starts at 0 $minValue = 0; //our max value is the count of $allRows - 1. This is because the function count() returns the number //of elements in the array $allRows which is 1 to much because an array starts with 0 and not like //normal counting which starts at 1, thats why we subtract the 1 $maxValue = count($allRows) - 1; $randomItems = array(); for($i = 0; $i < $itemCount;$i++){ //the function rand will return a random number between or equal to the minValue and maxValue given //we then set $randomIndex as that is our random number in the array $allRows $randomIndex = rand($minValue,$maxValue); $randomItem = $allRows[$randomIndex]; if(!in_array($randomItem,$randomItems)){ //all thats needed now is to add the element if it has not been added already $randomItems[] = $randomItem; }else{ $i--; } } return $randomItems; } Now you can call this function wherever you want and it will return a random item. So in your function home you can call it like this function home(){ //runs the function getRandomProduct and send you want 6 items returned, gets the result in $randomProducts $randomProducts = $this->getRandomProducts(6); //print it out to see it works, you can remove this echo "<pre>RANDOM PRODUCTS HERE:";print_r($randomProducts);echo "</pre>"; } By PHPin24 @ 2010-03-03 09:58:57
|
|
If all your colums were the same in the different tables you could alternatively just add a column called 'type' which will make your code a LOT less. So lets say you had a table called products function getRandomProduct(){ //gets the model which you are going to need to use to pull info from the database $this->loadModel('Product'); //this fetches all the fields in the table Product $products = $this->Product->findAll(); //our minimum value is zero because our products array starts at 0 $minValue = 0; //our max value is the count of $products - 1. This is because the function count() returns the number //of elements in the array $products which is 1 to much because an array starts with 0 and not like //normal counting which starts at 1, thats why we subtract the 1 $maxValue = count($products) - 1; //the function rand will return a random number between or equal to the minValue and maxValue given //we then set $randomIndex as that is our random number in the array $products $randomIndex = rand($minValue,$maxValue); //all thats needed now is to return the element $randomItem = $products[$randomIndex]; return $randomItem; } By PHPin24 @ 2010-03-03 10:26:35
|
|
Dude. That is amazing. It works perfectly. Will definitely put all my items in one table next time! Thanks for the GREAT reply! By Shadow @ 2010-03-03 11:31:59
|
|
Just something I picked up reading this, rather use: $this->Product->find('all'); instead of: $this->Product->findAll(); as the findAll() method is going to be deprecated in future releases of cake. Also, while I'm here, if you'd like to speed up your for loops, use: for ($x = 0, $s = sizeof($productsArray); $x < $s; ++$x) { // Some code here } because you don't want to calculate the size of the array each time you iterate through the loop. In larger array's, this uses quite a bit more processing power and is best avoided altogether. Lastly, if you don't want to keep writing all this: echo "<pre>RANDOM PRODUCTS HERE:";print_r($randomProducts);echo "</pre>"; You could just use Cake's handy debug() method, like so, which does the same thing: debug($randomProducts); Just make sure that the debug level is greater than 0 in your /app/config/core.php file ;) Just my 2 cents :) By snivels @ 2010-03-06 01:26:17
|
|
Thanks for the update. It's great feedback and always good to know future developments in CakePHP ex: the findAll function being deprecated in CakePHP 1.3 Just to clarify speeding up the loops: As snivels suggested. Rather use: $sizeOfProducts = sizeof($productsArray); for ($x = 0, $s = $sizeOfProducts; $x < $s; ++$x){ // Some code here } Just to confirm the debug function is quite useful if you have debugging enabled. By PHPin24 @ 2010-03-09 16:16:47
|
