I want a global array that I can access through controller functions, they can either add or delete any item with particular key. How do I do this? I have made my custom controller 'globals.php' and added it on autoload library.
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
$notification_array = array();
$config['notification'] = $notification_array;
?>
following function on controller should add new item to my array
function add_data(){
array_unshift($this->config->item('notification'), "sample-data");
}
after add_data adds to the global array, whenever following function is called from client, it should give the updated array to the client.
function send_json()
{
header('content-type: application/json');
$target = $this->config->item('notification');
echo json_encode($target);
}
But my client always gets empty array. How can I make this happen? Please help.
Hi take advantage of OOP, like this
// put MY_Controller.php under core directory
class MY_Controller extends CI_Controller{
public $global_array = array('key1'=>'Value one','key2'=>'Value2'):
public function __construct() {
parent::__construct();
}
}
//page controller
class Page extends MY_Controller{
public function __construct() {
parent::__construct();
}
function send_json()
{
header('content-type: application/json');
$target = $this->global_array['key1'];
echo json_encode($target);
}
}
One solution I came up is to use session, its easy to use and its "fast" you need to do some benchmarking.
As I commented on both answers above/below there is no way you get same data in different controllers just because with each request everything is "reset", and to get to different controller you need to at least reload tha page. (note, even AJAX call makes new request)
Note that sessions are limited by size, you have a limit of 4kb (CodeIgniter stores session as Cookie) but wait, there is way around, store them in DB (to allow this go to config file and turn it on $config['sess_use_database'] = TRUE; + create table you will find more here)
Well lets get to the answer itself, as I understand you tried extending all your controllers if no do it and place some code in that core/MY_Controller.php file
as follows:
private function _initJSONSession() { //this function should be run in MY_Controller construct() after succesful login, $this->_initJSONSession(); //ignore return values
$json_session_data = $this->session->userdata('json');
if (empty($json_session_data )) {
$json_session_data['json'] = array(); //your default array if no session json exists,
//you can also have an array inside if you like
$this->session->set_userdata($ses_data);
return TRUE; //returns TRUE so you know session is created
}
return FALSE; //returns FALSE so you know session is already created
}
you also need these few functions they are self explainatory, all of them are public so you are free to use them in any controller that is extended by MY_Controller.php, like this
$this->_existsSession('json');
public function _existsSession( $session_name ) {
$ses_data = $this->session->userdata( $session_name );
if (empty( $ses_data )) return FALSE;
return TRUE;
}
public function _clearSession($session_name) {
$this->session->unset_userdata($session_name);
}
public function _loadSession($session_name) {
return (($this->_existsSession( $session_name )) ? $this->session->userdata($session_name) : FALSE );
}
the most interesting function is _loadSession(), its kind of self explainatory it took me a while to fully understand session itself, well in a few words you need to get (load) data that are in session already, do something with it ([CRUD] like add new data, or delete some) and than put back (REWRITE) all data in the same session.
Lets go to the example:
keep in mind that session is like 2d array (I work with 4+5d arrays myself)
$session['session_name'] = 'value';
$session['json'] = array('id' => '1', 'name' => 'asok', 'some_array' => array('array_in_array' => array()), 'etcetera' => '...');
so to write new (rewrite) thing in session you use
{
$session_name = 'json';
$session_data[$session_name] = $this->_loadSession($session_name);
//manipulate with array as you wish here, keep in mind that your variable is
$session_data[$session_name]['id'] = '2'; // also keep in mind all session variables are (string) type even (boolean) TRUE translates to '1'
//or create new index
$session_data[$session_name]['new_index'] = FALSE; // this retypes to (string) '0'
//now put session in place
$this->session->set_userdata($session_data);
}
if you like to use your own function add_data() you need to do this
well you need to pass some data to it first add_data($arr = array(), $data = ''){}
eg: array_unshift( $arr, $data );
{
//your default array that is set to _initJSONSession() is just pure empty array();
$session_name = 'json';
$session_data[$session_name] = $this->_loadSession( $session_name );
// to demonstrate I use native PHP function instead of yours add_data()
array_unshift( $session_data[$session_name], 'sample-data' );
$this->session->set_userdata( $session_data );
unset( $session_data );
}
That is it.
You can add a "global" array per controller.
At the top of your controller:
public $notification_array = array();
Then to access it inside of different functions you would use:
$this->notification_array;
So if you want to add items to it, you could do:
$this->notification_array['notification'] = "Something";
$this->notification_array['another'] = "Something Else";
Related
Im trying to access session throw different controllers OR in different functions in one controller but when i try access the value from different function , variable is NULL
i read some documents (including cakephp session cookbook) and more , but i couldnt understand a bit on how to configure the session before using it.
i have a problem in one controller that im trying to use a session but the value is null after im writing it in another function!?
my other question is how can i avoid writing $this->request->session(); in every function that i want to use session.
CODE :
<?php
namespace App\Controller;
use App\Controller\AppController;
use App\Model\Entity\Answer;
use Cake\ORM\TableRegistry;
class ComlibsController extends AppController {
public function index() {
}
public function getResult(){
$this->viewBuilder()->layout('comlib'); //change the layout from default
$live_req = $this->request->data['searchBox']; // get the question
$session->write('comlib/question' , $live_req);
$query = $this->Comlibs->LFA($live_req); // get the first answer
$shown_answerID = array($query[0]['answers'][0]['id'], '2');
$this->Session->write(['avoidedID' => $shown_answerID]); //avoid the answer that user saw to repeat agian
$this->set('question',$query[0]['question']); // does work
//get the answers result
//and send the array to the
$fields = array('id','answer','rate' , 'view' , 'helpful');
for ($i = 0 ; $i <= 6 ; $i++) {
$this->set('id'.$i,$query[0]['answers'][$i][$fields[0]]);
$this->set('answer'.$i,$query[0]['answers'][$i][$fields[1]]);
$this->set('rate'.$i,$query[0]['answers'][$i][$fields[2]]);
$this->set('view'.$i,$query[0]['answers'][$i][$fields[3]]);
$this->set('helpful'.$i,$query[0]['answers'][$i][$fields[4]]);
}
}
public function moveon() {
$this->render('getResult');
$this->viewBuilder()->layout('comlib');
echo $question = $session->read('comlib/question'); // empty value echo
$avoidedIDs = $session->read('avoidedID');
var_dump($avoidedIDs); // returns NULL WHY ?
$theid = $this->request->here;
$query = $this->Comlibs->LFM($theid,$avoidedIDs,$question);
echo 'imcoming';
}
}
Thanks In Adnvanced
You use these codes for write and read session data:
$this->request->session()->write($name, $value);
$this->request->session()->read($name);
Please read this section in CakePHP book.
Try
$this->session()->write('avoidedID', $shown_answerID);
instead of
$this->session()->write(['avoidedID' => $shown_answerID]);
And try
$avoidedIDs = $this->session()->read('avoidedID');
instead of
$avoidedIDs = $session->read('avoidedID');
Am trying to pass some data from one function to another when i set the data into session and print the session data i get the correct data, but whe trying to use the data in another function i get the word "Assets" i dont know where this word come from. Session library is auto loaded.Any help please.
These are my codes:
First function:
$client_id = $this->uri->segment(3);
$sess_array = array(
'cl_id' => $client_d,
'selected_client'=>TRUE,
);
$this->session->set_userdata('selected_client',$sess_array);
Second function:
$client_sess = $this->session->userdata('selected_client');
$client_id= $client_sess['cl_id'];
Try this i think this will give you some idea.
function one(){
$client_id = $this->uri->segment(3);
$sess_array = array(
'cl_id' => $client_d,
'selected_client'=>TRUE,
);
$this->two($sess_array);
}
function two($id){
$client_id= $id;
}
Here is what the Model looks like:
function getResponse($gettingresponse)
{
$enrollresponse=$gettingresponse['sendresponse'];
return $enrollresponse;
}
The Controller is as follows:
public function Register()
{
$this->load->view('firstview');
$this->load->view('secondview');
if($_POST) {
$gettingresponse=array(
'sendresponse'=>$_POST['source'],
'receiverresponse'=>$_POST['destination']
);
$registration_confirm=$this->systemModel->responselogin($gettingresponse);
$resposeflag=$this->systemModel->getEmail($gettingresponse);
$data['resposeflag']=$gettingresponsevalue;
if($registration_confirm){
$this->token($data);
}
}
$this->load->view('thirdview');
}
public function token($data=array())
{
$this->load->view('firstview');
$data['resposeflag'];
$this->load->view('token',$data);
$this->load->view('thirdview');
}
The following View shows the data that has been passed between the functions of the Controller.
<?php
echo form_input(array('name'=>'source','readonly'=>'true','value'=>$resposeflag));
?>
Im carrying out some form validation with codeigniter using a custom validation callback.
$this->form_validation->set_rules('testPost', 'test', 'callback_myTest');
The callback runs in a model and works as expected if the return value is TRUE or FALSE. However the docs also say you can return a string of your choice.
For example if I have a date which is validated, but then in the same function the format of the date is changed how would I return and retrieve this new formatted value back in my controller?
Thanks for reading and appreiate the help.
I'm not entirely sure I got what you were asking, but here's an attempt.
You could define a function within the constructor that serves as the callback, and from within that function use your model. Something like this:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Controllername extends CI_Controller {
private $processedValue;
public function index()
{
$this->form_validation->set_rules('testpost','test','callback');
if ($this->form_validation->run()) {
//validation successful
echo $this->processedValue; //outputs the value returned by the model
} else {
//validation failed
}
}
private function callback($input)
{
$this->load->model('yourmodel');
$return = $this->yourmodel->doStuff($input);
//now you have the user's input in $input
// and the returned value in $return
//do some checks and return true/false
$this->processedValue = $return;
}
}
public function myTest($data){ // as the callback made by "callback_myTest"
// Do your stuff here
if(condition failed)
{
$this->form_validation->set_message('myTest', "Your string message");
return false;
}
else
{
return true;
}
}
Please try this one.
I looked at function _execute in file Form_validation of codeigniter. It sets var $_field_data to the result of callback gets(If the result is not boolean). There is another function "set_value". Use it with the parameter which is name of your field e.g. set_value('testPost') and see if you can get the result.
The way Tank_Auth does this in a controller is like so
$this->form_validation->set_rules('login', 'Login', 'trim|required|xss_clean');
if ($this->form_validation->run()) {
// validation ok
$this->form_validation->set_value('login')
}
Using the set_value method of form_validation is undocumented however I believe this is how they get the processed value of login after it has been trimmed and cleaned.
I don't really like the idea of having to setup a new variable to store this value directly from the custom validation function.
edit: sorry, misunderstood the question. Use a custom callback, perhaps. Or use the php $_POST collection (skipping codeigniter)...apologies haven't tested, but I hope someone can build on this...
eg:
function _is_startdate_first($str)
{
$str= do something to $str;
or
$_POST['myinput'} = do something to $str;
}
================
This is how I rename my custom callbacks:
$this->form_validation->set_message('_is_startdate_first', 'The start date must be first');
.....
Separately, here's the callback function:
function _is_startdate_first($str)
{
$startdate = new DateTime($this->input->post('startdate'), new DateTimeZone($this->tank_auth->timezone()));
$enddate = new DateTime($this->input->post('enddate'), new DateTimeZone($this->tank_auth->timezone()));
if ($startdate>$enddate) {
return false;
} else {
return true;
}
}
I am using Kohana 3.2 and I am having problems calling the ouput of a controller in another controller.
What I want...
In some pages I have got a menu, and in others I don't. I want to use make use of the flexability of the HMVC request system. In the controller of a page I want to call another controller which is responsible for the creation of the menu.
What I have a the moment:
file menu.php:
<?php defined('SYSPATH') or die('No direct script access.');
class Controller_Menu extends Controller
{
private $_model = null;
public function __construct(Request $request, Response $response)
{
parent::__construct($request, $response);
$this->_model = Model::factory('menu');
}
public function action_getMenu()
{
$content = array();
$content['menuItems'] = $this->_model->getMenuItems();
// Render and output.
$this->request->response = View::factory('blocks/menu', $content);
//echo '<pre>'; print_r($this->request->response->render()); echo '</pre>'; die();
}
}
somepage.php
public function action_index()
{
$this->template->title = 'someTitle';;
$contentData['pageTitle'] = 'someTitle';
$contentData['contentData'] = 'someData';
#include the menu
$menuBlock = Request::factory('menu/getMenu')->execute();
$menuData = array('menu' => $menuBlock);
$this->template->menu = View::factory('pages/menu')->set('menu',$menuData);
$this->template->content = View::factory('pages/somePage', $contentData);
$view = $this->response->body($this->template);
$this->response->body($view);
}
If I uncomment the following line in menu.php, I see the menu rendered:
//echo '<pre>'; print_r($this->request->response->render()); echo '</pre>'; die();
So I guess that part is alright. The problem is in the following line in somepage.php:
$menuBlock = Request::factory('menu/getMenu')->execute();
This gives me back a response object. Whatever I do, I do not get the output in $this->template->menu.
$this->template->menu = View::factory('pages/menu')->set('menu',$menuData);
What must I do to have $this->template->menu contain the view, so I can use it correctly?
I hope this all makes sense. This is the way I would like to do it, but maybe I am completely on the wrong track.
I would do it this way:
class Controller_Menu extends Controller
{
public function action_build()
{
// Load the menu view.
$view = View::factory('navigation/menu');
// Return view as response-
$this->response->body($view->render());
}
}
In your controller get the menu as follows:
// Make request and get response body.
$menu = Request::factory('menu/build')->execute()->body();
// e.g. assign menu to template sidebar.
$this->template->sidebar = Request:.factory('menu/build')->execute()->body();
I would not use the __construct method in your controllers. Use before() instead, this is sufficient for most of the problems (for example auth):
public function before()
{
// Call aprent before, must be done here.
parent::before();
// e.g. heck whether user is logged in.
if ( !Auth::instance()->logged_in() )
{
//Redirect if not logged in or something like this.
}
}
I found the answer to my problem in less than an hour after asking.
I just forgot to put it here.
In somePage.php change :
$menuBlock = Request::factory('menu/getMenu')->execute();
$menuData = array('menu' => $menuBlock);
$this->template->menu = View::factory('pages/menu')->set('menu',$menuData);
To:
$this->template->menu = Request::factory('menu/getMenuBlock')->execute()->body();
And in menu.php change:
$this->request->response = View::factory('blocks/menu', $content);
To:
$request = View::factory('blocks/menu', $content);
$this->response->body($request);
I hope this will help someone else.
i'm trying to apply some module system on my web, using get and include, here's some of my code
on my index.php
$section = 'user';
if(isset($_GET) && !empty($_GET) && $_GET !== ''){
$module = $_GET['module'].".php";
load_module($section, $module);
}
load_module function
function load_module($section="", $module=""){
include(SITE_ROOT.DS.$section.DS.'modules'.DS.$module);
}
*i have already define DS as DIRECTORY_SEPARATOR
and i stored few files inside modules folder, the file loads perfectly, my problem is that all the variable i declared on my included page fails to load, here's my code on one of the included file
if($session->is_logged_in()){
$user = User::find_by_id($session->user_id);
$profile = $user->profile();
$company = $user->compro();
$logo = $user->logo();
}else{redirect_to('index.php');}
on my index.php i got this error
Notice: Undefined variable: session in C:\www\starpro\user\modules\edit_company.php on line 3 Fatal error: Call to a member function is_logged_in() on a non-object in C:\www\starpro\user\modules\edit_company.php on line 3
and if i move those variables inside my index.php, i get this message
Notice: Undefined variable: company in C:\www\starpro\user\modules\edit_company.php on line 181 Notice: Trying to get property of non-object in C:\www\starpro\user\modules\edit_company.php on line 181
please some one help me, thank you in advance
Regards
======================================================================
i am using deceze's answer
and modify my user's class by adding a static function like this
public static function load_module($section="", $module="", $user_id=""){
$user = self::find_by_id($user_id);
$profile = $user->profile();
$company = $user->compro();
$logo = $user->logo();
include(SITE_ROOT.DS.$section.DS.'modules'.DS.$module);
}
and then on my index i use this
if(isset($_GET) && !empty($_GET) && $_GET !== ''){
$module = $_GET['module'].".php";
User::load_module($section, $module, $user->id);
}else{
i got it working, but is this a bad practice ??
need advise
thanks much
As has been stated, you are trying to include the code into the middle of the function, making the scope of the included page limited to that function.
One solution would be to have a global array of files to include, then include them at the end of the script. Just add each file to the array, and at the end, loop through it and include them all.
$includeFiles = array();
...
function load_module($section="", $module=""){
// include(SITE_ROOT.DS.$section.DS.'modules'.DS.$module);
global $includeFiles;
$location = SITE_ROOT.DS.$section.DS.'modules'.DS.$module;
array_push($includeFiles, $location);
}
...
foreach( $inludeFiles as $location )
{
include_once($location);
// using include_once so that if the file is added multiple times in the
// document, it only gets included once
}
It is also a massive security risk to include a file based on a parameter in the GET request. You should sanitize that input by either stripping or encoding all symbols which could be used to traverse to another directory and include code you don't want included (so remove any slashes, etc.), or make a whitelist of includable files. If you had an array of sections and modules and their locations you could take an approach which would solve both problems:
$modules = array(
'section1' => array(
'module1' => '/php/modules/module1.php',
'module2' => '/php/frameworks/foo/bar.php'
),
'section2' => array(
'module1' => '/php/modules/baz.php',
'module2' => '/php/modules/quot.php'
)
)
}
$modulesIncluded = array();
...
function load_module($section="", $module="")
global $modulesIncluded;
array_push($modulesIncluded, $section => $module);
}
...
foreach( $modulesIncludes as $section => $module )
{
include_once($modules[$section][$module]);
}
Note: I have not tested any of this code, this is purely theoretical. I would not advise copying this, but using it as a jumping-off place.
Including a file is like putting the contents of the file exactly where the include command is. So, this:
function load_module($section="", $module=""){
include(SITE_ROOT.DS.$section.DS.'modules'.DS.$module);
}
is equivalent to this:
function load_module($section="", $module=""){
if($session->is_logged_in()){
$user = User::find_by_id($session->user_id);
$profile = $user->profile();
$company = $user->compro();
$logo = $user->logo();
}else{redirect_to('index.php');}
}
All your variables are confined to the scope of the function. As soon as the function returns, the variables go out of scope. Also, variables that are not in scope inside the function are not available to the included code.
You'll need to do the include directly without the function.
The include's scope is the same as if the code were in that function.
If you want a variable in this case to be global, assign it to $GLOBALS['varName']
Aside from using globals, you can also use static class methods/properties, e.g.:
/* session.php */
class session {
public static $user_id;
public static $logged_in;
public static function user_id() {
return self::$user_id;
}
public static is_logged_in() {
return self::$logged_in;
}
}
/* foo.php */
class foo {
public static $user;
public static $profile;
public static $company;
public static $logo;
public static function init() {
self::$user = User::find_by_id(Session::user_id());
self::$profile = self::$user->profile();
self::$company = self::$user->compro();
self::$logo = self::$user->logo();
}
}
if (Session::is_logged_in()) {
foo:init();
}