Hi, I'm new to this mailing list, I hope is the right place to ask for such questions. I'm writing a module for drupal which implements a jabber client and hooks in the appbar module. The issue i'm having now is regarding the data used for jabber communication. I'm using a jabber class and I need to store this object somewhere so that the _init code is just executed one time. I thought about sessions and I found a couple of ways, both don't works properly for me. First is using the global $user: function jwclient_jabberclass_init() { global $user; if (!isset($user->jabclient) && $user->uid) { require_once('jabber.php'); ... $jab = New Jabber($debug); $jabclient = New JabberClient($jab); $jabclient->jabber_client_set_user($user); ... user_save($user, array('jabclient' => $jabclient)); } } function jwclient_init() { jwclient_jabberclass_init(); ... } function theme_jwclient_chat () { global $user; return $user->jabclient->status; } This solution gives me an errors of __PHP_Incomplete_Class Object. Googling in understood that a proper way to save classes in session is to fistly define the class and than call session_start. I don't see ways to achieve this since the class I'm using is defined in a module and the drupal session is already initiated. A workaround i found on drupal.org is by using serialize/unserialize but it doesn't work around for this case. I changed the code in this way: function jwclient_jabberclass_init() { global $user; if (!isset($user->jabclient) && $user->uid) { require_once('jabber.php'); ... $jab = New Jabber($debug); $jabclient = New JabberClient($jab); $jabclient->jabber_client_set_user($user); ... $jabclient = serialize($jabclient); user_save($user, array('jabclient' => $jabclient)); } } function jwclient_init() { jwclient_jabberclass_init(); ... } function theme_jwclient_chat () { global $user; $jabclient = $user->jabclient; $jabclient = unserialize($jabclient); return $user->jabclient->status; } The result is: warning: unserialize() expects parameter 1 to be string, object given After this, i give away $user and tried with $_SESSION function jwclient_jabberclass_init() { global $user; if (is_null($_SESSION['jabclient']) && $user->uid) { require_once('jabber.php'); ... $jab = New Jabber($debug); $jabclient = New JabberClient($jab); $jabclient->jabber_client_set_user($user); ... $_SESSION['jabclient'] = serialize($jabclient); } } function jwclient_init() { jwclient_jabberclass_init(); ... } function theme_jwclient_chat () { $jabclient = unserialize($_SESSION['jabclient']); return $jabclient->status; } This attempt works on the first call. On the second call I get again the error about __PHP_Incomplete_Class Object. I'm out of clue now. Anyone know how to manage the case of storing objects in session with drupal? Thanks, Salvatore
Short answer: you can't. Even if you are able to serialize your class, I'm sure the class contains resources (http://www.php.net/manual/en/language.types.resource.php) and these cannot be serialized nor stored in $_SESSION. Some resources can be persistent but I think that's only possible with PHP extensions aka C code. I'm sure there are other possible solutions, including a running process/service on the server to which either your module can talk. On Tue, Dec 8, 2009 at 5:42 PM, Salvatore De Paolis <iwkse@gmx.com> wrote:
Hi,
I'm new to this mailing list, I hope is the right place to ask for such questions. I'm writing a module for drupal which implements a jabber client and hooks in the appbar module. The issue i'm having now is regarding the data used for jabber communication. I'm using a jabber class and I need to store this object somewhere so that the _init code is just executed one time. I thought about sessions and I found a couple of ways, both don't works properly for me.
First is using the global $user:
function jwclient_jabberclass_init() { global $user; if (!isset($user->jabclient) && $user->uid) { require_once('jabber.php'); ... $jab = New Jabber($debug); $jabclient = New JabberClient($jab); $jabclient->jabber_client_set_user($user); ... user_save($user, array('jabclient' => $jabclient)); } } function jwclient_init() { jwclient_jabberclass_init(); ... } function theme_jwclient_chat () { global $user; return $user->jabclient->status; }
This solution gives me an errors of __PHP_Incomplete_Class Object. Googling in understood that a proper way to save classes in session is to fistly define the class and than call session_start. I don't see ways to achieve this since the class I'm using is defined in a module and the drupal session is already initiated. A workaround i found on drupal.org is by using serialize/unserialize but it doesn't work around for this case. I changed the code in this way:
function jwclient_jabberclass_init() { global $user; if (!isset($user->jabclient) && $user->uid) { require_once('jabber.php'); ... $jab = New Jabber($debug); $jabclient = New JabberClient($jab); $jabclient->jabber_client_set_user($user); ... $jabclient = serialize($jabclient); user_save($user, array('jabclient' => $jabclient)); } } function jwclient_init() { jwclient_jabberclass_init(); ... } function theme_jwclient_chat () { global $user; $jabclient = $user->jabclient; $jabclient = unserialize($jabclient); return $user->jabclient->status; } The result is: warning: unserialize() expects parameter 1 to be string, object given
After this, i give away $user and tried with $_SESSION
function jwclient_jabberclass_init() { global $user; if (is_null($_SESSION['jabclient']) && $user->uid) { require_once('jabber.php'); ... $jab = New Jabber($debug); $jabclient = New JabberClient($jab); $jabclient->jabber_client_set_user($user); ... $_SESSION['jabclient'] = serialize($jabclient); } } function jwclient_init() { jwclient_jabberclass_init(); ... } function theme_jwclient_chat () { $jabclient = unserialize($_SESSION['jabclient']); return $jabclient->status; } This attempt works on the first call. On the second call I get again the error about __PHP_Incomplete_Class Object.
I'm out of clue now. Anyone know how to manage the case of storing objects in session with drupal?
Thanks, Salvatore
On Tue, 8 Dec 2009 18:52:25 +0100 Sascha Grossenbacher <saschagros@gmail.com> wrote: Hi Sascha,
Short answer: you can't. I was afraid of something like this. Even if you are able to serialize your class, I'm sure the class contains resources (http://www.php.net/manual/en/language.types.resource.php) and these cannot be serialized nor stored in $_SESSION. Some resources can be persistent but I think that's only possible with PHP extensions aka C code. I do not have experience with PHP extensions writing but i do with C so probably i'll consider this option if it's the best one to follow.
I'm sure there are other possible solutions, including a running process/service on the server to which either your module can talk. I guess here you're talking about PHP daemon process used for storing/retrieving the jabber class. I don't have experience about it but i can look at some documentation and see if this is something i can do.
If you have further hints they will be welcome, thank you for now Salvatore
On Wed, 9 Dec 2009 02:16:16 +0100 Salvatore De Paolis <iwkse@gmx.com> wrote:
I'm sure there are other possible solutions, including a running process/service on the server to which either your module can talk.
I'm thinking now that i can modify the jabber class itself to act as a daemon and allow socket communication. Salvatore
That's not entirely true. In PHP, you can store an object of a class into the session (or any other serialized data structure) IFF the class is defined when the data is unserialized OR it can be autoloaded at that time. Drupal opens its session before any modules have loaded, so you cannot have the classes defined. Drupal 6 has no autoload mechanism natively. There is an Autoload module (http://drupal.org/project/autoload) that enables autoload functionality but it doesn't take effect until hook_init(), which is after the session has started. However, you can certainly include the necessary files yourself before the session opens. The place to do that is in settings.php. That's not a great distributable solution, but for your specific site it can work fine. I'm doing that on a site I'm working on right now. It's best if you move the class to its own file and then include_once() that file both from the corresponding .module file and from settings.php, so that you know it will be there when you need it. Poof, classes work in the session. Drupal 7 has a built-in class autoloader that initializes before the session does, so that won't be a problem going forward. It's true that resources like DB connections or file handles don't survive serialization. That's why PHP offers the __sleep() and __wakeup() magic methods that you can use to control what gets serialized or deserialized if necessary. You can find more on them on http://www.php.net/ On Tuesday 08 December 2009 11:52:25 am Sascha Grossenbacher wrote:
Short answer: you can't.
Even if you are able to serialize your class, I'm sure the class contains resources (http://www.php.net/manual/en/language.types.resource.php) and these cannot be serialized nor stored in $_SESSION. Some resources can be persistent but I think that's only possible with PHP extensions aka C code.
I'm sure there are other possible solutions, including a running process/service on the server to which either your module can talk.
On Tue, Dec 8, 2009 at 5:42 PM, Salvatore De Paolis <iwkse@gmx.com> wrote:
Hi,
I'm new to this mailing list, I hope is the right place to ask for such questions. I'm writing a module for drupal which implements a jabber client and hooks in the appbar module. The issue i'm having now is regarding the data used for jabber communication. I'm using a jabber class and I need to store this object somewhere so that the _init code is just executed one time. I thought about sessions and I found a couple of ways, both don't works properly for me.
First is using the global $user:
function jwclient_jabberclass_init() { global $user; if (!isset($user->jabclient) && $user->uid) { require_once('jabber.php'); ... $jab = New Jabber($debug); $jabclient = New JabberClient($jab); $jabclient->jabber_client_set_user($user); ... user_save($user, array('jabclient' => $jabclient)); } } function jwclient_init() { jwclient_jabberclass_init(); ... } function theme_jwclient_chat () { global $user; return $user->jabclient->status; }
This solution gives me an errors of __PHP_Incomplete_Class Object. Googling in understood that a proper way to save classes in session is to fistly define the class and than call session_start. I don't see ways to achieve this since the class I'm using is defined in a module and the drupal session is already initiated. A workaround i found on drupal.org is by using serialize/unserialize but it doesn't work around for this case. I changed the code in this way:
function jwclient_jabberclass_init() { global $user; if (!isset($user->jabclient) && $user->uid) { require_once('jabber.php'); ... $jab = New Jabber($debug); $jabclient = New JabberClient($jab); $jabclient->jabber_client_set_user($user); ... $jabclient = serialize($jabclient); user_save($user, array('jabclient' => $jabclient)); } } function jwclient_init() { jwclient_jabberclass_init(); ... } function theme_jwclient_chat () { global $user; $jabclient = $user->jabclient; $jabclient = unserialize($jabclient); return $user->jabclient->status; } The result is: warning: unserialize() expects parameter 1 to be string, object given
After this, i give away $user and tried with $_SESSION
function jwclient_jabberclass_init() { global $user; if (is_null($_SESSION['jabclient']) && $user->uid) { require_once('jabber.php'); ... $jab = New Jabber($debug); $jabclient = New JabberClient($jab); $jabclient->jabber_client_set_user($user); ... $_SESSION['jabclient'] = serialize($jabclient); } } function jwclient_init() { jwclient_jabberclass_init(); ... } function theme_jwclient_chat () { $jabclient = unserialize($_SESSION['jabclient']); return $jabclient->status; } This attempt works on the first call. On the second call I get again the error about __PHP_Incomplete_Class Object.
I'm out of clue now. Anyone know how to manage the case of storing objects in session with drupal?
Thanks, Salvatore
-- Larry Garfield larry@garfieldtech.com
On Wed, Dec 9, 2009 at 6:57 AM, Larry Garfield <larry@garfieldtech.com> wrote:
It's true that resources like DB connections or file handles don't survive serialization. That's why PHP offers the __sleep() and __wakeup() magic methods that you can use to control what gets serialized or deserialized if necessary. You can find more on them on http://www.php.net/
Correct. But the main thing an XMPP class does is maintaining a connection (which is a resource) to the XMPP server. And If I understood the thread starter correctly, the idea is to avoid the connection initialization. I'm doing something similiar right now and in my case, initalizing the connection to the server takes ~40% of the whole request time. If I have to do that in every __wakeup() call, I don't gain anything.
On Wed, Dec 9, 2009 at 9:35 AM, Sascha Grossenbacher <saschagros@gmail.com>wrote:
On Wed, Dec 9, 2009 at 6:57 AM, Larry Garfield <larry@garfieldtech.com> wrote:
It's true that resources like DB connections or file handles don't survive serialization. That's why PHP offers the __sleep() and __wakeup() magic methods that you can use to control what gets serialized or deserialized if necessary. You can find more on them on http://www.php.net/
Correct. But the main thing an XMPP class does is maintaining a connection (which is a resource) to the XMPP server. And If I understood the thread starter correctly, the idea is to avoid the connection initialization. I'm doing something similiar right now and in my case, initalizing the connection to the server takes ~40% of the whole request time. If I have to do that in every __wakeup() call, I don't gain anything.
I think that best solution in this case, is to have a background process in charge of managing XMPP related jobs, avoiding to create for each request a new XMPP environment. Ex: Request ---> Drupal <--socket--> XMPP Server (background process) -- Paolo Mainardi CTO Twinbit Blog: http://www.paolomainardi.com -- Please consider the environment before printing this email --
A nice article on PHP Daemon implementation: http://www.bbgamedev.net/index.php/writing-a-daemon-in-php/ On Wed, Dec 9, 2009 at 11:37 AM, Paolo Mainardi <paolomainardi@gmail.com>wrote:
On Wed, Dec 9, 2009 at 9:35 AM, Sascha Grossenbacher <saschagros@gmail.com
wrote:
On Wed, Dec 9, 2009 at 6:57 AM, Larry Garfield <larry@garfieldtech.com> wrote:
It's true that resources like DB connections or file handles don't survive serialization. That's why PHP offers the __sleep() and __wakeup() magic methods that you can use to control what gets serialized or deserialized if necessary. You can find more on them on http://www.php.net/
Correct. But the main thing an XMPP class does is maintaining a connection (which is a resource) to the XMPP server. And If I understood the thread starter correctly, the idea is to avoid the connection initialization. I'm doing something similiar right now and in my case, initalizing the connection to the server takes ~40% of the whole request time. If I have to do that in every __wakeup() call, I don't gain anything.
I think that best solution in this case, is to have a background process in charge of managing XMPP related jobs, avoiding to create for each request a new XMPP environment.
Ex: Request ---> Drupal <--socket--> XMPP Server (background process)
-- Paolo Mainardi
CTO Twinbit Blog: http://www.paolomainardi.com
-- Please consider the environment before printing this email --
-- Paolo Mainardi CTO Twinbit Blog: http://www.paolomainardi.com -- Please consider the environment before printing this email --
See also http://drupal.org/project/daemon It would be great to see some joint community effort in this area, because there are quite a lot of modules and applications that could benefit from a shared and "community-approved" standard solution. sun ________________________________ From: development-bounces@drupal.org [mailto:development-bounces@drupal.org] On Behalf Of Paolo Mainardi Sent: Wednesday, December 09, 2009 2:20 PM To: development@drupal.org Subject: Re: [development] Add data to Drupal session A nice article on PHP Daemon implementation: http://www.bbgamedev.net/index.php/writing-a-daemon-in-php/
participants (5)
-
Daniel F. Kudwien -
Larry Garfield -
Paolo Mainardi -
Salvatore De Paolis -
Sascha Grossenbacher