I upgraded my application from CI2 to CI3 (CI v3.1.9 and PHP7). Now I have performance issue with the new concurrency system in the session (see doc).
Some of the actions in the application are very long (because of calling an external APIs that can takes several minutes to respond for example) and I don't want those actions to lock the session. As recommended, I would use session_write_close() function in the controller before doing the very long action.
The problem is that I want to display a message to user after redirecting at the end of this action. Right now, I am using session->set_flashdata() before the redirection, but because I closed the session earlier, it is not working.
Does anyone have recommendations on how to achieve that?
If I am starting the session again with session_start() it is working, but I have no idea if this is best practice to use PHP session like that with Codeigniter.
There is no problem with starting the session again using session_start(). The CodeIgniter "Session" class is still loaded and the instance is still valid. So all the "special" stuff that CI does to make sessions work is good to go.
I tested and then used this scheme in a project some time back and didn't experience any problems. Haven't had any blow-back from the client of a still operating site either. YMMV.
BTW, in the __construct() function of the CI_Session class a call to session_start() is made in order to start up PHP's session extension. So making that call is clearly not a "bad" practice. :)
Related
I just upgraded my app from CakePHP 1.3 to 2.3. The upgrade console is far from perfect, but after a day of debugging, I've solved most of the issues. There's just one left, and it's a big one: Sessions.
In my app I am not using any of the fancy $this->Session or CakeSession::read login, I've always relied on PHP Superglobal $_SESSION. In 1.3, that worked fine.
Enter CakePHP 2.3: Sessions seem to work only at some places in my functions, and for unknown reasons, they are sometimes empty. One example: in line 1 of a function in a controller, $_SESSION['key'] gives me an empty array, in line 10 it will give me a nicely populated array, and in my view it's empty again. Extremely frustrating. I've been able to solve this by calling session_start() when it doesn't work, but I don't want to go down that road.
The documentation states:
Usage of the $_SESSION is generally avoided in CakePHP, and instead usage of the Session classes is preferred.
I'm a bit surprised: Cake runs on PHP, so I would expect PHP superglobals to work.
I'm considering switching to CakeSession::read and CakeSession::write, but that's a laborious task: I'm using Sessions throughout my app.
Before switching, I'd like to know:
Is there a way to make the normal PHP $_SESSION superglobal work in Cakephp 2.3.7?
If not: is CakeSession::read and CakeSession::write the right alternative?
Some extra info:
I am calling the Session component in my AppController
I am calling the Session helper in my AppController
In general, you could access $_SESSION itself, but then you would need to assert session start and other things manually, as well - which CakePHP can and should take care of itself.
So why bother when you got a nice wrapper access to it?
I dont really see why this needs to be a question here. There are usually bigger fish to fry.
Believe me when I say that everyone uses the clean and neat component/helper/CakeSession access.
Also a nice site effect: You cannot trigger any "undefined index" warnings with the wrapper methods. They would simply return null if this key has not been set yet.
I am calling the Session component in my AppController
I am calling the Session helper in my AppController
No, helpers are for the view layer.
After a research it seems that Meteor Sessions are reset after refreshing page or opening the website in new tab, i.e. they are not usual server-side sessions but something like global javascript variables on client-side. Some people advice to use AmplifyJS, but I'm not sure that it will work like usual session in other frameworks/languages and also it is a third party library, so is there any normal way to use sessions in Meteor, i.e. keep user-specific data on server?
At this moment I'm handling that by using custom Collections, but it is not an ideal way of doing that because it is needed to remove expired values from Collection manually, which makes additional troubles.
Yes this is correct. Despite the name Session is nothing like a cookie, but just a reactive form of a variable stored in a hashmap
To keep data persistent across tabs you need to use a Collections (as this is the only way to reactively share data across tabs) - Cookies can't work because they can't be made reactive as data needs to be sent to the server to notify the client when there is a change. There really wouldn't be another way at the moment as the publish/subscribe methods can only send down data from collections at the moment.
You can use your setup you have now with your custom collection. You can use a server side cron job to remove expired data (either with Meteor.setInterval or Tom Coleman's cron.
There is a package developed just for that: https://atmospherejs.com/u2622/persistent-session
After installation you can use the following functions to set sessions which are persistent:
//store a persistent session variable which is stored across templates
Session.setPersistent(key, value);
//same as above, but automatically deletes session data when user logs out
Session.setAuth(key, value);
I've tried the package and it works like charm.
Im building a really small social site about sports.
And i would like to ask a more experienced developer, if it would be better to use native session or ci session library? and if ci library it it better to use the databse store?
Thank you for your options
The CI session library will get you up and going very quickly, giving you greater flexibility than native sessions. Keep in mind, though, that the CI_Session class is pretty paranoid; you might get some unexpected session expiration, particularly with AJAX-heavy applications.
I recommend going with CI sessions, with the following caveats:
Don't autoload the session class, as you'll probably want to ignore session renewal in some instances.
As best you can, avoid the session class for AJAX requests (if you absolutely need it, you'll need to overhaul the sess_update() function to prevent unexpected expirations)
You shouldn't be loading images dynamically through CI, but there are cases where it's needed. The same issues apply here as with AJAX requests.
Additionally, you'll need to store sessions in a table if you risk needing more storage than cookies allow (4KB, I think; you'll use it up even faster with encryption). Might as well go with a database and be done with it.
I would go for native PHP Session because I believe there's a problem with the latter.
What if the user's browser have cookies disabled?
Although Browsers with cookies disabled aren’t getting far on the internet these days… But still, there are people having their cookies disabled so CI sessioncookies in not a very good candidate...
So how can we use $_SESSION[] in codeigniter?
Try this:
Since the pages in mvc are triggered by the controller, we could do this
public function __construct(){
self::$instance =& $this;
foreach (is_loaded() as $var => $class) {
$this->$var =& load_class($class);
}
$this->load =& load_class('Loader', 'core');
$this->load->initialize();
log_message('debug', "Controller Class Initialized");
session_start();
}
to the CI_Controller class on system/core/Controller.php
You can also have the best of both by using the native session extended library.
To quote:
Benefits over CI_Session
* hardened against session fixation by cookie id TTL (time to live) - regenerates cookie id automatically every given amount of time (right
now configured inside the class) - see Note about making it setable.
* you can use all available PHP session storage drivers (database, memcache, etc.)
* “flash” session attributes (see: “Flash” attributes)
Benefits over PHPsession
* compatible with CI_Session
- the same way of use, just load the library, set_userdata(), userdata()
- easy to migrate existing apps to Native_session
- need docs - use the CI manual :)
* better security (automatic and manual session id regeneration)
PHPsession introduces concept of session namespace, which IMHO
encourages you to use large number of the the session vars. I prefer
to limit the use of sessions as much as possible (because of the
potential scalability problems), so the Native_session won’t implement
session namespaces.
I do have my own Controller in Magento, that has been done by following the guidelines here:
http://alanstorm.com/magento_admin_controllers
My controller extends Mage_Adminhtml_Controller_Action and inside there is a method:
public function myAction() {
sleep(1000);
die('I am done');
}
When this method is running I cannot load any other Magento Admin pages. They will load eventually right after the method above is complete.
Also Frontend works fine, running the very same action from the Frontend controller does not cause Magento to hang like this.
Any solutions to keep my method in Admin and while this method is running, rest of the admin should stay usable?
Longest time this process runs is about 4-5 hours and it imports products. Yes I do have cron also set up, but I would like to give the user the ability to init processes at will also.
This is a feature.
The workaround is to use two browsers, e.g. Firefox + Chrome, Firefox + Opera and so on.
It is better to work two-browser on these tasks as you don't want a crash in your other tabs to interrupt your import.
I know that is not an in-depth programming answer, sometimes the lateral solution works though.
Have to answer this myself:
Solution is mega simple:
call this right before the long process (make sure that you have done manipulating the session data before calling this method, otherwise errors may occur)
session_write_close();
And voila, you can run multiple processes at the same time!
I'm using a modified version of Felix Geisendörfer's SimpleAuth/SimpleAcl components that I've combined into a single Component, Simple_Authable.
I changed his startup() function to initialize() to not clutter the beforeFilter function in my app_controller.
One of the things that this component does is check who the active user is and if that user can't be found it either looks him up based on the primary User.id or uses 'guest'. Either way, the component uses $this->Controller->Session->write() to save the active user or guest information.
I'm also using Felix's Authsome plugin instead of the default CakePHP Auth component.
When I'm logging in, the active user is guest, obviously.
After I've submitted the form, the active user is still guest because the component's initialize() function is firing before everything else. Then, the Authsome plugin comes into play and validates my user as "root" and also calls $this->SimpleAuthable->setActiveUser($id, true); to force SimpleAuthable to update the active user information it is storing via $this->Controller->Session; Then I am redirected and my simple Session information and DebugKit's Session tab reflect that I am indeed the root user.
However, when I try to navigate to an 'admin' page, let's say /admin/users/index, lo and behold SimpleAuthable thinks I'm still a 'guest' user because when it performs a $this->Controller->Session->read() call to the key holding my user id, it is getting an empty response, i.e., the data stored on the previous page didn't persist.
Maybe there is something funky happening between Authsome & SimpleAuthable, but things look pretty straightforward and to my mind, $this->Controller->Session should be saving and persisting the data written to it.
So, I'm looking at refactoring all the calls to $this->Controller->Session and replacing them with $this->Session but first I wanted to throw this out to the community and see if anybody has seen anything similar and if so how did they resolve it.
Sincerely,
Christopher.
I found the problem... I'm also using Joshua McNeese's Permissionable plugin and I needed to disable it for the $this->Controller->{$this->userModel}->findById($id); in my SimpleAuthable component when I try to lookup the current active user.
Note to self: I would have caught this faster if I had some unit testing in place :(.