I have a few pages that require login, so all controllers that link to these pages start with
$this->checkSession();
//...rest of the code
CheckSession should verify the session is still live, otherwise display a message and stop the execution of the rest of the code in the controller:
function checkSession()
{
if (!$this->session->userdata('is_logged_in'))
{
//the session has expired!
$data['main'] = 'confirmation_message';
$data['title'] = "Session expired";
$this->load->vars($data);
$this->load->view('template');
exit();
}
}
.
I was expecting these instructions to happen in sequence, but I only get a blank page.
How can I make sure exit() gets executed only after all views are loaded?
In this case Pedro is correct. If they are not logged in just redirect them, it's even better if you can use Public/Admin named base controllers to stop you having to do this in each separate protected file.
Generally speaking though, if you use exit() it will stop the Output library for running. If you just want to stop the current controller from executing but allow output of the controller you can use return in exactly the same way.
function checkSession()
{
return (bool) $this->session->userdata('is_logged_in');
}
Then simply:
if(!$this->checkSession())
{
//the session has expired!
$data['main'] = 'confirmation_message';
$data['title'] = "Session expired";
$this->load->vars($data);
$this->load->view('template');
return;
}
exit() should only ever be used if you really want instant death of your application's execution for debugging, error reporting, etc.
In this case you should not use exit, what you should do if the session is not valid is redirect your app using example:
redirect('/init/login/','refresh');
I had a similar problem. Where I wanted to stop the user to due to no login. But I wanted to offer a list of links for them not simply redirect them to a login page. I am using CI version 1.7.2 and the $this->_output() $this->display->_output() and $this->output->_display() solutions did not work for me. I was however to get my results using the $this->output->get_output() function.
$this->load->vars($data);
$this->load->view('template');
die($this->output->get_output());
$this->output->_display();
exit();
Is the correct answer! Thanks to Sam Sehnert... It's hidden in the comments so thought I'd re-post.
I don't know enough about codeigniter's workflow but it seems to me that you want to redirect to the login page instead of trying to render it. Evidently, none of the code you supplied sends the template to the browser by the time exit() is called.
exit() cuts your scrip there and the actual _output() function of the controller is never called. What you need to do is add action in one of your controllers for example the user login screen and redirect there. You can use the flashdata function from the Session - http://codeigniter.com/user_guide/libraries/sessions.html to pass your message and then catch it inside your view and display it.
Another way which is not very smart but should work is to forcefully call the output function.
function checkSession()
{
if (!$this->session->userdata('is_logged_in'))
{
//the session has expired!
$data['main'] = 'confirmation_message';
$data['title'] = "Session expired";
$this->load->vars($data);
$this->load->view('template');
$this->_output();
exit();
}
}
Actually in the newest CI function to manually call output class is
$this->display->_output();
and don't be worried - it handles caching, content will also be properly gzipped if you set so in config
I usually add and extended controller with login logic that handles login functions, so that if a normal controller is one that is needing an auth then the login method is called automatically and the original content is not displayed. It's a good solution if you would like to stay on the page the user tried to access without redirecting (and then posting him back to the same page)
Put the code in a variable and write it.
$html = $this->load->view('template',null,true);
echo $html;
exit();
Related
I have one form in my view.php file. Its URL like https://example.com/members/view/1, https://example.com/members/view/2 etc. When I submit form its calling model through controller like below
public function insert_comments(){
$data=$this->input->post();
$this->load->model('work_model');
$result=$this->work_model->insert_comments($data);
if($result)
{
$this->session->set_flashdata('insert_comments','your comments succesfully');
$this->session->set_flashdata('succesfully','alert-success');
$this->load->view('add_coments');
}
else{
$this->session->set_flashdata('insert_comments','your comments failed');
$this->session->set_flashdata('succesfully','alert-danger');
$this->load->view('add_coments');
}
}
}
and model is like below
public function insert_comments($array)
{
return $this->db->insert('comments',$array);
}
Currently its working fine and on form submit its loding view called add_comments, instead I want reload/refresh current page. I am not able to get idea of how I can do it, let me know if someone can help me for do it.
Thanks!
According to this answer, in the controller you can use:
redirect($this->uri->uri_string());
use this :
redirect($_SERVER['REQUEST_URI'], 'refresh');
Whenever you are reloading or redirecting a page you should always use the redirect() method instead of loading a view.
Redirection basically uses the header() method of core PHP and redirection will never execute the code blocks written beyond the redirect() method. But in the case of loading the view, it can execute until the end of the code block.
In your code, replace the line $this->load->view('add_coments'); with the redirection to the desired controller
redirect('your-controller','refresh');
I hope that helps you.
I'd like to ask you how can I instead of $this->load->view('some_view.php') at the end of controller code, return user to page from where he invoked controller method? Simple return statement is not working.
ie.
public function someMethod($IDCustomer) {
$this->Some_modal->persist($IDCustomer);
// how to return to previous page instead of line after?
// i've used $this->load->view('someView.php');
}
This should help http://www.codeigniter.com/user_guide/libraries/user_agent.html
$this->load->library('user_agent');
if ($this->agent->is_referral())
{
echo $this->agent->referrer();
}
or straight PHP:
redirect($_SERVER['HTTP_REFERER']);
I've found answer on some thread.
In the page that you want to go back to you can do:
$this->session->set_userdata('referred_from', current_url());
Then redirect back to that page
$referred_from = $this->session->userdata('referred_from');
redirect($referred_from, 'refresh');
Tried return redirect()->to($_SERVER['HTTP_REFERER']); , this would work well.
In Codeigniter 4 You can use previous_url() function from url helper
find more https://codeigniter.com/user_guide/helpers/url_helper.html
I've tried header('location:'.$_SERVER['HTTP_REFERER']); and it's working quite well.
Just a one-liner plain old PHP code.
Use the REDIRECT_QUERY_STRING alternative of HTTP_REFERRER:
// set in session redirect back URL in your common is_logged_in function if user is not logged in
$CI->session->set_userdata('redirect_back', $_SERVER['REDIRECT_QUERY_STRING']);
// below code user after successful login in auth.php library
if($this->ci->session->userdata('redirect_back')){
$redirectBackUrl = $this->ci->session->userdata('redirect_back');
$this->ci->session->unset_userdata('redirect_back');
redirect(base_url() . $redirectBackUrl);
}
Here is my code in controller:
$newdata = array(
'uid' => $usern,
'ou' => $filter
);
$this->session->set_userdata($newdata);
$this->masterpage->view('User/homeuser');
And here is my code in views:
<?php
$user = $this->session->all_userdata();
if ($this->session->userdata('uid')=='') {
redirect('main/main', 'refresh');
}
?>
However when I type link: http://localhost/[system_name]/index.php/[controller_name]/index
(link to show when uid is null, the page should redirect to main)
Only blank page is appearing. It seems it didn't redirect to the main/main page. Can anyone help me ? Thanks.
You can not do redirect in views. Use controllers for this, so move your logic to check session data from view to the controller.
View is rendered at the very end of your request so if there is some output, php will not redirect you to anywhere. You see blank page probably because you turned off errors display, but I am sure if you check php error log you'll see there is an error "can not modify headers" or so.
If you deadly want to do redirect in views, use Javascript for that.
This is the most silly things I've done. I just forget to import session from library. So should in my public function I put this function.
$this->load->library('session');
This is what happen when you try to built two system simultaneously. Anyway thanks for the response and tried to solve it for me.
I have a framework and I think I'm following something like the MVC pattern: A framework (the model) an index page that controls the input (the controller) and the views pages (that are included inside main.php/the main html)
I read a lot about structure and logics, to write a good application. I read many comments like "Why are you outputting anything if all you are going to do is try and redirect the user to another page?". Well the answer is, the most common case: redirect after the user successfully logged in. Do I need to print something? Of course, the whole main page with a login form/post. How I'm supposed to do that redirection??
So I'm a bit confused about logics and structure of the application. How do you store all the output and do the header redirection without printing anything?
I was thinking about using javascript to do the redirection but I also read comments saying; "if you write good code (following a good logic/structre), you won't need to use hacks like javascript redirection". How is that even possible?
Because the php output_buffering should not be enabled.
I have the output_buffering enabled, and I can use header (after output) without any problem. If I use the javascript redirection the whole page reloads, but using header it just loads the content (the views content that are included in main.php).
So how do you do this without output_buffering?
If you want to redirect to a success page AND pass messages - say, after a successful login - an easy solution is to use "flash" sessions, where you store a message in a SESSION and then, as soon as it's used, you discard it. You don't need to sore anything in the output buffer for this.
This is a very basic example, but should give you the gist of it.
login.php
if($login_successful) {
// put your message in the session
$_SESSION['message'] = 'Login Successful';
// redirect to the success page
header('location: success.php');
}
success.php
<?php
session_start();
// check if $_SESSION['message'] exists
if(isset($_SESSION['message'])) {
// print the message
echo $_SESSION['message'];
// clear the session
$_SESSION['message'] = null;
}
Looks like you are mixing up some things here. What you are talking about are actually two different requests. Either the user wants to view the main page, or he wants to log in using that form on your main page. In your index.php you would have something like this (pseudocode):
if (isLoginRequest) {
// user wants to log in
if( validateLogin($loginFormData) ) {
redirect('successful');
} else {
displayLoginError();
}
} else {
// user wants to view main page
echo main.html
}
Update to answer the question in the comments: The better alternative would be to leave your form validation stuff in login.php and refer to that in your login form <form action="login.php" .... Then in your login.php you would have something like this:
if (loginSuccessful) {
redirect('success.php');
// no need to call die() or whatever
} else {
setFlashMessage('Login failed'); // set a flash message like timgavin described
redirect('index.php')
// also no die() or whatever
}
index.php then is responsible to display your main page and, if set, rendering the flash message from a failed login attempt.
Simple solution: Move the login post script from login.php to another file (login_post.php). The same for other scripts using header() after dom output. (no need to change the form action="")
In index.php:
$url = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
//some more security checks like esc_url() (non-php function)
if ($url == '/login') {
include('header_pages/login_post.php');
}
// all these includes before including main.php
// where views pages are included and the DOM output starts
Since header() is inside the post script, no more headers already sent errors (And output_buffering off, of course).
Same for logout page that is currently being included inside main.php
Thanks to the other answers, they helped me finding this solution.
I was wondering if what I'm using is safe:
Header(“Location:”);
I want to use it like this:
$user would be the user's session and 1 would mean admin. (Just an example.)
if($user != 1){
header("location: index.php"); }
So would this stop users from using that page, including downloading files, looking at the source of that page?
Because my adminpanel is going to have downloads and also inserts for the homepage..
If it's not safe to use, or the way I'm using it. What should I use instead?
Thanks.
header() is safe to use, but it means you have to include that call in every page you don’t want a non-admin to view.
A better way would be to have an authenticated user class that handles this. The benefit is, it DRYs your code.
<?php
class User
{
public function __construct()
{
// create your user however, i.e. fetch a record from your database
}
public function isAdmin()
{
return ($this->user->role == 'admin');
}
public function redirect()
{
header('Location: index.php');
exit;
}
}
And then use it in your code:
<?php
$user = new User();
if (!$user->isAdmin()) {
$user->redirect();
}
// continue with your page as normal; user here is an admin
Don't forget to die() after setting a Location header. That's what really stops people from using pages they're not supposed to.
you need put exit; after header
I feel like a better way would be to exit the page and prevent any other code execution. I'm not sure but a user might be able to ignore header redirect requests if they wanted to.
I've always just added a little snippet like "Sorry, this is only available to Administrators" and then just return; or exit;
edit: great googly moogly you guys are quick to the draw.
So what happens here is that by setting the Location tag, you are in fact giving back a HTTP 30x request, pointing the users browser to the new page. But it's in the hands of the browser to respect it. If the browser/user is malicious, he might just ignore it.
So you need to stop your output right after sending the Location header with die(). Than it's safe - the browser doesn't get any data it shouldn't get
use die(header("Location:...")); kill the page