Strange behavior with flashdata in codeigniter - php

I have found very strange behavior of "if" condition and session flashdata in codeigniter,
public function edit_equip($equip_id, $company_id) {
$this->data['section_title'] = 'Edit Equipment';
$this->data['equip_detail'] = $equip_detail = $this->common->select_data_by_id('equipment', 'id', $equip_id, '*', array());
if (empty($equip_detail)) {
$this->session->set_flashdata('error', 'Error Ouccrred. Try Again!');
redirect('Company/equipment/' . $company_id, 'refresh');
}
//some other code
$this->load->view('company/edit_equip', $this->data);
}
this is a function of my Equipment class. Now when I call below url like,
http://localhost/scale/Equipment/edit_equip/1/2
then edit view will open correctly. but now when I press F5 button or browser refresh button then it is showing "Error Ouccrred. Try Again!" flash message which I have set in above if condition. I am not understand why this is happening, because $equip_detail contains data and I have also try to die in it but it is not going into if which is correct so why only $this->session->set_flashdata('error', 'Error Ouccrred. Try Again!');
is providing effect?
in conclusion my code is not running if block but if i press F5 or browser refresh button after first time my view is loaded it is showing me error message which is set in if condition, but my code is not going to it otherwise it has to redirect but it is loading view page with flash message.
I have only set this flash message at only one place as per above code. I am using codeigniter 3.1.6
Please can anyone explain me this?

This isn't the solution, but more of an investigation to satisfy yourself how things are working...
So when things go "screwy", its always a good time to go back to basics. So seeing as you are so convinced your code is executing correctly but giving you unexpected results here is some test code just to check out the behavior of flashdata.
Flash_session_test.php
class Flash_session_test extends CI_Controller
{
public function __construct()
{
parent::__construct();
$this->load->library('session');
$this->load->helper('url');
}
public function index()
{
echo "This is " . __METHOD__;
$this->test_display();
}
/**
* Mockup code derived from sample code
* to test the behavior of the flash data.
*
* #param $equip_id
*/
public function edit_equip($equip_id)
{
echo "This is " . __METHOD__;
// Set up our Fail / Pass for the If statement below.
if (isset($equip_id)) {
if ($equip_id == 'fail') {
// Create a Fail Condition
$equip_detail = null;
} else {
// Create a Pass Condition
$equip_detail = array('fred' => 1);
}
}
// The code we are testing.
if (empty($equip_detail)) {
$this->session->set_flashdata('error', 'Error Occurred. Try Again!');
// Redirect and display the flashdata error message
redirect('/flash_session_test', 'refresh');
}
$this->test_display();
}
/**
* Our Test "View" put here for simplicity
*/
public function test_display()
{
echo '<br>';
echo '<a href="/flash_session_test/edit_equip/pass" >Click here to Create a PASS</a>';
echo '<br>';
echo '<a href="/flash_session_test/edit_equip/fail" >Click here to Create an ERROR</a>';
echo '<br>';
echo '<br>';
// Only display the message if we have one
$error = $this->session->flashdata('error');
if ($error === null) { // If null, then It doesn't exist
echo '<div style="color:green">';
echo "Not An Error in Sight!";
echo '</div>';
} else {
echo '<div style="color:red">';
echo $this->session->flashdata('error');
echo '</div>';
echo "Now Refresh the page!";
}
}
}
Note: This will run standalone, without relying on your existing code.

the CI manual says:
CodeIgniter supports “flashdata”, or session data that will only be
available for the next request, and is then automatically cleared.
F5 is sending a new request, so flashdata is cleared

Don't use $this->session->set_flashdata(), use $this->session->mark_as_flash() instead, it worked for me!

Related

PHP Rest API Endpoint Function Will Echo Stop Further Processing

class REST {
// this section is from http://www.tutorialsface.com/2016/02/simple-php-mysql-rest-api-sample-example-tutorial/
public function response($data,$status){
$this->_code = ($status)?$status:200;
$this->set_headers();
echo $data;
exit;
}
}
class API extends REST {
private function create_booking(){
if($this->get_request_method() != "POST"){
echo $this->response('Method Not Acceptable',406);
}
/*pseudocode for processing data if method is POST*/
Find whether record exists.
If exist {
set $message = "record found"
} else {
If not exist, insert record
set $message = "record inserted"
}
echo $this->response($message,200);
}
}
I would like to know, if let's say I have an API end point using the above method, when user is not using POST, will system stop processing after echo the error 406, or it will still continue after existing IF statement.
I have users submitting a new booking to this end point several times due to server did not response a message. End up I have duplicate bookings in my database.
What could lead to such incident?
Yes, it will execute further, but you need to stop further execution. You can add a simple return in your method below the echo message to quit the method:
if($this->get_request_method() != "POST"){
echo $this->response('Method Not Acceptable',406);
return;
}

Store value of session key then unset?

I'm trying to imitate the behavior of flash messages in native PHP, for one-time display of error messages.
Displaying the Login page:
public function showLoginAndRegistrationPage()
{
$session = new Session();
$data['errors']['login']['account'] = $session->getFormErrorFlashData('login', 'account');
$this->viewPresenter->display('basic', 'customer/login-registration', $data, 'Login/Register');
}
Verifying the login details:
public function processLogin()
{
// Some code
$session = new Session();
if($this->formInputFilter->isValid()) {
// Some code
if(true) {
// Some code
} else {
$errors = array(
'account' => 'Account does not exist.'
);
$session->setFormErrorFlashData('login', $errors);
header('Location: /login');
}
} else {
header('Location: /login');
}
}
For setting the error messages:
public function setFormErrorFlashData($form, $errors = array())
{
foreach($errors As $field => $message) {
$_SESSION['errors']["{$form}"]["{$field}"] = $message;
}
}
For getting the error messages stored in the session:
public function getFormErrorFlashData($form, $field)
{
if(isset($_SESSION['errors']["{$form}"]["{$field}"])) {
$message = $_SESSION['errors']["{$form}"]["{$field}"];
unset($_SESSION['errors']["{$form}"]["{$field}"]);
return $message;
}
}
Basically for an invalid attempt, after redirect, it should now display the 'Account does not exist' message, and then when the user refreshes the page, it should no longer be there.
What happens is when I comment out the unset() line in getFormErrorFlashData(), the $_SESSION contains the errors, but of course as expected they do persist even after countless page refreshes.
But when it's not commented out, I get a NULL. It seems that $message is also unset, even after attempting to store in it the value of that session key.
I have a bootstrap file that has the session_start() line, it's loaded for every page so I doubt that's the cause?
UPDATE:
index.php (bootstrap file)
<?php
session_start();
date_default_timezone_set('Asia/Taipei');
require_once 'core/Autoloader.php';
use core\Autoloader As Autoloader;
use core\Router As Router;
use core\Dispatcher As Dispatcher;
spl_autoload_register('core\Autoloader::loadClass');
$request_uri = trim($_SERVER['REQUEST_URI']);
$router = new Router();
$route = $router->handleRequest($request_uri);
if (!$route) {
require_once ('./views/errors/404.php');
} else {
$dispatcher = new Dispatcher($route);
$isDispatched = $dispatcher->dispatch();
if (!$isDispatched) {
echo '<div>' .$route['class'] .'/' . $route['action'] . ' not found </div>';
require_once ('./views/errors/404.php');
}
}
I've found the culprit.
When I traced the request logs, showLoginAndRegistrationPage() was being called twice because I didn't realize I also had a .js file attached in the html file with a submit event handler that gets fired too, thus the double page requests.
I removed the file and now it's working.
Thanks for the help!

Codeigniter form validation: run function is not working

I am working with a from in codeigniter where program control is moving to submit function which I can test by adding the die function. Although set_rules() are successfully checking the entry but the control is not being passed to if($this->form_validation->run()) this function. Its getting out of it and running the die function dead-2 that I have kept to test the program flow.
Below is my controller code
function addPost(){
$this->load->library('form_validation')
if($this->admin_lib->checkMembers()){
if($this->input->post('submit')){
//validate the form
$this->form_validation->set_rules('country','Country','required');
$this->form_validation->set_rules('city','City','required');
$this->form_validation->set_rules('area','Area','required');
$this->form_validation->set_rules('street','Street','required');
$this->form_validation->set_rules('house_no','House number','required|numeric');
if($this->form_validation->run()){
//add to database
die("dead-1");
if($this->members_model->addPost())
{
echo "Successfully made one entry will be validated";
}
else{
echo "Error uploading the datas into database Please contact us about the problem";
}
}
die("Dead -2");
}
$data['content']=$this->load->view('members/addPost','',true);
$this->load->view('members/home',$data);
}
else{
echo "you dont have preveledge to access this page ,<br/> LOgin link rakhnu paryo ";
}
}
Your code will always call die("Dead -2") because it isn't part of an Else block. It's sitting directly below your If statement which means, regardless of what happens with your form validation, it will always die.
Consider changing your code to the following
if($this->form_validation->run())
{
//add to database
die("dead-1");
if($this->members_model->addPost())
{
echo "Successfully made one entry will be validated";
}
else
{
echo "Error uploading the datas into database Please contact us about the problem";
}
}
else
{
die("Dead -2");
}

Phalconphp flash SESSION messages after redirect doesnt show

I have a prepared AccessControll plugin for cheking access to resources and actions, so when i set flash message in plugin and then redirect to the login page the message doesn't show.
I have in access control plugin lines:
if(!$role || !$moduleAcl || !$moduleAcl->isAllowed($role,$controller,$action)){
$this->flash->warning('Nemáte oprávnění na provedení této akce.');
if(!$moduleAcl->isAllowed($role, 'index', 'index')){
$auth = \Core\Auth::logout();
}
else {
return $this->response->redirect($module.'/');
}
}
In, base controller i have a line:
if(!$identity)
{
return $this->response->redirect('manager/auth/');
}
Can someone tell what i'm doing wrong ?
In you controller just put
$this->view->disable();
before
$this->redirect();
It will help. That was unexpected for me as well some time ago ;)
I made a solution for that:
<?php
namespace Core\Http;
/**
* Description of Response
*
* #author softdream
*/
class Response extends \Phalcon\Http\Response {
//put your code here
public function redirect($locationPath = null, $baseUrl = null, $statusCode = null) {
if($statusCode){
$this->setStatusHeader($code);
}
if(substr($locationPath, 0,1) === '/'){
$locationPath = substr($locationPath, 1);
}
header("Location: ".$baseUrl.'/'.$locationPath);
exit;
}
protected function setStatusHeader($code){
header("HTTP/1.0 ".$code);
}
}
This will resolve all problems with showing flash message after redirect, the problem is that phalcon doesn't stop script when redirect, so it can render some data before redirect.
I think that disabling view is not a good and cleaned solution how to do it :)

codeigniter flashdata not clearing

I'm a newbie to codeigniter and I'm creating a project in which users are created and managed. here I'm using flashdata to display the temporary messages like "user created",etc.,
My code to set flash data is
$this->session->set_flashdata('message', 'User Created.');
In my view I called it as
$this->session->flashdata('message');
My problem is that when the user is created,flashdata is displayed and when i click home link the flash data is still available but when i click refresh/home again it disappears. I want it to be cleared when i click the home link for the first time itself. Is there a way to code it??.
Flashdata will only be available for the next server request, and are then automatically cleared.
if($user_created)
{
$this->session->set_flashdata('success', 'User created!');
redirect('login');
}
else
{
redirect('register');
}
if you want to clear set_flash in controller or another view file, then you can use this simple code.
$this->session->set_flashdata('error', 'User not found...'); //create set_flash
unset set_flash
//echo "<pre>"; print_r($_SESSION); die; //for check
if(isset($_SESSION['error'])){
unset($_SESSION['error']);
}
You should redirect after user created. Then when next time you click on home link it will not appear, try this,
$this->session->set_flashdata('message', 'User Created.');
redirect(base_url().'home.php');// you can change accordingly
The flashdata is supposed to display once.
And it gets disappears on page refresh.
So, if you redirect the page to another, it should work.
If you do not refresh the page, you can do it through jQuery.
Say your div displaying flash:
<div id="flash-messages">Success Message</div>
Write jQuery:
<script type="text/javascript">
$(function(){
$("#flash-messages").click(function(){$(this).hide()});
});
</script>
You must redirect the page somewhere after $this->session->set_flash('item','value');
Example:
if ($this->form_validation->run() == FALSE){
$this->session->set_flashdata('error',validation_errors());
redirect(base_url().'user/login');
}
else{
$this->session->set_flashdata('success','Thank you');
redirect(base_url().'user/login');
}
Usually developer make a mistake when they submit data to same page. They set flash data but forget to redirect.
You can use a Ajax framework for automatically hide the flash message.Also their contains all of the flash operation.
You can get more information from here.
https://github.com/EllisLab/CodeIgniter/wiki/Ajax-Framework-For-CodeIgniter
If nothing else helps, just extend the Session library and add a clear_flashdata function.
<?php defined('BASEPATH') or exit('No direct script access allowed');
// application/libraries/Session/MY_Session.php
class MY_Session extends CI_Session
{
public function __construct(array $params = array())
{
parent::__construct($params);
}
/**
* Clear flashdata
*
* Legacy CI_Session compatibility method
*
* #param mixed $data Session data key or an associative array
* #return void
*/
public function clear_flashdata($data)
{
$this->set_userdata($data, null);
}
}

Categories