Why not use included variables? - php

This is a rather basic question from a total php newbie so please be patient...
Why do most of the tutorials on php site maintenance tell you to use php includes but do not mention using variables?
Is there for example something wrong with this one:
<title><?php include 'includes/meta.php';
echo "$title_index";?></title>
<meta name="description" content=<?php include 'includes/meta.php';
echo "$desc_index";?>>
... if compared to this one:
<title><?php include 'includes/sitename.php';?></title>
<meta name="description" content=<?php include 'includes/description.php';>
?
In this particular case wouldn't it be easier to have all the SEO-relevant meta tag content in one file instead of spreading them or parts of them in separate files?
So back to the main point: is there some reason to avoid using a "master file" and thus spreading the included content into multiple files that are included in their totality here and there? Or have I just read the wrong articles?

It all comes down to preference. For example Wordpress defined methods in separate files, so it is closer to your first example, like
<?php include 'functions.php' ?>
<title><?= get_title() ?></title>
<body><?= get_body() ?></body>
etc.
In the closed-source projects I work in, we define all the variables like
<?php
$title = 'What';
$body = 'foo';
Then we include the template file from there.
include 'template.php';
Where template looks like
<title><?= $title ?></title>
<body><?= $body ?></body>
etc.
There are many ways to shoot yourself in the foot here. Choose your own adventure!

I believe they do it this way so your are dealing with variables instead of straight HTML. This way you have more control over how to display the information.

Related

PHP MVC different stylesheets, javascript files on every page

each one of my pages shares the common.css stylesheet but then nearly every other page has its own custom stylesheet and this is the same for javascript files.
My main template file is in this sort of format (obviously the real one has more html in it):
<html>
<head>
<title><?php echo $this->data['title']; ?></title>
</head>
<body>
<?php echo $this->data['content']; ?>
</body>
I was thinking of doing it this way:
When I create the view object in the controller I could add the required files (in an array) to the view object so then they could be accessed in the main template like $this->data['css'] and $this->data['javascript'] and I could loop through the arrays in the main template to output them in the <head> of the page.
Is this an okay way to do it or is it breaking some rules or bad practice? Thanks.
It is totally okay, though I advice you to write yourself a asset() method in order to prepend your basepath before filename [e.g. http://yoursite.com/web/] so your code is more portable an deploying is easier.
As Fluffeh said consider compressing your whole styles in a single file for better performance - check YUI compressor for example.

Converting a site from a PHP site into a full LemonStand e-commerce site

Brand new to LemonStand, and it's my front-runner for developing a client's web site.
This first candidate for utilizing LemonStand is a newly built web site I built in PHP.
I've got all of the non-e-commerce pages (things like about and contact) pulling from the LemonStand CMS.
But now I am trying to convert what were simple PHP includes to partials:.
Example:
<? include 'standard_include.php'; ?>
<? include 'header.php'; ?>
to LemonStand's
<? $this->render_partial('standard_include') ?>
<? $this->render_partial('header') ?>
I get an unhandled exception related to undefined variables:
This is what the beginning my page/template looks like
<?php
require_once('lib/php/configuration.php');
$pagetype = 'home';
$subpagetype = 'index';
$titleValue = 'Client Name';
?>
<!DOCTYPE html>
<html lang="en">
<head>
<title><?php echo $titleValue ?></title>
<? $this->render_partial('standard_include') ?>
</head>
<body>
<? $this->render_partial('header') ?>
Do the partials not render till later in the page load process (as compared to PHP includes)?
Am I utilizing partials incorrectly? If so, what do I do to put the PHP includes into the LemonStand backdoor system?
I've never used Lemonstand, but if its MVC works like other MVC systems, then you need to inject the variables needed by standard_include into the view. Something like:
$this->renderPartial('standard_include', array('pagetype'=>$pagetype, ...)) ?>
Otherwise the partial won't have access to the variables you defined in your parent template because the partial is rendered in a different context.
PHP include works differently. It just literally inserts the included file in place at that point before the script is executed.
I'm thinking the render_partial is happening after the pages start rendering, while the include happens prior, so it has a value for pagetype.
I'm thinking the solution is going to be to keep them includes. I just won't be able to have every file in their admin/backend system.
For common elements, the included templates with LemonStand don't seem to do anything but have them inline, which obviously isn't optimal for making a change across a site for something like a header or footer.

Something wrong with PHP include title

I'm relatively new at PHP and came across a slight problem.
I have a php page called info.php and use an included php file called components.php to pull functions that have html code in them that is then used in page.php (and other pages.) I put the title in a variable called $title and then reference that in my components.php, but for some reason the components.php doesn't recognize that as a title. Here's the code, and thanks for all help ( I know my description of the problem is hard. Let me know if you need any more info)
page.php
<?php
include("components.php");
$title = "This is my page Title!";
echo writeHeader();
?>
components.php
<?php
function writeHeader()
{
echo <<<HED
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>
HED;
echo $title;
echo <<<HED
</title>
HED;
}
?>
Good solution: Pass $title as a parameter to he function.
Less good solution: Declare $title as
global $title
within the function to make it belong to the global scope.
Without declaring it as global, it is a fresh new variable.
To summarize the comments:
Never use global! Anything a function/method depends on, should be passed as a parameter.
Never access $_GLOBALS! Same reason.
Disable register_globals! No GET-parameters should be automatically injected into your application.
Enable the highest error level! Write your application in such a way, that no error or warning gets printed.
Unfortunately, my question regarding PHP newbie practices is closed. But it provides some helpful hints.
In case you like it, click the re-open link.
A variable has a scope. When you declare it, unless it's global you can't use it in another scope. To do that you have to pass it to the other scope using parameters
Your code should be like that :
page.php
<?php
include("components.php");
$title = "This is my page Title!";
echo writeHeader($title);
?>
components.php
<?php
function writeHeader($title)
{
echo <<<HED
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>
HED;
echo $title;
echo <<<HED
</title>
HED;
}
?>
In your code example, you call the echo function at two places :
In your page.php file : This one does nothing
In your component.php : This one prints the text
The best practice is to group the prints into a single component called the "view".
If your view is the file called component.php then you should remove the first echo.

Creating a custom PHP template

I created a custom PHP templating system and the way I built it seems, well, inefficient. The three main goals for my template was to:
Pull all site-wide HTML elements from a template.tpl include.
Be able to dynamically assign content in the template.tpl (like <title> or <script>)
Be as efficient and scalable as possible.
In the end, my template system looked something like this:
randomPage.php
<?php
// declare any page specific resources
$pageTitle = "Random Sub-Title";
$pageResources = "/css/someRandomCSS.css"
$pageContent = "/randomPage.tpl"
// include the generic page template
include dirname($_SERVER['DOCUMENT_ROOT']).'/includes/template.tpl'
?>
randomPage.tpl
<h1><?=$pageTitle?></h1>
<p>Some random page's content</p>
template.tpl
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Site -- <?=$pageTitle?></title>
<link href="/css/styles.css" rel="stylesheet" type="text/css">
<link href="<?=pageResources?>" rel="stylesheet" type="text/css">
</head>
<body>
<? include $pageContent ?>
</body>
</html>
The main problem with this system is that for every web page, I need to manage two files: one for logic/data and the other for the page template. This seems largely inefficient to me, and doesn't seem like a very scalable approach.
Recently, I come across the smarty framework, which would allow me to consolidate my system from randomPage.php and randomPage.tpl into something like:
randomSmartyPage.php
{extends file="template.tpl"}
{block name=pageTitle}My Page Title{/block}
{block name=pageResources}
<link href="/css/someRandomCSS.css" rel="stylesheet" text="text/css">
{/block}
{block name=pageContent}My HTML Page Body goes here{/block}
Seeing this approach raised three major questions for me:
Are there any fundamental flaws with how I am approaching my templating system?
Can my original php code be refactored so I don't have to create two files for every web page?
Would using the smarty (or perhaps an alternative framework) be a good idea in this case?
Your code isn't really using any templating engine besides PHP itself, which is fine. A flaw I can see is your template will have access to all variables, and the ones you create for it are all global.
Two files is a good system, one to change what is preprocessed and passed to the view, and one for the view itself, containing HTML or whatever. This allows you to easily swap views, for example, a view for standard browsing and a mobile view for mobile browsers.
It can be a good idea, but I'm a firm believer that using PHP is good enough.
Here is an example, untested. It will encapsulate all the variables so you don't pollute the global namespace.
index.php
function view($file, $vars) {
ob_start();
extract($vars);
include dirname(__FILE__) . '/views/' . $file . '.php';
$buffer = ob_get_contents();
ob_end_clean();
return $buffer;
}
echo view('home', array('content' => Home::getContent()));
views/home.php
<h1>Home</h1>
<?php echo $content; ?>
The approach you are describing is part of MVC design pattern. Separating the different aspects of your application.
What you seem to have already understood is that PHP is a templating system in itself as have many others before you.
Take a look at this benchmark for a rough comparison of popular template systems.
Update 2022.08.29
Updated broken links to archived versions.
Note: The answer remains valid if you're trying to learn the language. But for anything serious, consider using a framework.

How could you create a "content_for" equivalent in PHP?

I've been working on a small page in PHP, one that doesn't need the power of a full-fledged framework behind it. One thing that I'm really missing from previous work in Ruby-on-Rails is the ability to effectively pass content up the page using "content_for".
What I was wondering is, how could you create a page lifecycle that would accomplish this same effect in PHP?
So, here's a simple example:
Let's say you have a template that defines an index page, just a recurring header and menu you want to use on all your pages. So your index.php file looks basically like this:
...header stuff...
<body>
<?php include $file.'.php'; ?>
</body>
...footer stuff...
EDIT: Thanks for the tips on URL security, but let's just assume I'm getting the user request safely :)
Now, lets say in the header you want to put this:
<head>
<title><?php echo $page_title; ?></title>
</head>
It would be nice to be able to specify the title in the included file, so at the url http://example.com/index.php?p=test you're loading test.php, and that file looks like this:
<?php $page_title = 'Test Page'; ?>
... rest of content ...
Now, obviously this doesn't work, because the including page (index.php) is loaded before the variable is set.
In Rails this is where you could pass stuff 'up the page' using the content_for function.
My question is this: What would be the simplest, leanest way that you all can think of to effect this kind of 'content_for' functionality in PHP?
Ideally I'd like suggestions that don't involve strapping on some big framework, but some relatively light boilerplate code that could be used in a lot of different applications.
Never do include $_GET['p']. This opens a huge security hole in your site, as include accepts filenames and URLs, so anybody would be able to read any file on your site and also execute any code on your server. You may want to check and sanitize the value first.
If you need something simple, you may put header and footer in separate files, execute your test.php which would set the variables, capture its output using output buffering, then include the header, output the middle part and include the footer. Example:
<?php ob_start(); ?>
<body>
<?php include $filename.'.php'; ?>
</body>
<?php $content = ob_get_clean();
include 'header.php';
echo $content;
include 'footer.php';
?>
If I understand you correctly (I have not used RoR extensively), you could put your data in a variable or a function. If your content was in a variable, your "test.php" could simply hold all your variables and you could load it at the very beginning of your index file (likewise for a function depending on how complicated your needs are; if you're doing a lot of extra work, you may need to use a function as a variable won't work).
For example, your test.php would look something like this:
<?php
$page_title = "Test Page";
$page_content = "Some sort of content";
// Or
function page_content()
{
// Run some functions and print content at the end
}
?>
Then, in your index.php
<?php include $_GET['p'].'.php'; ?>
...header stuff...
<title><?php print $page_title; ?></title>
<body>
<?php print $page_content; ?>
<!-- OR if function -->
<?php page_content(); ?>
</body>
...footer stuff...
This way everything should load properly. You could also split things up, but that would complicate your structure (especially if there is no need for an elaborate framework, this would be unnecessary).
Good luck!
Dennis M.
Are you worried about XSS? Or are you going to filter/whitelist the "filenames" from the query string?
My answer would be to use mod_rewrite -- if you're using PHP, you're likely using Apache!
You could filter out files with a RewriteCond and your RewriteRule could be:
RewriteRule /index.php?p=(.*)$ $1 [L,QSA]
This may be a different approach than the PHP functionality you were looking for, but it comes to mind...

Categories