[eluser]Grimbog[/eluser]
Hi guys,
Just thought to share this as it may be useful in certain cases - at the moment session->flashdata is only returned as a single string, but in my own case I needed a way to show multiple notifications to the screen at once.
Why? Lets say that you submit a form, and it goes away to do its thing... not only do I have form validation going on, but there is also the process of accessing the database and checking data, or processing user input. Rather than having just 1 ambiguous line of text saying "an error has occurred", I prefer to have types of notifications in the following categories:
notice, success, pending, warning, error
So for each function that's run, it attempts to carry its task out and creates a global notifications array filled with types of messages like so:
Code:
core()->set_notification( 'The login you provided appears to be invalid.', 'warning');
Code:
core()->set_notification('Sorry, an error has occurred submitting this form.', 'error');
Don't worry about core(), this is just a master class library I wrote for my own app, but the function set_notification() is as follows:
Code:
/**
* Sets a global notification
*
* @access public
* @return bool
*/
public function set_notification($message = NULL, $type = 'error')
{
if (!empty($message))
{
// Generate the error string
$prefix = sprintf('<li class="%s rounded">', $type);
$suffix = '</li>';
$str = $prefix.'<strong>'.ucfirst($type).'</strong>: '.$message.$suffix."\n";
$this->notifications[] = array(
'notifications' => $str
);
$this->ci->session->set_flashdata($this->notifications);
return TRUE;
}
return FALSE;
}
So the function populates a global array called 'notifications', that is then filled with the message and error type. Finally this global array is sent to the session->set_flashdata. Now, we still can't do anything nice, because the stock set_flashdata function for CI was not designed to traverse multidimensional arrays. So, the trick is to extend the Session class with MY_Session.php and do a few changes.
Code:
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
* CI Session Extension Class
*
* @author Lawrence Eldridge
* @subpackage Auth Class
* @category Library
*
*/
class MY_Session extends CI_Session {
/**
* Constructor method
*
* @access public
* @return void
*/
function __construct()
{
parent::__construct();
}
// --------------------------------------------------------------------
// Main Methods (PUBLIC)
// These are methods that can be called externally by the system.
// --------------------------------------------------------------------
/**
* Add or change flashdata, only available
* until the next request
*
* @access public
* @param mixed
* @param string
* @return void
*/
function set_flashdata($newdata = array(), $newval = '')
{
if (is_string($newdata))
{
$newdata = array($newdata => $newval);
}
if (count($newdata) > 0)
{
foreach ($newdata as $key => $val)
{
if (is_array($val))
{
foreach ($val as $item => $content)
{
$flashdata_key = $this->flashdata_key.':new:'.$item.$key;
$this->set_userdata($flashdata_key, $content);
}
}
else
{
$flashdata_key = $this->flashdata_key.':new:'.$key;
$this->set_userdata($flashdata_key, $val);
}
}
}
}
/**
* Keeps existing flashdata available to next request.
*
* @access public
* @param string
* @return void
*/
function keep_flashdata($key)
{
$userdata = $this->all_userdata();
foreach ($userdata as $key => $value)
{
// make sure we're only dealing with flashes
if (strpos($key, ':old:'.$item))
{
// get value from old flash key
$value = $this->userdata($key);
// convert flash back to new
$parts = explode(':old:', $key);
if (is_array($parts) && count($parts) === 2)
{
$new_name = $this->flashdata_key.':new:'.$parts[1];
$this->set_userdata($new_name, $value);
}
}
}
}
/**
* Retrieve array of all flashdata
*
* @access public
* @return array
*/
public function flashdata($item)
{
$flasharray = array();
$userdata = $this->all_userdata();
foreach ($userdata as $key => $value)
{
// check key haystack with item value and use it!
if (strpos($key, ':old:'.$item))
{
array_push($flasharray, $value);
}
}
return $flasharray;
}
}
/* End of file MY_Session.php */
So here, we have 'set_flashdata' which has been altered slightly so that it checks if the value of $newdata is actually an array itself (taken from the global notifications array). It then traverses the multiarray and generates the flastdata key with the numeric key value from the global notifications to ensure the flashdata keys are kept unique and not overwritten.
The 'keep_flashdata' is basically altered so that I can still set which key I want to keep for another run/process. So because we simply look for the :old: value and then convert it to :new: we can safely split it via explode.
The final function 'flashdata' just ensures that we retain the array when we push it to view, rather than a single string.