Content of class property gets cleared out before outputting to browser - php

I have this inside a class named site among other harmless stuff:
private
$notice_type = '',
$notice_msg = '';
public function setNotice($type,$msg){
$this->notice_type=$type;
$this->notice_msg=$msg;
}
public function notice($what){
switch($what){
case 'type': return $this->notice_type; break;
case 'msg': return $this->notice_msg; break;
}
}
public function clearNotice(){
$this->notice_type='';
$this->notice_msg='';
}
I've set this class to a session like this:
$_SESSION['site'] = new site();
Here's a scenario of how I use it:
After submitting a form; I set the notification like this : $_SESSION['site']->setNotice('success','success message');, or error if that's the case and redirect the user somewehere using header().
Then I output the message like this on the landing page:
echo $_SESSION['site']->notice('msg');
$_SESSION['site']->clearNotice();.
But; When I use the clearNotice()-function - the contents of both $notice_type and $notice_msg is cleared out before it gets outputted to the browser.
I need for it to stay untill the user navigates away from the page somehow. What am I missing here?

I don't know what happend. But somehow this script started to work as expected.
I've rewritten the code over and over for a while now, and as far as I know it's just about the same as before. But anyway; This is what works now:
site()-class:
This class controlls notifications as well as settings set by the user - like preffered sorting direction of data and selections worth remembering for better user experience and such.
<?php
class site {
private
$notice_type = '',
$notice_msg = '';
public function newNotice($type,$msg){
$this->notice_type=$type;
$this->notice_msg=$msg;
}
public function notice($what){
switch($what){
case 'type': return $this->notice_type; break;
case 'msg': return $this->notice_msg; break;
}
}
public function clearNotice(){
$this->notice_type='';
$this->notice_msg='';
}
}
?>
I have a document where I configurate the entire site by setting a couple of variables to Yes or No - As in this case : $_SITE_CLASS_site.
<?php
# check to see if session is started
if(!isset($_SESSION)){session_start();}
//
// check if site()-class should be activated for this site
if($_SITE_CLASS_site=='Yes'){
# if Yes; prevent resetting the class if it has already been started.
if(!isset($_SESSION['site'])){$_SESSION['site']=new site();}
//
}
//
?>
I've created a template where I have this code before the page content is outputted:
basically it just checks if there is any message to display
<?php if ($_SITE_CLASS_site=='Yes'&&$_SESSION['site']->notice('msg')!=''): ?>
<div id="site-notice-<?=$_SESSION['site']->notice('type')?>" class="grid_12"><p><?=$_SESSION['site']->notice('msg')?></p></div>
<?php endif; ?>
Then I load the page content, and at the end I have this:
the notice should be viewable untill the user closes it, or leaving the page. I don't want, or need, to keep the message
<?php
if ($_SITE_CLASS_site=='Yes'&&$_SESSION['site']->notice('msg')!=''):
$_SESSION['site']->clearNotice();
endif;
?>
Now; Whenever I need to give the user a feedback on their actions - after submitting a form successfully for example - I can just do this at the end of the script:
$_SESSION['site']->newNotice('success','<b>Success!</b> Your request was submitted successfully...');
header('Location '.$_SERVER['HTTP_REFERER']);
exit;
It works like a charm...

Related

Echo (or display errors) after page reload

My latest idea which didn't seem to work was to store the array in a session,
include_once "scripts.php"
.........
//some code later
$errorlog .= "a random message<br/>";
$_SESSION['errorlog']=$errorlog;
reloadPage();
And then if 'errorlog' wasn't empty then display it,
[code]
<div class="randomclass">
<?php
displayErrors('errorlog');
?>
</div>
//here are the functions
function reloadPage(){
Header('Location: '.$_SERVER['PHP_SELF']);
}
function displayErrors($valuename = "errorlog"){
if(!empty($_SESSION['valuename'])){
echo $_SESSION['$valuename'];
unset($_SESSION['$valuename']);
return true;
}else{
return false;
}
}
[/code]
scripts.php
<?php
if(!isset($_SESSION)) session_start();
........
I have included scripts.php which starts with if(!isset($_SESSION)) session_start();.
I'm new to php, still making my first webpage (or actually, preparing scripts for it). I can't seem to successfully find bugs in my scripts because I don't know how to show the errors after a page reload is needed.
What I want, is a way to store strings like in this $errorlog and display it just like an echo(in div or whatever) after the page was reloaded
I don't get any errors with headers, the page reloads correctly but the problem is that no text is displayed after the page reloads, so I don't see why I shouldn't be using them unless you know another way to reload the page after script is done
surely this way is not the best one, but I think that the problem is very easy..
function displayErrors($valuename = "errorlog"){
if(!empty($_SESSION['valuename'])){ // here you must put a variable $valuename instead a simple string 'valuename'
echo $_SESSION['$valuename'];
unset($_SESSION['$valuename']);
return true;
}else{
return false;
}
}
You must change the session key at this row whit: $_SESSION[$valuename]
if(!empty($_SESSION['valuename'])){
The correct function is the follow:
function displayErrors($valuename = "errorlog"){
if(!empty($_SESSION[$valuename])){
echo $_SESSION[$valuename];
unset($_SESSION[$valuename]);
return true;
}else{
return false;
}
}
Bye!
Marco

Codeigniter session authentification still allows restricted page to load

I am trying to restrict access from a page if the user is not logged in. The weird thing is that the webpage, when tried to be accessed by an unauthorised user, shows the page for the restricted access (with the "unauthorised, please login" message and, on the same page, it loads the members only page).
For the site controller:
class Site extends CI_Controller {
function __construct(){
parent::__construct();
$isLogged=$this->session->userdata('logged');
if($isLogged!='logged' || !isset($isLogged)){
$data['content']='denied';
$this->load->view('include/template', $data);
}
}
function members(){
$data['content']='memberArea';
$this->load->view('include/template', $data);
}
The login form :
class Login extends CI_Controller {
function index () {
$data['content']='loginForm';
$this->load->view('include/template', $data);
}
function validateMember(){
// load the model for the login authentification
$this->load->model('loginModel');
//query should also contain the user details
$query = $this->loginModel->authenticate();
//if it returns something:
if($query){
foreach ($query as $row){
//set user data to be passed
$details=array(
'username'=>$row->user_name,
'id'=>$row->id,
'logged'=>'logged',);
}
//set session
$this->session->set_userdata($details);
redirect('site/members');
}
else{
$this->index();
}
}
The model for the login is:
class LoginModel extends CI_Model {
function authenticate(){
//select active fields
$this->db->select('id, user_name, password');
// query to select from table where conditions
$query = $this->db->get_where('login', array(
'user_name'=>$this->input->post('username'),
'password'=>$this->input->post('password'),),
1);
//if it finds something...must ask if i need to manually close the database with $this->db->close();
if($query->num_rows()==1){
foreach($query->result() as $row){
$data[]=$row;
}
return $data;
}
else {return false;}
}
}
My tests showed that site continues to call the other functions even if the construct function fails. the session does contain the data. If i use die() or exit() the webpages loads blank. many thanks in advance!
PS: the views only have <p> in them, nothing fancy.
I can see two solutions to this problem.
Redirect to another page that doesn't check for authentication. You can use redirect(<url>); from the URL helper.
Use exit() in the __construct() with the buffered output flushed. When you call $this->load->view() the data is sent to a buffer called output in CodeIgniter. You can write that buffer by doing :
if($isLogged!='logged' || !isset($isLogged)){
$data['content']='denied';
$this->load->view('include/template', $data);
// Write the output.
echo $this->output->get_output();
// Stop the execution of the script.
exit();
}
or you can by-pass the output buffer with:
if($isLogged!='logged' || !isset($isLogged)){
$data['content']='denied';
// Writes the content instead of sending it to the buffer.
echo $this->load->view('include/template', $data, true);
// Stop the execution of the script.
exit();
}
Pick which ever you want.
The constructor method does not "fail", the if statement is simply executed (because the condition is true) and there is no reason why this would prevent other methods from being executed.
Inside the constructor method, at the end of the if block, you may insert an exit statement, this way the page would probably behave as you are expecting.
See here http://php.net/manual/en/function.exit.php
You're testing if there is a query, not if the query actually return anything. Check the num rows and make sure they equal 1, doing greater than 0 is bad practice on login checks.
if($query->num_rows==1){
PS. Post your model code as well, it's possible the error is there and it's returning a result even when it shouldn't.

calling ajax from within a php function having a switch ($this->method)

when creating an XMLrequest in a php file having a code which goes something like this... I am using a MVC ( model-view-controller structure ) and this is a controller php file..
Controller_Institute extends Controller_Default{
function register(){
try {
$this->requireLogin();
switch($this->method){
case 'GET':
$content = $this->render('institute_registration_confirm');
break;
case 'POST':
$result = mysql_query("SELECT * FROM password WHERE pass='".mysql_real_escape_string($_POST['pass'])."'");
$num=mysql_num_rows($result);
if($num==2)
{
$content = $this->render('institute_registration');
}
else
{
$content = $this- >render("message",array('msg'=>'Your password is incorrect'));
}
break;
}
$institute = R::dispense('institute');
$institute- >import($_POST,'name,latitude,state,longitude,address,phone,year,url');
$id = R::store($institute);
}
catch(exception $e){
//If there was an error anywhere, go to the error page.
$content = $this->render('error',array('exception'=>$e));
}
$page = $this->render('default',array('content'=>$content));
return $page;
}
i am sending the ajax request from within the function ... so when the ajax sends back the request , it gets caught in the switch case... and then the response text becomes the function return value replacing the actual text... any idea how to prevent the xml response from getting into the switch case...? the institute_registration is the view file and i am including that file in my framework and then triggering the ajax function from within that file to check whether the password ( to enable registration form ) is correct or not...
Given the limited information and pseudo-code, I recommend setting up a stand-alone page called say... "ajax.php" that is stand alone and doesn't base it's return value on the request method. The pages that use AJAX will need to either POST or GET from this page depending.
If you determine whether or not regular output vs AJAX output is returned via request method, then you are limiting yourself in 2 ways. The first is you will not be able to do 1 or the other on your web pages (GET vs POST) instead of both. Also, the second, when it comes to the AJAX, you will not be able to run GET & POST AJAX requests, and yes, you can do both with AJAX: http://net.tutsplus.com/tutorials/javascript-ajax/5-ways-to-make-ajax-calls-with-jquery/

How to handle AJAX requests and Sessions and Db connections?

Okay, the best way I know to describe the scenario is to first give the example:
Say I have a page called index.php;
At the very top before the <html> tag, one can find;
<?php session_start();
$_SESSION['user_id'] = 1234;
require_once "db.con.php";
?>
Inside that of the <body> tag, one can find:
<div id="div_ajax">
<?php require_once "ajax.php"; ?>
</div>
Now inside the ajax.php page, there is a single button that when clicked will make an ajax request. After the request is made, a simple Db query statement to select user information based on the user_id will be made. The thing is, after the AJAX request, it seems as if the user_id session and the already included Db connection is "lost".
I know I can use a conditional statement to check for AJAX request and just add the lines...
session_start();
require_once "db.con.php";
..at the top of the ajax.php page, but I'm wondering if there's a better way to do this? I don't want to always have to add those two lines to every ajax called PHP page. It sort of defeats the purpose of having the lines on the master page (index.php) to begin with. I guess I can use one ajax called page and just include a bunch of case statements, but still wondering if there's a better way.
Thanks a lot.
As far as my experience goes, I think your problem can be solved with something called the FrontController pattern.
The basic idea is that you're whole application always calls the same file, index.php for instance (also called the single point of entry).
index.php then performs all the tasks that you need on every single page (like starting the session or including your library classes) and then calls the page you want to requested.
This could look something like this: (Can't test it now)
index.php:
<?php
session_start();
$_SESSION['user_id'] = 1234;
require_once("db.con.php");
if($_REQUEST['Request_Type'] == 'website'){
require_once("header.html");
switch($_REQUEST['Request_Url']){
case 'SomePage':
require('SomePage.php');
break;
case 'SomeOtherPage':
require('SomeOtherPage.php');
break;
default:
require('ajax.php');
}
require_once("footer.html");
}elseif($_REQUEST['Request_Type'] == 'ajax'){
switch($_REQUEST['Ajax_Function']){
case 'ProcessButton':
require('ProcessButton.php');
break;
}
}
?>
ajax.php
echo '<input type="button" onClick="ajaxRequest(\"index.php\",\"ProcessButton\")" Value="ClickMe!" />';
The ajaxRequest() Javascript function would have to send an Ajax Request to index.php setting the parameters
Request_Type = 'ajax'
Ajax_Function = 'ProcessButton'
I don't think that there is a better way, but that doesn't mean that there isn't.
Just a couple of notes from reading your question:
1) Use wrapper files for all of your header information. So, at the beginning of your page, put:
require_once('package.php'); // that's what I call mine
Then in package, I have:
require_once('session.start.php');
require_once('db.con.php');
That way, all your pages are accessing the same thing. If you ever need to change it, it's a lot easier.
There is a speed difference between require_once, include_once, include and require. I don't know how significant it is. Frameworks include like 60+ files when they make a page, so I've always assumed its not too bad.
The session information is stored in a folder on your server. PHP defaults it to /tmp (which you should change to a private folder / not web accessible).
Make sure that you are validating any information sent to the AJAX. Remember that it is just like its own web page, so any permissions or database sensitive information should be protected all the same.
"I guess I can use one ajax called page and just include a bunch of case statements, but still wondering if there's a better way."
The controller pattern is pretty good for this type of thing. Having a bunch of case statements in one file is hard on your maintenance. When you switch to having files that only have 1 or 2 functions in them, your life will get so much simpler.
Depending on the size of your project, you may want to implement a framework. Check out MVC frameworks. If I don't implement a framework, I still implement a controller pattern.
I lifted this from my blog. What I use now doesn't even look like this, but it started here:
In the Presentation layer, I am determining which elements I want to implement. For each element that I want to implement, I initiate the controller, like so:
$controller = new Controller();
$context = $controller->getContext();
$context->addParam('action', 'login');
$template->setContent( $controller->process() );
I am using the Controller from PHP Objects, Patterns, and Practice 3rd Ed by Matt Zandstra with my own modifications.
Here is what happens:
My presentation layer gets a new controller object.
The Controller object's constructor automatically creates a new CommandContext object.
The CommandContext is automatically going to load up the request variables as a Parameter, so I don't even need to worry about form data until I get to the Logic layer and need to validate and process it.
In the presentation layer, I load up any additional context parameters (or the information that I want to pass on to the controller), including most importantly, the action that I want to be taken by the Controller.
To pass the information on, I call $controller->process(). In the Logic layer, I can use a default "execute" or make a different command. So, in the Presentation layer, I set the action to "Login" which forces the login command and login view pages to open, and the command defaults to execute, but it could be anything.
When I call process, it triggers the CommandFacotry. The CommandFactory is going to first initiate a new Template child object, such as a side bar div box or main body context. It makes this determination with an optional flag that I can pass to the Controller.
The CommandFactory is then going to open up the Command file and pass the template and the context as objects to the Logic layer.
abstract class Command {
}
class CommandContext {
private $params = array();
private $error = "";
function __construct(){
$this->params = $_REQUEST;
}
function addParam( $key, $val ){
$this->params[$key] = $val;
}
function get( $key ){
return $this->params[$key];
}
function issetCheck( $key ){
if( ! empty( $this->params[$key] ) ){
return true;
}
return false;
}
function setError( $error ){
$this->error = $error;
}
function getError(){
return $this->error;
}
}
class CommandNotFoundException extends Exception { }
class CommandFactory {
private static $dir = 'include/classes/command/';
static function getCommand( $action = 'Default', $flag = 0 ){
switch( $flag ){
case 1:
$template = new TemplateQuickViewOnly();
break;
case 2:
$template = new TemplateQuickViewToggle();
break;
default:
$template = new TemplateMainBodyOnly();
break;
}
if( preg_match ( '/\W/', $action ) ){
throw new Exception("illegal characters in action");
}
$class = UCFirst(strtolower($action))."Command";
$file = ROOT_PATH."".self::$dir."{$class}.php";
if( ! file_exists( $file ) ){
throw new CommandNotFoundException( "could not find '$file'" );
}
include_once( $file );
if( ! class_exists($class) ){
throw new CommandNotFoundException( "no '$class' class located" );
}
$cmd = new $class( $template );
return array( $cmd, $template );
}
}
class Controller {
private $context;
function __construct(){
$this->context = new CommandContext();
}
function getContext(){
return $this->context;
}
function process( $method = 'execute', $flag = 0 ){
list( $cmd, $template ) = CommandFactory::getCommand( $this->context->get('action'), $flag );
if( ! $cmd->$method( $this->context ) ){
// handle failure
// $template->setMessage( UCFirst($this->context->get('action')).' failed to execute.');
return $template->getMessage();
}else{
// success dispatch view
return $template->getMessage();
}
}
}
The Logic layer is in a fixed directory. An instance of the object has already been instatiated by the Controller layer, which means the constructor has been triggered. Further, the controller layer already called the method "execute" (default) or another method, such as "getLoginForm". Also, note that when the Controller calls the method "execute", it is also passing the CommandContext to the method so we have stuff to work with.
class LoginCommand extends Command {
public function __construct( ){ }
function execute ( CommandContext $context ){
if( $context->get('login_user_name') == 'demo' ){
$this->view->setMessage('Success is true!');
return true;
}
return false;
}
function getLoginForm( CommandContext $context ){
$this->view->setMessage('Second sucess is even more true!');
return true;
}
}
You seem confused.
AJAX requests are separate requests for a webpage, nothing you did in the index.php on the server side will be available in the subsequent requests (except for any variables in the session). It works like this:
Request is sent for index.php from the browser
Server runs index.php (storing user_id in the session) and returns the HTML output to the browser at the end, the PHP script finishes and all resources are freed.
User clicks on button, creating a new request for another PHP file, say ajax.php
Server runs ajax.php and returns whatever is output to the browser. Again the PHP script finishes and all resources are freed.
Another way to think about this: From the server side, an AJAX request is almost the same as if you'd just pointed your browser to ajax.php directly.

php session variable problem when unset

i have made a function to set a session variable $_SESSION['flash'] in order to store a message between page
function setFlash($string,$type="info") {
switch ($type) {
case "warning":
$_SESSION['flashtype'] = "warning";
break;
case "error":
$_SESSION['flashtype'] = "error";
break;
case "info":
$_SESSION['flashtype'] = "info";
break;
default:
$_SESSION['flashtype'] = "info";
break;
}
$_SESSION['flash'] = $string;
}
and a function to print this message
function printFlash() {
echo $_SESSION['flash'];
unset($_SESSION['flash']);
}
i call this function at the top of every page (naturally after session_start)
the problem is that it doesn't print nothing, but if I comment " unset($_SESSION['flash']);" it prints the message in every page.
how can i solve?
Solved sorry my fault.
my page is something like this
include "func.inc.php"
session start
function editSomething {
that call setFlash()
}
include "template.php" (where printFlash() is called)
now i put printFlash directly in my page and works..bah strange...what's my mistake?
On every page this is what happened:
Make a session
Display flash
Delete flash
Create 'flash' with value
You have to move Create before display.
(it's also not very usefull because you do not transmit 'flash' (it's delete right after been created)

Categories