Multiple Sessions in Codeigniter/PHP - codeigniter

I am developing a e-commerce website in codeigniter having sessions for following:
admin login
shopping cart
user login
Now i am unable to figure out a mechanism for managing these three sessions with different sets of data.
I know it can be achieved with session_name() in core php. But with codeigniter i am a bit confused.
Googled it a lot but couldn't found a proper answer.
I want a clear understanding of multiple sessions in codeigniter so that it doesn't create any confusion in future. Any link to tutorial would be great.

$this->session->set_data('admin',$array_of_admin_data);
$this->session->set_data('user',$array_of_user_data);
$this->session->set_data('cart',$array_of_cart_data);
then retrieve each seesion data ? using
$this->session->userdata('admin');
why wouldnt this work ?

Codeigniter's session is completely different from Native PHP Session and it's very secure especially when stored in a database. You can work with codeigniter's sessions and Native PHP Session they would work fine together because PHP would see the as different variables.
If you want to check for the existence of a codeigniter session value use
if(isset($this->session->userdata['course_id']))
{
$this->data['course_id'] = $this->session->userdata('course_id');
}
While Native PHP would look like
if(isset($_SESSION['course_id']))
{
$this->data['course_id'] = $_SESSION['course_id'];
}

I'm also developing a e-commerce system and have the same problem. I didn't like to manage all the data stored as serialized data in the database, especially not for the cart/basket, as it makes it hard to query the database and i simply think it's kinda messy.
I'm quite new to CI and stackoverflow, but my idea was to set up the ci_session table as it is written in the docs, thus keeping the consistency and security of CI sessions. Then i only add one reference id to the session varialbe for each session data you want to manage. E.g. for the cart:
$unique_cart_id = random_string('unique');
$this->session->set_userdata('cart_id', $unique_cart_id);
and now i reference my cart_id in a separate "basket"-table with all the data. E.g.:
CREATE TABLE basket (
id int(11) NOT NULL auto_increment,
cart_id varchar(32) default NULL,
timestamp timestamp NULL default NULL,
price float(10,2) default NULL,
title varchar(100) default NULL,
serialized_data text,
product_id int(11) default NULL,
PRIMARY KEY (id)
)
Now each time someone wants to add something to the basket i get the cart_id from the session variable:
$cart_id = $this->session->userdata('cart_id');
and store the $cart_id together with any other cart data in my "basket"-table, by writing a little insert script.
$data = array(
'cart_id' => $cart_id,
'title' => $product_title,
'product_id' => $product_id,
'price' => $price,
'serialized_data' => serialize(array('what ever you need else'))
);
$this->db->insert('basket', $data);
Now if someone wants to view the basket I just retrieve the $cart_id from the session variable again and query the database where it matches the cart_id.
$this->db->query("SELECT * FROM basket WHERE cart_id = ?", array($cart_id));
And you use the same principle for the your other session data, admin and user login. Thus I keep only to have a single session cookie for each user but I can manage each type of session data separately in the database.
This was just a rough breakdown of the idea. I hope it helped.

With the userdata() method, you can retrieve the fields you saved during the creation of the session.
For example, you pass the $array_of_admin_data array, which holds some information like userType. If you want to retrieve this value, you must call userdata() like this:
$this->session->userdata('userType');
Hope, that this helps.

Related

How to keep session id after login in Laravel 5.1

I been using my session id to identify all the items that are added to a shopping cart temporary items table.
What I didn't know is that once the user login into the system the session id changes so I can't query the temporary items table anymore as there is no products containing the new session id value.
I am using file session driver and I was thinking to use db sessions but I think it will be exactly the same.
Any ideas on how to keep the session id after login?
Instead of using user's session_id you can store the cart items in a separate session key.
Like so -
Session::put('cart.items.0', $item_id);
Now you can access it as -
$cart = Session::get('cart');
Not exactly what you asked for, but to me this seems like a better way.

Cake 3.x How to use database sessions with a controller named SessionsController?

Cake Version 3.1.2
What I did:
Run the following query in MySQL database:
CREATE TABLE `sessions` (
`id` varchar(255) NOT NULL DEFAULT '',
`data` BLOB, -- or BYTEA for PostgreSQL
`expires` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
);
Change app.php
'Session' => [
'defaults' => 'database',
],
What I wanted:
To have a SessionsController.php
so I can have :
/sessions/add as the login page and action (allowing GET and POST)
/sessions/delete as the logout page and action (allowing GET and DELETE)
/admin/sessions/delete as a way for admin backend to logout certain users (allowing DELETE)
/admin/sessions/index as a way to fetch all the sessions in a paginated way (allowing GET)
Questions in my mind:
Do I actually bake Session Entity and Table?
Do I actually bake Session Controller?
Is it even possible for me to have SessionsController even when I don't use database to handle my Session? How do I bake such a Controller that does not have a default Entity or Table?
Most of the questions you have are answered in the CakePHP Book. The answers to your questions are:
Do I actually bake Session Entity and Table?
Do I actually bake Session Controller?
A: No, you don't HAVE to bake anything. You can write all the code by hand. Although, I recommend baking to set up the skeleton of the classes.
Is it even possible for me to have SessionsController even when I don't use database to handle my Session?
A: Yes, you can name your controllers anything you want as long as you follow the naming conventions.
How do I bake such a Controller that does not have a default Entity or Table?
A: You just bake it. You don't have to use models, default or otherwise, in your controllers.

Updating a the session of a specific user on CakePHP

I have a case where an admin can edit some user information, which might belong to a logged in user. I need to ensure that the other user's Auth info updates to reflect the new changes. It seems like, currently, Auth info is static unless manually updated. Is there a way to manually update Auth info (essentially the session), not of the current user, but of a known user?
Thanks to input from Mark Story, the most straightforward method seems to be the following:
1) make sure you're using database sessions...
Configure::write('Session', array(
'defaults' => 'database',
'handler' => array(
'model' => 'cake_sessions'
),
));
...a schema like the following will work fine:
CREATE TABLE `cake_sessions` (
`user_id` int(11) NOT NULL,
`id` varchar(255) NOT NULL DEFAULT '',
`data` text,
`expires` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2) Save the user's id to the user_id column. Do this by creating a file called cake_sessions.php, and saving it in your Model directory. The file should contain something like the following:
<?php
class cake_sessions extends AppModel{
public function beforeSave($options = array()){
if ( AuthComponent::user() ) {
$this->data[$this->alias]['user_id'] = CakeSession::read('Auth.User.id');
}
return true;
}
}
Then it becomes trivial to simply delete the desired session, based on user_id.
I dont think that is directly possible with CakePHP libraries because it looks like a very special use case. The ways you can go about this is -
Put a flag i your users table and switch it once the details are updated, for every request using the AppController's beforeFilter just check this flag for that user and regenerate the session data.
If you are storing your session data in the database you might be able to update it from there (or delete it to force user to login). I am not sure how cakephp stores it in the database. Else if you go for files for session data you can scan through them for the user id you want to update.
Updating a user's session externally is generally not the preferred mechanism and is considered to be a hack, try thinking of any possible workarounds.
Not sure what your exact use case is here, but I agree with using the beforeFilter in the AppController to check for a flag. It might not be desirable to query the database every page load for this check, that might not be a concern in your case, but if it is you can look into CakePHP's caching. In Config/bootstap.php you can setup additional caches and key them based on the user's id, then in the model you can place logic in a beforeSave() or afterSave() to clear that users cache file. Then the beforeFilter in the AppController can check for the cache file and if it is missing you know you need to build a new cache file and pull that data into your session. I use something along those lines for ACL caching in CakePHP. I build a cache for each user and load their permissions into their Session, if the ACL permissions change the cache is rebuilt.
http://book.cakephp.org/2.0/en/core-libraries/caching.html

Codeigniter ion auth register insert user id into multiple tables

first sorry if its a stupid question but im lost a bit.
So when i use ion auth register function, and the register is ok, inserts the user data in the users table, and inserts the users id in to the groups table too.
Im a bit lost at this part, i would like to insert the user id in to the user profile table, and user settings table, after the registration is complete.
And i dont really know which function to modify. I was looking at the model and library searching for how the group is added into the database but couldnt really find any hint in the code.
So could someone please help me out on this? Pointing to a tutorial maybe or just giving me a hint where to start the modify
Thank you
In models/ion_auth_model.php at line 733 starts the register function.
You can extend somewhere on line 793, after the line that gets the id of the user $id = $this->db->insert_id(); just add your custom data you wish to insert:
$mdata = array(
'user_id' => $id,
// ... your other data here
);
$this->db->insert('my_table', $mdata);

Building a Page Based on Roles in Session from Relational Database in CodeIgniter

I'm new to codeigniter and just about everything at this point, but I have had some success with feeling my way around php, mysql, ci, and web application development in general. Though, I'm kind of stuck at the moment. So, I wanted to throw this out there to get your opinion on what I'm trying to do, hopefully - you can have the patience to get through to understand my problem and have a solution, as I will attempt my best to give you all the details.
First, I am in the process of developing a web application, to help ease the logging of attendance at a certain organization. I created a member table to hold all the members of the organization, a login table to hold the username and password of members' who hold roles in the organization, a role table, to contain the roles held at the organization, and finally a member_role table to account for any member who may have more than 1 role at the organization. (and of course an attendance table, with Foreign Key to member, but that is outside my current question).
MySQL code includes only the pertinent tables: memeber, login, role, and member_role.
<!-- language: lang-mysql -->
CREATE TABLE `member` (
`id` int(10) NOT NULL auto_increment,
`fname` varchar(32) NOT NULL,
`lname` varchar(32) NOT NULL,
...
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `login` (
`memberid` int(10) NOT NULL,
`username` varchar(32) NOT NULL,
`password` varchar(32) NOT NULL,
FOREIGN KEY (`memberid`) REFERENCES member(`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `role` (
`id` integer(10) NOT NULL auto_increment,
`role` varchar(32) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `member_role` (
`memberid` integer(10),
`roleid` integer(10),
`active` char(1) NOT NULL,
FOREIGN KEY (`memberid`) REFERENCES member(`id`),
FOREIGN KEY (`roleid`) REFERENCES role(`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
So far, I think I did a pretty good job, in defining the database for this purpose. Your opinions here would be good, since I am a novice, I only know what a newbie would know.
Here's the real problem I'm currently having. I've created a user that has 2 roles. I have it properly storing it into a session, an array of a particular member's roles. The session array returns, roleid 1, and roleid 3.
Let's say I have certain buttons or functions assigned to each roleid. For memeberid = 1, I have assigned to him roleid = 1 and roleid = 3, therefor I only want to build a page including only the functions available with roleid = 1 and roleid = 3. Make sense?
This is where I'm stuck, I have the array, but not sure how to build a page for the user. Should I put the code into the controller or the view? and either way, I am not sure how to populate a page of buttons having only those regarding roleid = 1 and roleid = 3. Hmm, I hope you can understand, because that is about the best I think I can make it clear.
If you do understand, please perhaps if you could give an example of what/how I could achieve this.
Thanks for your time.
suggestion before you try to reinvent the wheel...
if you are trying to build a hrm application use orangehrm and work on that basis to your own needs.
otherwise use this
foreach($rolesarray as $currentrole)
{
//if currentrole is x then do that, if y then do different.
}
you can use this everywhere where you need to display multiple buttons, displays etc
The tables seem good to me except I wonder why you are separating the member and login tables. The columns in Login seem to be just additional attributes of each Member record in which case the tables could be merged into one.
Regarding your question on showing the right buttons for a person belonging to groups 1 and 3 -- I think you're getting stuck because you're thinking about creating one static page for a person with this combination (maybe I'm wrong..?). Instead, you create one page that everyone goes to and at the respective areas of the page where permissions are a factor, you put if statements to determine whether to display any given element, piece by piece. For example, you would come to the "Start Time" button and put logic to display as long as member belongs to at least one group. Then you would get to the "Management Dashboard" and only display if member has group 3 (if not, you would skip the element both in the controller and the view). I hope I understood your question properly.
Regarding whether to check for the permissions in Controller or View, the spirit of MVC is to perform this kind of logic in the Controller. In the View, then, you would check whether the controller prepared information for certain areas of the page. If the view doesn't need anything specific prepared by the controller to display an element (i.e. you don't need anything prepared to display a link/button to the Management Dashboard--you simply need to know whether the person is in group 3), you can have the controller set a variable like $display_management_db_button.
Lastly, user authentication is a very common thing to need in any web app, and CodeIgniter packages do exist for user authentication. I've recently come across Ion Auth which seems to be the right mix of lightweight and robust that I'm looking for, but you can search and find many others out there.
-Gus
(edit)
Example:
In the controller:
if($this->member->has_group(3)) { $display_management_db_button=true; }
else { $display_management_db_button=false; }
$data = array('display_management_db_button' => $display_management_db_button;);
$this->load->view('time_screen', $data);
In the view:
if($display_management_db_button) { echo '<input type="button" ... />'; }
So the logic remains in the controller. Separating the logic becomes more important in maintaining clean code as your program gets more complex.

Resources