how to display the content before exit() in php? - php

I'm using codeigniter. And in one of my admin controller, after a admin was logged in, I wanted to create a switch to check his admin level. If his level is below a certain number, he cannot view a certain page. And instead, a restriction notice page will be loaded and then the page will stop loading.
function add_user() {
$this->set_admin_level(9);
// stuffs
}
private function set_admin_level($level){
if ($this->session->userdata('admin_level') < $level ) {
$this->load->view("admin/restriction");
exit();
}
}
I tried exit() and die(), but both of them just killed the entire page without displaying anything. I know that I can do this with an if and then redirect method, but I wanted to know if I can do it the previous way.

try this:
private function set_admin_level($level){
if ($this->session->userdata('admin_level') < $level ) {
return $this->load->view("admin/restriction");
}
}

die or exit will stop all PHP processing.
If you don't want an error message on a blank page, you will need a page/view to display the error message. Then you either redirect the user to that page, or run the page in PHP before exiting, for example using $this->load->view.
Either way, you need to create the page or the view first, since you cannot display something by doing nothing.
And before displaying the actual error page, please set the HTTP 403 header to indicate to browsers and search engines that this is an Access Denied error page, not a normal page.

Related

Redirect user to login form

Dears,
I create a function that permits to redirect the user to a specific URL. The function is named redirect and user the header function:
public function redirect($url, $code = null)
{
if($code == 301){
header("HTTP/1.1 301 Moved Permanently");
}
header('Location: '.Router::url($url));
die();
}
I use it to protect some pages to be reachable for a none authenticated users. I put a condition, permits to check if user is logged, if not will be redirected to the login form:
if(!$this->Session->isLogged()){
$this->redirect('users/login');
}
The function isLogged is:
public function isLogged()
{
return isset($_SESSION['User'][0]->id);
}
I tried to do the same things, for BO admin pages and it works. But I need to protect the front pages too. The problem is when I try to access to a front-page, I'm redirect to the login form, but I got the ERR_TOO_MANY_REDIRECTS error on my Chrome browser.
I tried to delete cookies, but I have the same problem. When I try to ignore the following line, I can see my login form:
if(!$this->Session->isLogged()){
$this->redirect('users/login');}
You should not attempt to redirect to login in case you are already on that page.
if(!$this->Session->isLogged() && !$this->isLoginPage()){
$this->redirect('users/login');}
}
PHP raises this error in two main cases:
Infinite redirecting: you're probably invoking your mentioned function for an infinite number of times
Too many redirects in a row: the "Header" native PHP's function handle only one header per instance.
In a nutshell: the error related to your case is quite surely related to an infinite redirect, otherwise there could be other redirects invoked moreover the wanted one in the page where you're calling your function.

PHP die() shows brief white screen

I'm using a redirect function to redirect visitors to a certain page when they don't have access to the current page. The function is as follows:
$user->redirect('www.google.com');
die();
The redirect function links to:
public function redirect($url="",$time=0) {
header("Refresh: $time; url=$url");
}
Whenever you get redirected you briefly see a white page followed by the page you get redirected to. I'm assuming the white page is caused by die().
I don't like it and I really want to get rid of this.
The problem is not related to the die() call, but that you are sending the wrong header to handle a redirection.
Instad of doing
public function redirect($url="",$time=0) {
header("Refresh: $time; url=$url");
}
do:
public function redirect($url) {
header("Location: $url", true);
}
Or even:
public function redirect($url, $temporal = false) {
header("Location: $url", true, $temporal ? 302 : 301);
}
With this you are sending a status code "301" or "302", to indicate that the redirection is either temporal, or a permanent. Defaulting to a permanent redirect, since temporals are very rarely useful (although in your case, being a redirection because of permissions, a temporary redirection might be in order)
(I also removed the default value for $url, because it doesn't make much sense to redirect to an empty url)
Instead of using a 'Refresh:' header, you can just use 'Location:'. This way, the page does not have to be refreshed and will probably result in your desired behaviour.
public function redirect($url="/") {
header("Location: $url");
}
edit: added default $url '/' so that if no url was given it redirects to homepage
I'm disapointed to the prev. posts. It is about the die() !
When sending a header the browser takes a little time to take action. Between this time the php process then calls die() before you are redirected. This is asyc. Location and Redirect
So it shows you a black page and then you/visitors get redirected.
Good: setting die() to end the process to avoid futher actions inside your program
Bad: The blank page first.
This is depending on your enviroment of your browser! E.g: a very slow workstation will show you this behavior and you have to care about. Imagin the browser does know about header redirections (Today it (mostly) doesnt exists anymore)
To give the browser a change to take action, use this:
function someaction() {
// ...
$user->redirect('www.google.com');
// which give the time for the browser
// without further execution of your code
return;
}
In this case the visitor stays as long on the current page until the browser knows about headers or the cpu is slow but will take action when it is able to take action.

redirection without reloading the whole page

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.

PHP Redirect Headers Best Practices

I'm creating a PHP CMS and have some system pages like a 404 page, a maintenance page, and an unauthorized access page. When Page A isn't found, the CMS will redirect to the 404 page; if the user doesn't have access to Page B, it will redirect to the unauthorized access page, etc.
I'd like to use the proper status code in the header of each page, but I need clarification on how to handle the header/redirect. Do I put the 404 header on Page A and then redirect to the 404 page or do I put the 404 status on the 404 page itself? Also, if the latter is the correct answer, what kind of redirect should I use to get there, a 301 or a 302?
If a user arrives on page A and that page doesn't exist, then do not redirect : just send a 404 error code from page A -- and, to be nice for your user, an HTML content indicating that the page doesn't exist.
This way, the browser (and it's even more true for crawlers ! ) will know that the page that is not found is page A, and not anything else you'd have tried to redirect to.
Same for other kind of errors, btw : if a specific URL corresponds to an error, then, the error code should be sent from that URL.
Basically, something as simple as this should be enough :
if (page not found) {
header("404 Not Found");
echo "some nice message that says the page doesn't exist";
die;
}
(Well, you could output something nicer, of course ; but you get the idea ;-) )
I'm not sure if the redirecting is the best way for doing this. Id rather use some built in functionality that is included into the project.
If the data is not found, do not redirect the user to another page, just send him an error message, like Hey, this site does not exists! Try an other one and so.
And not at the end, you should build into the code, the code-part from the answer of Pascal Martin.
I would do this into a function, and call it from a bootstrap or something with a similar behavior.
function show_error($type="404", $header = true, $die = false)
{
if($header)
header("404 Not Found");
echo file_get_contents($type.'.php');
if($die) die; //
// and so on...
}

Sending Error Messages to Another Page?

When a user creates their own account, if there is an error I want to redirect them to the same page but display the errors at the top.
What's the best way to do this?
Structure your page as follows (in rough pseudo-code)
if (doing a post) {
process input
if (post is ok) {
redirect to success page
} else {
build error messages
}
}
if (error messages available) {
display errors
}
display form(filled in with previously submitted values)
i like to create a function named set_feedback() that sets the error in a session variable. then i have this other function get_feedback() that retrieves the information and unset the variable.
I save the error into the session and remove it once it was rendered. As you will probably abort the pages execution on a redirect it will never reach the code responsible for rendering thus leaving it in the session.

Categories