A row associates with session is deleted when user logout in YII - php

I have a site that uses YII. One thing that it does is storing session information into a MySql database table YiiSession. Also in a separate table (users_sessions), a new row is inserted with the following information:
session id
user id
online status of a user
I create another table for session because YiiSession is part of YII. Also users_session keeps track online status of a user, whereas YiiSession doesn't.
I only make an insertion into users_session during user login.
But I don't understand that when user logs out, the session that associates with the user got deleted.
Note that the session_id in the users_session is a foreign key to the one in YiiSession. But the one in YiiSession still exists even though it has an expiration date.
What mechanism that possibly deletes the row? Please help.

You should extend CDbHttpSession and overwrite the method destroySession($id). There you append the code and delete your entry also.
Configure Yii to use your session class instead of it's own in config/main.php:
'session' => array(
'autoStart' => true,
'class' => 'application.components.<your session class name>',
'connectionID' => 'db',
'sessionTableName' => 'session',
'autoCreateSessionTable' => false,
'timeout' => 3600, // 60 min
),
However I would not do this with a separate table, just add some fields to the YiiSession table. That's what I did and it works pretty well.
EDIT:
You should create a file named MyDbHttpSession.php in protected/components.
In this file extend CDbHttpSession like so:
class MyDbHttpSession extends CDbHttpSession
{
protected function createSessionTable($db, $tableName)
{
// basically this is a copy of CDbHttpSession
$db->createCommand()->createTable($tableName, array(
'id' => 'CHAR(32) PRIMARY KEY',
'expire' => 'integer',
'data' => $blob,
// your additional fields
'idUser' => 'INT(10) NULL',
'online' => 'TINYINT(1)',
// more of your fields here if you have
));
}
// this sets the user ID by session ID
public function setIdUser($idUser)
{
$db = $this->getDbConnection();
$db->setActive(true);
$db->createCommand()->update($this->sessionTableName, array('idUser' => (int) $idUser),
'id=:id', array(':id' => $this->sessionId)
);
}
// and this sets the online status, pass true or false to $online
public function setOnline($online)
{
$db = $this->getDbConnection();
$db->setActive(true);
$db->createCommand()->update($this->sessionTableName, array('online' => (int) $online),
'id=:id', array(':id' => $this->sessionId)
);
}
}
Set Yii to use your session class instead of it's own like I wrote above.
You should already have a class WebUser. If not, create one in protected/components and extend CWebUser.
In this class add a method afterLogin:
public function afterLogin($fromCookie)
{
// store user ID and online status in session table
Yii::app()->session->setIdUser($this->id);
Yii::app()->session->setOnline(true);
return parent::afterLogin($fromCookie);
}
You can from wherever you are in Yii use Yii::app()->session->setOnline(true); or Yii::app()->session->setOnline(false);

Related

Eloquent - fields that match in a record if firstOrNew fails with multiple conditions

Suppose I have the following create code
$User = User::firstOrNew(
array(
'username' => $args['username'],
'phone_no' => $args['phone_no']
),
array(
'otherDetails' => 'here',
)
);
$User->save();
if (!$User->wasRecentlyCreated) {
// code to check which field has same record in db
}
After confirming that the insertion was not able to push through because an existing record has been fetched, is there any way I can find out which of either username or phone_no has the same data in the User table? Without using another where lookup in the model. Thanks.

Chtml::link not getting ID of event attendee

I'm currently trying to redirect a user from a view in the events folder, going to the user folder with the id of the event attendee.
The issue I'm having is that the url is returning without the idea, in this case it should be 56. /user/InviteGuest/eventId but no ID
<p>You can also invite a guest to attend this event with you.
<?php echo CHtml::link("Click here to invite a guest", array('/user/InviteGuest', 'eventId' => EventAttendees::model()->id))?></p>
It doesn't seem to be getting the ID from the model and populating the field ID, it works fine when I link from within the event attendee views.
edit. for example in a view in the eventattendees folder
array('label' => 'Invite Guests','buttonType'=>'link', 'icon' => 'group', 'url' => array('/user/InviteGuest', 'eventId' => $data->id)),
work fine
'eventId' => EventAttendees::model()->id
This is not getting any data, unless your EventAttendees' id is set to 56 by default, which is really odd. "id" is usually used for primary keys.
I think what you're missing is to load your data. Maybe something like this:
// Exemple, not actual tested code
// In your controller
$attendee = EventAttendees::model()->findByAttributes( array(
'whatever'=>$something,
));
$this->render('view', array(
'attendee'=>$attendee,
));
// In your view
<?php echo CHtml::link("Click here to invite a guest", array('/user/InviteGuest', 'eventId' => $attendee->id))?></p>

cakephp - add detail to static user object

In cakephp 2.5.4, with $this->Auth->user() I can access to user object
I want when user logged in, set some user detail in user object and with $this->Auth->user() function, get all info in all controller
$user = $this->Auth->user();
$this->loadModel('Resource');
$resource = $this->Resource->find('threaded', array('order' => 'index'));
// here, i want add $resource to user object
How can I do this?
Try this, untested but should work.
$this->Session->write($this->Auth->sessionKey, array_merge(
$resource,
$this->Auth->user()
));
It is unlikely that the session key changes in most apps but it can happen. I don't consider it as good practice to hardcode the key everywhere like most people do.
Also keep in mind that this won't work with state less authentication systems!
You can also contain additional data when configuring the Auth adapters. Read this section of the manual. Taken from the manual and added the contain:
public $components = array(
'Auth' => array(
'authenticate' => array(
'Form' => array(
'fields' => array('username' => 'email'),
'contain' => array('Foo', 'Bar')
)
)
)
);

Yii relation failing with indexes > 5

I have a very simple relation defined as follows (aId and bId are the primary keys for each table).
class A extends CActiveRecord
{
// #var int32 $aId
}
class B extends CActiveRecord
{
// #var int32 $bId
// #var int32 $aId
public function relations()
{
return array(
'a'=>array(self::HAS_ONE, 'A', 'aId'),
);
}
}
As long as bId <= 5, I can access A through $bModel->a without any problems. What's strange is for bId > 5, $bModel->a is null. I've checked $bModel->aId for bId > 5 and the foreign key is correct. I can even access A with $aModel = A::model()->findByPk($bModel->aId);. I can also manually edit my bIds in the database table, which produces the same result.
I have no idea what's causing the relation to fail for primary key's greater than five. Any suggestions for troubleshooting? I'm at a loss.
EDITED
It turns out I wasn't using the relation properly. I should have used BELONGS_TO.
class B extends CActiveRecord
{
// #var int32 $bId
// #var int32 $aId
public function relations()
{
return array(
'a'=>array(self::HAS_ONE, 'A', 'aId'),
);
}
}
HAS_ONE was causing B to use bId to index A. Since I had five instances of A in my database that worked for bID < 5
Enable query logging in your application config to see what exactly is happening.
Do you get any results when manually running those queries?
'components' => array(
'db' => array(
(..)
'enableParamLogging' => true,
),
'log' => array(
'class' => 'CLogRouter',
'routes' => array(
// Show log messages on web pages
array(
'class' => 'CWebLogRoute',
'categories' => 'system.db.CDbCommand', //queries
'levels' => 'error, warning, trace, info',
//'showInFireBug' => true,
),
(I'd post this as a comment rather than an answer, but it seems I can't)
I recommend you to use this -> Yii Debug Toolbar (it is created by my friend here in Ukraine).
Can you provide mysql structure + some example data. Thanks.

Zend_Session_SaveHandler_DbTable is wiping the Session with every refresh?

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.

Categories