CakePHP Models and requestAction

Sunday October 04th 2009, 3:26 pm
Filed under: CakePHP, PHP

This may be kind of a “no duh” for some Cake veterans, but it was new to me, so I’ll share…

When it comes to accessing a different Model from a given Controller I had always wondered which was the better practice – include the other Model in the $uses array or using $this->requestAction() to get data from the other Model’s Controller.

For example, let’s say in the classic blog example you are in the PostsController and need to access some data from the AuthorsController. (Probably a bad example because in this case they would probably be joined by an Association, but pretend for a minute that they are not.)

I had always gone with this method – let the AuthorsController handle the Author data:

<?php
class PostsController extends AppController {
     var $name = 'Posts';
 
     function someaction($pid = null) {
 
          $post = $this->Post->findById($pid);
          $authname = $this->requestAction('/authors/getname/' 
                              . $post['Post']['author_id']);
     }
}
?>

And again, that’s a very simple example, you would obviously have an association here…

The alternative would be to add the Authors Model in the PostsController’s $uses array:

class PostsController extends AppController {
     var $name = 'Posts';
     var $uses = array('Post','Author');
 
     function someaction($pid = null) {
 
          $post = $this->Post->findById($pid);
          $author = $this->Author->findById($post['Post']['author_id']);
     }
}

The requestAction() method is probably a cleaner choice for occasional use, but I had a project where an Object could have 20 different associations. What I wanted to do though was let the user choose which “modules” to use. So those 20 different assocations could vary – I didn’t want to hard code them in the Models.

So the user chooses their modules and they are stored in a table. That table is then read and I was executing a loop through each of them and doing a requestAction for each of them to get the data from their respective Controllers. But the page was taking 20+ seconds to load. Looking at Cake’s debug output I noticed that for each of those requestAction’s, Cake was completely rebuilding the session data! (I store sessions in the DB)

The point? If you need to access data from multiple Controllers and can’t/don’t want to set up the appropriate associations for all of them, add them to the $uses array and turn on Model caching.

The Cake documentation clearly states that requestAction can lead to poor performance, but I guess I needed to see it for myself.



Dynamic Database Connection with CakePHP

Tuesday July 07th 2009, 10:34 am
Filed under: CakePHP





Recently I was working on a project where I had a central Cake application for a group of clients and each client had their own database.

I wanted to have all users sign into a central user’s table associated with the application, but then for the bulk of the controllers in the app have the database config change based on a field in the user record.

So if Bob Smith from Company A signs in to our app, he needs to use database configuration ‘company_a’.

Since we are using Cake’s built in Auth component, we always have access to the user record in the Session from the controller. But for the life of me, I could not figure out how to get at the Session data from the Model!

I saw several comments in my search that said to just abandon the Cake MVC model and get what I needed from $_SESSION. I had no qualms about doing that, but $_SESSION had no data. I believe this is because Cake overrides PHP’s default session handlers so session data stored by Cake is not going to end up in $_SESSION. Feel free to comment if I am wrong about that.

So I had the data I needed in the controller, but at that point the model has already been instantiated.

But it became a timing issue — ‘mydatabase’ had to be a valid database connection before the controller is even instantiated.

So to fix, a ‘dummy’ database was needed to make the initial connection, then we can make our adjustments in the controller.

function beforeFilter() {
     $config = array(
          'login'    =&gt; 'myusername',
          'password' =&gt; 'mypassword',
          'database' =&gt; $this-&gt;Auth-&gt;user('company_name')
     );
 
     $db =&amp; ConnectionManager::getDataSource("mydatabase");
     $db-&gt;disconnect();
     $db-&gt;setConfig($config);
     $db-&gt;connect();
}


Drag and Drop with jQuery and CakePHP

Tuesday July 07th 2009, 10:32 am
Filed under: CakePHP

Recently I had a need for a data report with shopping cart-like behavior — let the user paginate through a list of items, drag items of interest to a “basket” and then take action on all items in the basket.

To do this, I used the “draggable” and “droppable” functionality in jQuery UI. jQuery makes drag and drop (and everything else) ridiculously easy.

The only trick here was managing the “basket” contents with CakePHP.

My data was laid out in a table, so I took the item name and wrapped it in a div with a ‘draggable’ class like this:

<div class="draggable"><?php echo $item['Item']['name']; ?></div>

Then at the top of the page, I created my “basket” — just a stylized div with a “droppable” class or id, like so:

<div id="basket" class="droppable">Drag items of interest here.</div>

Then in the document ready function, just initialize the drag and drop:

$('.draggable').draggable({ revert: 'valid'; });
$('#droppable').droppable({
     accept: '.draggable',
     hoverClass: 'draggable-active',
     drop: function(event, ui) { doSomeFunction(ui.draggable); }
});

 






Copyright © Matthew Anderton, All Rights Reserved
Wordpress Themes (Naples News)