4
votes

My app starts on the Pages controlleR; first thing the app needs is to set a config value -from url- that i want to use on the whole app, for example localhost/laborbase/client1 i need to keep 'client1' as a constant.

So in AppController, beforefilter, i assign a constant (tried with Configure:: but same problem: value gets lost for other controllers.

AppController

public function beforeFilter() {
    $clienturl = explode('/', $_SERVER['REQUEST_URI']);
     if (sizeOf($clienturl) == 3) {
        $this->__fetchSettings($clienturl[2]);
    }

public function __fetchSettings($value) {
    debug('from app'.$value);
    //Configure::write('CLIENT_URL', $value);
    define("CLIENT_URL", $value);
    debug('after assign:'.CLIENT_URL); // THIS SHOWS FINE
}

PagesControler:

public function beforeFilter() {
    parent::beforeFilter();
    $this->Auth->allow('home', 'homedemo');
}

UsersController:

public function beforeFilter() {
    parent::beforeFilter();
    $this->Auth->allow('clientLogin', 'add');
}

and display the value for testing when a pages action is called (Pages/display

    public function display() {
        debug(Configure::read('CLIENT_URL')); // IT SHOWS FINE HERE
        ...

From UsersController, i can't access the value: constant comes undefined

public function clientLogin($id = null) {
    $this->autoRender = false;
    $this->RequestHandler->setContent('json', 'application/json');
    ob_end_clean();
    ///debug(Configure::read('CLIENT_URL'));
    echo json_encode(CLIENT_URL);
}

And is is not available to other controllers. Tried Configuration:: and same thing.

I need to be able to access the config value from anywhere in my app.

Can you help?

3
What is the reasoning of manually authorizing users in the PagesController? How about if they access another controller first... how are they checked in? I think you should rethink everything and control your application from AppController.AKKAweb
Thanks @AKKA-Web; I only auth there to see if the the problem with the config value has something to do with lacking a login. My app starts o Pages controller because from home page i need to retrieve db info particular to that url, example localhost/laborbase/client1, or localhost/laborbase/client2. I don't really need to login just yet, just retrieve some db info based on url. Please see edit.Carlos Garcia

3 Answers

3
votes

You basically want to take the action from the first request, and store it in a constant. You can do that, sure - but constants only last during the current request, so you'll need to use a session to store the value for the next request:

You can share class properties from the AppController to all of your other controllers, because they all extend the AppController, or you can use a constant like you are currently. I'll use a class property for this example.

You need to set the property up in your AppController, and use the Session component:

var $components = array('Session');
public $clienturl = null;

Then your AppController beforeFilter:

function beforeFilter() {
    // use if(!defined('CLIENT_URL')) for constants
    if(!$this->Session->read('clienturl')) { 
        // the first action is the value you want to save e.g. client1
        $this->Session->write('clienturl', $this->action); // save to session
    }
    // set the class property
    $this->clienturl = $this->Session->read('clienturl');
    // for constants: define('CLIENT_URL', $this->Session->read('clienturl'));        
}

This process is basically saying "if the session variable doesn't exist, create it from the current action. Then, write that variable to a class property/constant".

And as you are currently doing, you'll need to invoke the AppController's (parent) beforeFilter in each controller. Users controller example:

public function beforeFilter() {
    parent::beforeFilter();
    // you can now access:
    // class property: $this->clienturl
    // for constant: CLIENT_URL
    $this->Auth->allow('clientLogin', 'add');
}

And now in clientLogin:

public function clientLogin($id = null) {
    $this->autoRender = false;
    $this->RequestHandler->setContent('json', 'application/json');
    ob_end_clean();

    echo json_encode($this->clienturl);
    // echo json_encode(CLIENT_URL); // if using a constant
}

You can access this variable/constant from anywhere in your app, but you need to have invoked the AppController's beforeFilter in the current controller's beforeFilter, because the current controller's beforeFilter doesn't extend the AppController's function, it will overwrite it unless you invoke the AppController's function during your controller's beforeFilter.

However, after the first page impression where your session variable is being saved from the action, you can access the session variable from anywhere in the app without having to invoke the AppController's beforeFilter, because the session variable was created on the first impression (where you did invoke it).

echo $this->Session->read('clienturl');

Hope this makes sense and helps.

1
votes

You are doing that piece of logic in PagesController, thus it will only work in PagesController. If you want this logic to work in the whole application then you must have this logic (beforeFilter function you defined in PagesController) in appController.

1
votes

Consider using Sessions. This is what they are designed for.

The CakePHP SessionComponent provides a way to persist client data between page requests.

And don't set this value on every request, maybe you overwrite it by accident. Check if it is set or not.

Anyway the Configure class is available application wide so I think there is an other error. Maybe you call clientLogin() before the sizeOf($clienturl) == 3 condition becomes true, so there is no CLIENT_URL set, or the value has been overwritten - as I mentioned above.