I have a PHP website with a custom page routing system.
A php script checks the requested uri and uses a switch case to determine which page needs to be loaded. Each page has its own $page_id.
Here's a simplified version.
$page_uri = //code that extracts the relevent part of the uri
switch($page_uri){
case 'about':
$page_id = 'about';
break
case 'products':
$page_id = 'products';
break;
default:
$page_id = '404';
break;
}
include 'sessions.php'; //explanation about this after the code
include $page_id; //code that loads the page based on the $page_id
For one of the site's function, I need to know the $page_id of the previously visited page.
I am using sessions for this.
session_start();
$previous_page_id = $_SESSION['current_page_id'];
$_SESSION['current_page_id'] = $page_id;
I am therefore storing the previous $page_id which is stored in a session variable in the $previous_page_id variable before the session variable gets updated to the current $page_id.
The problem is that it doesn't work. The $previous_page_id is always equal to the default $page_id which is 404. I know the actual routing function works because the right page gets loaded and if I echo the value of the session right after storing it it's correct.
I've noticed that I can get the correct $previous_page_id if I put the following part before everything else.
session_start();
$previous_page_id = $_SESSION['current_page_id'];
What am I missing? Can you think of anything wrong with my code or logic? Is there some weird quirks I should be aware of when it comes to PHP sessions?
Thanks.
Update
It seems adding session_start(); echo $_SESSION['current_page_id']; at the top of the page makes the value stick. Otherwise by the time I get to transfering the session value to the $previous_page_id in sessions.php, the session value has changed to 404.
Can anyone make sense of that?
The problem was coming from a missing favicon.ico file which was triggering a 404 page load after each page load.
You need to put the session_start(); at the beginning of the script, that way the session is started (and available) when you need it in your big switch statement.
You have forgot to add .php extension to your include (+ some smaller things). And remember that session_start must be called at beggining, before any use of it. So you need to call it on beggining or include sessions at beggining.
So it should look like:
session_start();
$page_uri = //code that extracts the relevent part of the uri
switch($page_uri){
case 'about':
$page_id = 'about';
break;
case 'products':
$page_id = 'products';
break;
default:
$page_id = '404';
break;
}
$previous_page_id = $_SESSION['current_page_id'];
$_SESSION['current_page_id'] = $page_id;
include $page_id . '.php'; //code that loads the page based on the $page_id
session_start();
$previous_page_id = $_SESSION['current_page_id'];
$_SESSION['current_page_id'] = $page_id;
I don't really get this. $previous_page_id and $page_id are equal.
You are setting them to be equal.
You should set it after the switch statement as follows:
$page_uri = //code that extracts the relevent part of the uri
if (file_exists('sessions.php')) {
include 'sessions.php';
} else {
trigger_error("'sessions.php' not found", E_USER_ERROR);
}
switch($page_uri) {
case 'about':
$page_id = 'about';
break
case 'products':
$page_id = 'products';
break;
default:
$page_id = '404';
break;
}
if (isset($_SESSION['current_page_id'])) {
$_SESSION['current_page_id'] = $page_id;
} else {
trigger_error("'current_page_id' key not set", E_USER_ERROR);
}
if (isset($page_id)) {
include $page_id;
} else {
trigger_error("'page_id' not set", E_USER_ERROR);
}
with sessions.php being:
$ss = session_start();
if (!$ss) { trigger_error("Session couldn't be started", E_USER_ERROR);
if (isset($_SESSION['current_page_id'])) {
$previous_page_id = $_SESSION['current_page_id'];
} else {
trigger_error("'current_page_id' key not set", E_USER_ERROR);
}
Related
This is how I have my files setup:
INDEX.PHP:
include($sys->root_path.'sections/start.php'); // Includes everything from <html> to where we are now
if (isset($_GET['page'])) {
$page = $_GET['page'].'.php';
} else {
$page = 'index.php';
}
if (isset($_GET['cat'])) {
$cat = $_GET['cat'];
} else {
$cat = '';
}
include($sys->root_path.'/content/'.$cat.'/'.$page);
include($sys->root_path.'sections/end.php'); // Includes everything from here to </html>
To view this page, I visit: example.com/index.php?cat=red&page=car
This will show me a page with the content of the file at:
/content/red/car.php
The problem I am having is that I want to specify a title, meta description, etc. for each page, and this is outputted to the page in start.php- before any specific data for this particular page is called.
What I was hoping to do is something like this:
/CONTENT/RED/CAR.PHP:
<?php $page_title = 'Title of the page'; ?>
<p>Everything below is just the page's content...</p>
How can I use this page specific data in the <head> of the site, when all that data is grabbed before the contents of this specific page?
You could do something like:
switch($_GET['page']) {
case 'car':
// Here you could have another conditional for category.
$page_title = 'Title of the page';
break;
// Other cases.
}
include($sys->root_path.'sections/start.php');
And in start.php you could have something like:
<title><?php echo $page_title; ?></title>
I must advise against that way of including content. It is insecure. Someone could browse your server files or include something you don't want included. One should never include files that way (through get variables) unless one always filter that variable through a regular expression or something else.
The correct way to do what you're trying to do is with a database and
apache url_rewrite. My answer is just a fix for your problem.
Step 1
Include start.php below the if statment, this way when you include start.php you already know which page you need, like this:
if (isset($_GET['page'])) {
$page = $_GET['page'].'.php';
} else {
$page = 'index.php';
}
if (isset($_GET['cat'])) {
$cat = $_GET['cat'];
} else {
$cat = '';
}
include($sys->root_path.'sections/start.php');
Step 2
Now, inside the start.php use a switch:
<?php
switch ($cat) {
case "blue":
$title = "The car is $page";
break;
case "green":
$title = "The car is $page";
break;
case "red":
$title = "The car is $page";
break;
default:
$title = "Welcome to ...";
}
?>
<!DOCTYPE html>
<head>
<title><?php echo $title ?></title>
</head>
etc...
My recommendation would be to use an MVC approach with either a function to pass the parameters or OOP with a setter function.
I have created an index.php that serves as a template with a content box. I also have home.php, about.php, and contact.php which only contain the content to fill that content box. This is the code I use to embed pages into that content box:
<?php
if(!$_GET[page]){
include "home.php"; // Page to goto if nothing picked
} else {
include $_GET[page]."php"; // test.php?page=links would read links.php
}
?>
The home page works fine but I am not sure what code to use in the main menu to link to the other pages. I am having a very hard time getting an answer, so I think I may be searching with the wrong terms, which is why I am asking here.
On the main menu for the website, what code do I use in the links so that they get home.php, about.php, or contact.php?
I made the following test:
$page = "test.php?page=links";
$link = explode("=", $page);
echo $link[1].".php"; //gets links.php
So, your code should looks like:
<?php
if(isset($_GET[page])){
$page = $_GET[page];
$link = explode("=", $page);
include $link[1].".php"; // test.php?page=links would read links.php
} else {
include "home.php"; // Page to goto if nothing picked
}
?>
Saludos.
if(!$_GET[page]){
include "home.php"; // Page to goto if nothing picked
} else {
include $_GET[page].".php"; // test.php?page=links would read links.php
}
It was just missing the '.' before the 'php'.
You should use Quotes for arrays though to avoid a Notice (Undefined constant)
Be careful though, you should verify that $_GET['page'] only contains sites you want to make accessible. Otherwise an attacker could just read any file on your server.
if(array_key_exists('page', $_GET)) {
$page = preg_replace('~[^a-z]~', '', $_GET['page']);
include __DIR__ . '/' . $page . '.php';
} else {
include __DIR__ . '/home.php';
}
Better solution (but you have to manually add all the pages):
$page = (array_key_exists('page', $_GET) ? $_GET['page'] : 'home');
switch($page) {
case 'about':
case 'links':
case 'whatever':
include __DIR__ . '/' . $page . '.php';
break;
default:
include __DIR__ . '/home.php';
break;
}
About
?<key>=<value> in the url.
You look up a value in the $_GET-array by using the key.
I usually use this code below to include the page that I need into the body of my website to include the page when clicking on a link.
<?php
switch($_GET['page']){
case '1':
if(file_exists('main.php'))
{
include_once('main.php');
break;
}
default:
include_once('main.php');
break;
}
?>
but then I have to change this everytime i add a menu item by adding a case '2' ... etc
and now my question can this be written shorter/dynamically so that i just can add a link without having to change the piece of code everywhere?
ps: i did made it a little bit shorter.. but its still not good enough i think..
i also want to add this: i get my links from a ini file. i place it in there like this:
[navigation]
main.php = "Home"
if (!isset($_GET['page'])) {
$_GET['page'] = 'main.php';
}
switch ($_GET['page']){
case 'main.php':
case 'about.php':
case 'portfolio.php':
case 'tips.php':
$file = $_GET['page'];
break;
default:
$file = '404.html';
}
include_once $file;
is it possible to get this too from the ini file?
Try this:
$page = isset($_GET['page']) ? $_GET['page'] : "main.php";
if( file_exists($page)) include($page);
else include("404.html");
I'm working on a website and this is what I have for my index.php:
<?php
$p = $_GET['p'];
$pages = array('home', 'culture', 'design', 'art', 'about');
$path = 'http://localhost:8080/projects';
include('header.php');
if(!isset($p) || !in_array($p, $pages)) {
include('header.index.php');
include('content.index.php');
} else {
switch($p) {
case "home";
include('header.home.php');
include('content.home.php');
break;
case "culture";
include('content.culture.php');
break;
case "design";
include('content.design.php');
break;
case "about";
include('content.about.php');
break;
case "art";
include('content.art.php');
break;
default:
include('content.index.php');
break;
}
}
include('footer.php');
?>
I get the following error:
**Notice: Undefined index: p in C:\wamp\www\projects\index.php on line 3
Call Stack
# Time Memory Function Location
1 0.0523 680200 {main}( ) ..\index.php:0**
When you assign p initially, p is not set in $_GET
So you can do this
$p = isset($_GET['p']) ? $_GET['p'] : null;
If you don't care about notices, You can disable them in your php.ini by changing error_reporting to E_ALL & ~E_NOTICE, however I wouldn't recommend it
The switch statement you have is somewhat bogus, especially as you already have the $page array. You actually want to verify if the page exists or load the index page (probably?):
$p = isset($_GET['p']) ? (string) $_GET['p'] : NULL;
$pages = array('home', 'culture', 'design', 'art', 'about');
$path = 'http://localhost:8080/projects';
if (!in_array($p, $pages)) {
$p = 'index';
}
// include $p based on $path
However, you still have the problem with the header. So this is the lesson: make the header part of every include. You can stack as many includes as you like, just take care that every include contains it's correct header. Then you're done. And you won't see any warnings.
So the code after following what #hakre suggested should look like this:
$p = isset($_GET['p']) ? (string) $_GET['p'] : NULL;
$pages = array('home', 'culture', 'design', 'art', 'about');
$path = 'http://localhost:8080/projects';
include('header.php');
if (!in_array($p, $pages)) {
$p = 'index';
include('header.index.php');
include('content.index.php');
}
Thanks #hakre for your help..
Just a suggestion maybe try !empty()
if(!empty($p) || !in_array($p, $pages)) {
include 'header.index.php';
include 'content.index.php';
}
This is NOT an error. As the log claims this is a NOTICE. It is meant to inform you about a potential problem, but does not keep the script from being executed.
In this case the interpreter tells you that the array $_GET does not contain an element with index 'p'. It is not initialized, probably cause it has not been specified in the request in this case.
Try to test first if the element exists before you try to access it. Use isset() for this.
I have setup a new server and copyed my website on to it and the follow dont work (?p=home) includes pages.
Code:
if(isset($HTTP_GET_VARS['p']))
{
$page = $HTTP_GET_VARS['p'];
}
else
{
$page = 'home';
}
switch($page)
{
case 'home':
require('home.php');
break;
case 'login':
require('login.php');
break;
default:
echo('Error: There is no file on this server with that name');
}
On the other webhost it was on it worked fine am think in that it is a php.ini config file need editing can anyone help me?
Use the $_GET array instead of $HTTP_GET_VARS. The latter one is deprecated and probably disabled due to register_long_arrays.
This must do the trick :)
if(isset($_GET['p']))
{
$page = $_GET['p'];
}
else
{
$page = 'home';
}