Best zend-framework questions in March 2011

problem with zend module specific configuration

9 votes

Hi, iam using zend framework to build a REST web service and i am using modules to separate my api versions.

Now, i want to have a separate configuration file for each of my module (v1 and v2), mainly for specifying separate database connections.

I had a directory structure like this:

- application
      - modules
            - v1
                  - controllers
                  - models
                  - views
                  - configs
                    - module.ini         
            - v2
                  - controllers
                  - models
                  - views  
                  - configs
                    - module.ini
      - configs
            - application.xml   
- library

I already have the database connection mentioned in my "application.ini" inside application/configs. I read here about module specific confurations and tried it.

I removed these database params from application.ini and put it in module.ini:

[production]
resources.db.adapter = PDO_MYSQL
resources.db.params.host = 127.0.0.1
resources.db.params.username = myuser   
resources.db.params.password = mypwd
resources.db.params.dbname = my_db
resources.db.params.profiler.enabled = "true"
resources.db.params.profiler.class = "Zend_Db_Profiler_Firebug"

.....

But i got an error saying "No adapter found..." when i accessed database in my module's controller. Please help...

The solution (My_App) you refer to in your question does not require any additional configuration for module specific database connections, or any other module specific configuration (except for routes). All you need to do is to declare a MultiDb resource in the application.ini as db1. Then you can declare any module specific database resource in the requested module's respective module.ini as db2, db3, db4... etc... you do not need any additional configuration. I placed an example in the download file at my github. Not to disrespect the response by "mingos" above but there's no need for any additional code in My_App.

Here's the exact verbage taken from the download (application.ini):

...if this resource is declared here, then it
will be available to all modules. If different
db resources need to be used for different
modules then MultiDB resource can be
initiated. Example: A general db resource can be
defined here and a module specific db can be
declared in its corresponding module.ini.
The db resource declared in the module will not
be available to other modules but the db resource
in this application.ini will be available to all
modules...

Then it declares a single db resource as an example in the download. Just change it to a multi db resource. Declare the application wide needed db resource in application.ini, and any additional db resource that is needed for any specific module in their respective module.ini files. It's straightforward. That's all you need to do. Once you understand the logic behind My_App, you will see it's very powerful.

Zend_Session_SaveHandler_DbTable is wiping the Session with every refresh?

4 votes

I'm basically encountering the same problem as the poster in this question. My database is initialized properly. I've tried doing the initialization of both the database and the session SaveHandler in the application.ini and in the Bootstrap. Same result no matter how I do it.

Here's what the application.ini initialization looks like:

resources.db.adapter = "pdo_mysql"
resources.db.params.host = "localhost"
resources.db.params.username = "uname"
resources.db.params.password = "******"
resources.db.params.dbname = "dbname"

resources.session.saveHandler.class = "Zend_Session_SaveHandler_DbTable"
resources.session.saveHandler.options.name = "sessions"
resources.session.saveHandler.options.primary = "sessionID"
resources.session.saveHandler.options.modifiedColumn = "lastModifiedTime"
resources.session.saveHandler.options.dataColumn = "data"
resources.session.saveHandler.options.lifetimeColumn = "lifetime"

And here's what the Bootstrap initialization looked like:

protected function _initSession() {
        $db = Zend_Db::factory('Pdo_Mysql', array(
            'host'        =>'localhost',
            'username'    => 'uname',
            'password'    => '******',
            'dbname'    => 'dbname'
        ));
        Zend_Db_Table_Abstract::setDefaultAdapter($db);


    $sessionConfig = array( 
            'name'           => 'sessions',      
            'primary'        => 'sessionID',   
            'modifiedColumn' => 'lastModifiedTime',     
            'dataColumn'     => 'data',
            'lifetimeColumn' => 'lifetime'
        ); 
        $saveHandler = new Zend_Session_SaveHandler_DbTable($sessionConfig); 
        Zend_Session::setSaveHandler($saveHandler); 
        Zend_Session::start();

}

My sessions database table is defined as follows:

create table sesssions (
    sessionID char(32) primary key not null, 
    lastModifiedTime timestamp, 
    lifetime timestamp, 
    data text
) engine=innodb;

I have a test action that tests this through a very simple one field form that just dumps its contents into the Session. The action looks like this:

public function addAction()
{
    $namespace = new Zend_Session_Namespace();

    $form = new Application_Form_AddToSession();
    $request = $this->getRequest();
    if ($request->isPost()) {
        if ($form->isValid($request->getPost())) {
           $namespace->content = $request->getParam('toAdd');
        }
    }
    $this->view->form = $form; 
}

Here's the form it uses:

class Application_Form_AddToSession extends Zend_Form
{

    public function init()
    {
        $this->setMethod('post');

        $this->addElement('text', 'toAdd', array(
            'filters'    => array('StringTrim', 'StringToLower'),
            'validators' => array(
                array('StringLength', false, array(0, 256)),
            ),
            'required'   => true,
            'label'      => 'Add:',
        ));

        $this->addElement('submit', 'add', array(
            'required' => false,
            'ignore'   => true,
            'label'    => 'Add',
        )); 
    }


}

The view just shows the form.

To test whether or not the value actually went into the session, I use the index action. This is the index action in question:

public function indexAction()
{
    $namespace = new Zend_Session_Namespace();
    echo 'Content: '.$namespace->content.'<br>';
    echo '<pre>'; print_r($_SESSION); echo '</pre>';
}

Now. If I don't have Session saving configured to use Zend_Session_SaveHandler_DbTable, ie, if I don't have session saving configured at all, then this works fine. I enter a value in the form field, go to the index action and have it output back to me. Session works exactly the way it is supposed to.

If I have Zend_Session_SaveHandler_DbTable configured in either the application.ini or the Bootstrap, then when I enter a value into the test field and go to the index action the value is gone. My database table has a row with the proper sessionID and the sessionID matches a cookie in my browser. But there is no other information in the database. data is NULL and both the TIMESTAMP fields are zeroed out.

I've run out of things to try. I've had the Mysql table as a regular table and an InnoDB table. I've tried every permutation of the database and session configuration I can come up with, including giving the db to the configuration array, and initializing one in the Bootstrap and the other in the .ini. I've scoured the web and StackOverflow for clues. I've seen other people post about similar problems, but none of the answers I've found have worked. What haven't I done? What have I screwed up? How can I make it work?

The problem is that you defined lastModifiedTime and lifetime columns as timestamp. They should be INT instead:

CREATE TABLE  `sessions` (
`sessionID` char(32) NOT NULL,
`lastModifiedTime` INT,
`lifetime` INT,
`data` text,
PRIMARY KEY (`sessionID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

After this small modification it should work.