Posts Tagged ‘ PHP ’

CakePHP and in-memory query caching

CakePHP models by default cache in-memory all database queries you make in each request, this reduces the database querying overhead when redundant queries are made, assuming that nothing changed. But sometimes there’s a need to implement complex methods in your models to perform complex and crazy actions with your data, and sometimes when you do that you need to make the same query many times, for example, when you’re checking something inside any loop, and when you do that, if your model is caching queries, you’ll get always the same result, that will bring you for sure an unexpected behavior. So when you do that, you just need to disable query caching by setting the cacheQueries variable to false in your model before the database query you don’t want to cache, and enabling it after, if needed. It’ll make you model to generate a real fetch of data in the server. I believe that some of you are thinking which it can be avoided if you do any kind of data handling in your logic, avoiding the model to do repeated fetches to the database, and you’re right, but each situation is unique, and this need is not very usual. I just want you to be aware about the models query cache existence :)

Simple use of route prefixes within AuthComponent in a CakePHP App

In any regular website you have a restricted area for management, and a public webpage.
When writing a CakePHP app you would usually use the AuthComponent for authentication, and for allowing and denying actions. A boring task of using Auth is that you have to define in every controller that has public actions the allowed actions in that controller, it can be done by overriding the beforeFilter() method or by using any other technique, like looking for any defined variable with the allowed actions names and handle it in the AppController::beforeFilter(), or you can do it automatically! Yes, you can can assume a convention telling that every restricted action has a route prefix. So you won’t need to define any additional information on each controller.
The authorization logic for allowing users to reach a specified action is then set in the AppController::beforeFilter() by playing with the $this->params[‘prefix’] value.

A simple example is shown below:

We enable a single route prefix by editing app/config/core.php

	Configure::write('Routing.prefixes', array('admin'));

Then we edit our app/app_controller.php

class AppController extends Controller {

    public function beforeFilter () {
        if (empty($this->params['prefix'])) {
            $this->Auth->allow($this->action);
        } else {
            $this->layout = 'admin';
        }
    }

}

The example above checks for an non prefixed request (following our own conventions, it’ll be a public action), and if it is non prefixed just allow it, for example:

domain.com/posts/view/123

In other hand, if it is prefixed and there’s not a logged in user, it is not allowed, being denied by default.
So if a not logged user tries to request for:

domain.com/admin/posts/view/123

He is immediately redirected to the AuthComponent logoutRedirect url.

It’s just a very simple tip, i hope it helps someone :-D

Show SQL dump on redirect using CakePHP 1.3

Hi there!

An inconvenient i faced when i moved from CakePHP 1.2 to 1.3 is the fact of the debug SQL dump is now rendered as an element, this can be usefull if you want to customize or display it in any other place than in the bottom of the rendered output. But, in some situations, when you have an action without a view, those kind of actions usually redirect immediately after doing something, it means that the layout is never rendered, and as a consequence, the SQL dump too.

My solution is pretty simple and straight forward, i’ve just overrided the Controller::redirect() method in the AppController to detect if a debug was triggered (if any header was sent, it happens when you output something, in this case it’s sent by a debug() call), and if so, just render the sql_dump element, and stops.

The code is show below:

class AppController extends Controller {

    public function redirect ($url, $status = null, $exit = true) {
        if (headers_sent()) {
            $this->viewPath = 'elements';
            echo $this->render('sql_dump', false);
            if ($exit) {
                $this->_stop();
            }
        }
        parent::redirect($url, $status, $exit);
    }

}