From: LFaR on
Hi,

Firstly, thanks to the authors of HTTP_Session. My testing with it has been
flawless.

I have been using the MDB2 container and I can watch my session data being
created and destroyed in the sessiondata table.

Before session data is destroyed, I would like to replicate it in another
table so that it can be recovered at a later time for some post-processing.
Is there a preferred way to do this? Maybe I need to extend HTTP_Session
with a custom procedure?

I would really appreciate hearing how others have approached this, assuming
I'm not the only one with this need.

In case some additional context helps...

I have a session that contains customer order data. I am connecting to
PayPal to process the payment and it later notifies me via its Instant
Payment Notification (IPN). This is asynchronous. When I get notified, I
would like to restore the session data to perform post-processing.

However, I can't rely on the session record that has already been saved,
since a user may prefer to continue shopping, in which case the previous
session must be destroyed. Hence, I need to replicate it before destroying
the session.

Thoughts?

LFaR.
From: LFaR on
On 9/12/06, LFaR <livefreeandroam(a)gmail.com> wrote:
>
> Hi,
>
> Firstly, thanks to the authors of HTTP_Session. My testing with it has
> been flawless.
>
> I have been using the MDB2 container and I can watch my session data being
> created and destroyed in the sessiondata table.
>
> Before session data is destroyed, I would like to replicate it in another
> table so that it can be recovered at a later time for some post-processing.
> Is there a preferred way to do this? Maybe I need to extend HTTP_Session
> with a custom procedure?
>
> I would really appreciate hearing how others have approached this,
> assuming I'm not the only one with this need.
>
> In case some additional context helps...
>
> I have a session that contains customer order data. I am connecting to
> PayPal to process the payment and it later notifies me via its Instant
> Payment Notification (IPN). This is asynchronous. When I get notified, I
> would like to restore the session data to perform post-processing.
>
> However, I can't rely on the session record that has already been saved,
> since a user may prefer to continue shopping, in which case the previous
> session must be destroyed. Hence, I need to replicate it before destroying
> the session.
>
> Thoughts?
>
> LFaR.
>
>

I'm extending this discussion to per-dev.

I crafted an extentsion and would appreciate feedback. I have had to modify

the HTTP_Session package, as I could not find a better way to extend it with

a replicate() behaviour.

This extension allows the session record to be replicated in another
datatabase table. I'm using MDB2, so I've only extended that module.
Hopefully this replicate() behaviour would be generally useful.

Perhaps there are better ways to do this (without modifying the PEAR
HTTP_Session package). If not, then perhaps this type of functionality
could be incorporated into the HTTP_Session package, so then I won't need to
maintain my own copy of it.

New file: HTTP/Session/Container/MDB2Enhanced.php
Modified file: HTTP/Session.php

New file: HTTP/Session/Container/MDB2Enhanced.php
---------------------------------------------------------
<?php
require_once 'HTTP/Session/Container/MDB2.php';

class HTTP_Session_Container_MDB2Enhanced extends
HTTP_Session_Container_MDB2 {
function replicate($id, $dest_table)
{
// Check if table row already exists
$query = sprintf("SELECT COUNT(id) FROM %s WHERE id = %s",
$dest_table,
$this->db->quote(md5($id), 'text')
);
$result = $this->db->queryOne($query);
if (MDB2::isError($result)) {
trigger_error(print_r($result,1));
$this->db->raiseError($result->code, PEAR_ERROR_DIE);
return false;
}
if (0 == intval($result)) {
// Insert new row into dest table
$query = sprintf("INSERT INTO %s SELECT * FROM %s WHERE id = %s",
$dest_table,
$this->options['table'],
$this->db->quote(md5($id), 'text')
);
} else {
// Update existing row
$query = sprintf("UPDATE %s dst, %s src SET dst.expiry =
src.expiry, dst.data = src.data WHERE dst.id = src.id AND src.id = %s",
$dest_table, $this->options['table'],
$this->db->quote(md5($id), 'text')
);
}
$result = $this->db->query($query);
if (MDB2::isError($result)) {
echo $query;
trigger_error('<pre>'.print_r($result,1).'</pre>');
$this->db->raiseError($result->code, PEAR_ERROR_DIE);
return false;
}

return true;
}
}

?>

I added the following function to HTTP/Session.php
-----------------------------------------------------
function replicate($id, $dest_table) {
return $GLOBALS['HTTP_Session_Container']->replicate($id,
$dest_table);
}

Example Usage
---------------
.... Take a look at the example code from the HTTP_Session package. Modify
Container_Example.php with the following changes.

// Use MDB2Enhanced container to get the replicate() behaviour
HTTP_Session::setContainer('MDB2Enhanced', array('dsn' =>
'mysql://root:password(a)localhost/test',
'table' => 'sessiondata'));

// When its time to destroy the session, replicate it first
if (HTTP_Session::isExpired()) {
HTTP_Session::replicate(HTTP_Session::id(), 'cp_sessiondata');
HTTP_Session::destroy();
}


--- end ---

LFaR.
From: "Torsten Roehr" on
> I'm extending this discussion to per-dev.
>
> I crafted an extentsion and would appreciate feedback. I have had to
> modify
>
> the HTTP_Session package, as I could not find a better way to extend it
> with
>
> a replicate() behaviour.
>
> This extension allows the session record to be replicated in another
> datatabase table. I'm using MDB2, so I've only extended that module.
> Hopefully this replicate() behaviour would be generally useful.
>
> Perhaps there are better ways to do this (without modifying the PEAR
> HTTP_Session package). If not, then perhaps this type of functionality
> could be incorporated into the HTTP_Session package, so then I won't need
> to
> maintain my own copy of it.
>
> New file: HTTP/Session/Container/MDB2Enhanced.php
> Modified file: HTTP/Session.php
>
> New file: HTTP/Session/Container/MDB2Enhanced.php
> ---------------------------------------------------------
> <?php
> require_once 'HTTP/Session/Container/MDB2.php';
>
> class HTTP_Session_Container_MDB2Enhanced extends
> HTTP_Session_Container_MDB2 {
> function replicate($id, $dest_table)
> {
> // Check if table row already exists
> $query = sprintf("SELECT COUNT(id) FROM %s WHERE id = %s",
> $dest_table,
> $this->db->quote(md5($id), 'text')
> );
> $result = $this->db->queryOne($query);
> if (MDB2::isError($result)) {
> trigger_error(print_r($result,1));
> $this->db->raiseError($result->code, PEAR_ERROR_DIE);
> return false;
> }
> if (0 == intval($result)) {
> // Insert new row into dest table
> $query = sprintf("INSERT INTO %s SELECT * FROM %s WHERE id = %s",
> $dest_table,
> $this->options['table'],
> $this->db->quote(md5($id), 'text')
> );
> } else {
> // Update existing row
> $query = sprintf("UPDATE %s dst, %s src SET dst.expiry =
> src.expiry, dst.data = src.data WHERE dst.id = src.id AND src.id = %s",
> $dest_table, $this->options['table'],
> $this->db->quote(md5($id), 'text')
> );
> }
> $result = $this->db->query($query);
> if (MDB2::isError($result)) {
> echo $query;
> trigger_error('<pre>'.print_r($result,1).'</pre>');
> $this->db->raiseError($result->code, PEAR_ERROR_DIE);
> return false;
> }
>
> return true;
> }
> }
>
> ?>
>
> I added the following function to HTTP/Session.php
> -----------------------------------------------------
> function replicate($id, $dest_table) {
> return $GLOBALS['HTTP_Session_Container']->replicate($id,
> $dest_table);
> }
>
> Example Usage
> ---------------
> ... Take a look at the example code from the HTTP_Session package. Modify
> Container_Example.php with the following changes.
>
> // Use MDB2Enhanced container to get the replicate() behaviour
> HTTP_Session::setContainer('MDB2Enhanced', array('dsn' =>
> 'mysql://root:password(a)localhost/test',
> 'table' => 'sessiondata'));
>
> // When its time to destroy the session, replicate it first
> if (HTTP_Session::isExpired()) {
> HTTP_Session::replicate(HTTP_Session::id(), 'cp_sessiondata');
> HTTP_Session::destroy();
> }
>
>
> --- end ---
>
> LFaR.

Good idea, might be useful for others as well. This could be implemented by
setting a config option so that all containers would support this natively.

Please create a feature request on pear.php.net with links to your modified
files and I'll see what I can do and when ;)

Thanks and best regards,

Torsten
 | 
Pages: 1
Prev: Pager in reverse order
Next: MDB2 and transactions