I am mainly looking for Performance, Website Cacheing, Ease of typing & Security - Upsides and Downsides
Split up the files and throw them in as includes and seems to be a shared preference
<?php
include('header.php');//and whatever includes inside
include('footer.php');//and whatever includes inside
?>
VS
Making them into functions and calling them while in one file where you can check values and share them between the two functions such as multi-style choices
<?php
include $_SERVER['DOCUMENT_ROOT'] . '/more-functions.php';
if(isset($_cookie['style']) || isset($_session['style'])){
if(isset($_cookie['style'])){$style = $_cookie['style']}else{$style = $_session['style']}
}
function siteheader($style){
if(!isset($style)){$style = 'default';}
print ('<http>');//insert rest of header
}
function sitefooter($style){
if(!isset($style)){$style = 'default';}
print ('</http>');//insert rest of footer
}
?>
include('header.php');//and whatever includes inside
include('footer.php');//and whatever includes inside
This breaks PSR-1.
While it's almost inevitable that using a header and footer, whether explicitly or implicitly invoked, will result in badly formed HTML fragments, when you explicitly invoke it (as a function/method) you can at least have the two fragments defined inside the same file.
Performance won't differ significantly.
Related
I am currently trying to find a way to create a flag (or variable) that can be accessed by all scripts. Meaning if I set the flag to true all scripts have that flag as true.
The point behind this that I am writing my own CSS, JS and HTML compressor. This script basically removes all unneccessary information from the code. Like unneccessary whitespace etc. The script is used with a call to require_once. It is working great but sometime I would like to globally disable it.
Is this possible?
There are a couple of ways you can do this but you might be better off creating a file like config.inc.php, including this within your compressor (e.g. compressor.php) and having a boolean flag within this config file like:
$compressorEnabled = true;
Then you include this in your compressor so that even when you have your require_once('compressor.php') in every one of your scripts, at the top of compressor.php you have something like:
if (!$compressorEnabled) {
exit;
}
You could also use a constant rather than a variable, or do a couple of other things. Your main concern with including files this way in all scripts is preventing variable name collisions between the compressor script and whatever script you are including it into.
I have a PHP page that lists many products that each consist of HTML that -depending on the product- does or does not show certain information. I extracted this "product HTML" into a separate PHP file that I include many times. The external file uses variables for each of the product's attributes and also if statements so that parts of the HTML are not rendered at all when an attribute is not set.
The problem is that many of the attributes have default values that I do not want to set each time I call the include
So is there a mechanism in PHP that lets me include another PHP file in such a way that:
I can provide parameters to the file,
uses a default value for the parameters when I do not provide a value,
can be used multiple times in one file.
(This is the way <jsp:include works.)
Keep in mind that I cannot use simple variables (as far as I know) because they keep their value between two separate include calls.
When you include a file in PHP, that file has access to the current scope. So, we need a "clean" scope with no variables and populate the one we need. The best way to go is using a function and the PHP extract method:
function product($data){
extract($data);
require(....path to file);
}
Now call it:
product(array(
'foo' => 'bar',
....
));
This way, on the included file you got a $foo variable with 'bar' value and nothing else. This is how MVC frameworks deal with views.
Edit:
<?PHP
function product($data){
extract($data);
?>
<HTML content>
<?PHP
}
?>
Now "require_once" the file with this and call it like before.
Good morning,
I'm creating my own framework to use in my PHP projects, and I was thinking of some way that I could add .CSS files in the header part of the page, and .JS files and scripts in the footer (keeping HTML clean and valid), but - all this dynamically.
I mean, for example, imagine I have the following structure:
index.php
components
component1
component1.php
component1.js
component1.css
I would like to include each file I need dynamically in index.php for example, keeping the code clean.
And for example, imagine that I insert JS directly in component1.php, is it possible to dynamically add it to component1.js (without human job, to save time in future)
Thanks.
One possible way of doing it would be to represent your entire template/view/whatever-you-want-to-call-it as an object:
class View {
// ...
}
The index.php file could determine which component(s) to use, create them, and then poll them for any required CSS/JS files:
$view = new View();
foreach ($components as $component) {
$cmp = new $component();
$view->addCss($cmp->getCss());
$view->addJs($cmp->getJs());
}
Once everything has been included and such, then index.php can just render the entire thing:
$view->render();
Obviously this is just an example, and your syntax will vary, but hopefully you get the idea.
Edit: You could also make the logic a little more brief by simply adding components to the view directly, and have the view's internal logic handle polling/adding the CSS/JS, rather than index.php. Of course, it really depends on what a "component" is supposed to be in your framework, so I'll leave that up to you to decide.
A very simple example of how to include your js and css assets at the top, before you start outputting anything:
// somewhere in the beginning, before html output
$js = array();
$css = array();
$css[] = 'all_pages.css';
$js[] = 'all_pages.js';
if (some_condition_based_on_page)
{
$css[] = 'some_page_specific.css';
$js[] = 'some_page_specific.js';
}
...
// in your view where you build the head section
foreach ($css as $item)
{
echo "<link rel='stylesheet' href='{$item}' type='text/css'>";
}
...
// in your view where you build the footer
foreach ($js as $item)
{
echo "<link src='{$item}' type='text/javascript'>";
}
The simplest and more portable way would be to include all files matching a certain pattern, e.g., /components/component1/header.css
This would present two complications. One is performance (you need to check all the directories of all your components). The other is isolation of components, i.e., what happens if you need a given CSS to be included before or after another which might or might not be there?
You might try to solve both problems by including a "manifest" in each component, which could specify, at first, the location of any files and where they should be included. Then your processing is reduced to examining the "components" directory and decoding all manifests, and "compiling" this in a series of directive vectors (e.g. $CSSToBeIncludedInThisOrder[] ). You might also serialize the compiled object to a cached file. Of course, any alterations to components should include removal of the compiled meta-manifest.
Later on, you might include in the manifest instruction such as conditional priorities.
All this should be done BEFORE anything is sent to the client's browser (what if component ZZZ wishes to alter the ob_ state, or maybe the encoding, or is a download override component and wants to send a Content-Type of application/octet-stream?), but the "compilation" should allow to keep perceptual latency low.
So let me clarify:
1. index.php checks whether a metamanifest.cache file exists.
2. If it does, it runs something like
$__META = unserialize(file_get_contents($METACACHE));
and goes on to #4.
3. If it does not, opendirs/readdirs the components directory,
looks what files are there, decides (but does not do yet) what to do with them,
placing those decisions in $__META, e.g. $__META['HeaderJS'][].
4. Now HTML generation begins: the __META array is walked and everything that
needs doing gets done (headers, inclusion of JS in heads, etc.).
Phase #3 might even perform some duplicate checks or versioning, say you have two components that both need "jQuery.js" to be included; instead of blindly appending "/components/comp1/js/jQuery.js" and "/components/comp2/js/jQuery.js" to a __Meta['HeaderJS'], the system could declare a conflict or decide it is solved by including only one of them, thereby further reducing processing time.
I have a function that loops through different types of listings pulled from MySQL and displays them as a Facebook-esque "feed". Each type of listing has a different appearance, and therefore requires a different template.
Here is the below function example might be called 100 times (if there are 100 listings):
function display_listing($id,$type) {
global $abs_path;
switch($type) {
case 'photo':
include($abs_path . '/templates/photo.php');
break;
case 'video':
include($abs_path . '/templates/video.php');
break;
}
}
Is there a better way to do this, where I don't potentially end up with 100 includes - which may slow my process down? Can I somehow save the include once on the page, and refer to it as many times as needed?
...or is this the best practice?
Also, I want to know how to do this on my own, without a template engine...
EDIT: The problem isn't solved just by include_once (I dont believe)...I need to be able to reuse the included file multiple times, replacing the variables each time.
Although a switch is not the most scalable way to write this code, I'm afraid that includes is the only way to keep your templates in separate files, here.
You could, conceivably, encapsulate each template's code in a function, however:
/*
photoTemplate.php
*/
<?php
function loadPhotoTemplate($id) {
?>
<div id="photo">
...
</div>
<?php
}
?>
/*
listing.php
*/
function display_listing($id,$type) {
global $abs_path;
switch($type) {
case 'photo':
include_once($abs_path . '/templates/photo.php');
loadPhotoTemplate($id);
break;
case 'video':
include_once($abs_path . '/templates/video.php');
loadVideoTemplate($id);
break;
}
}
This will load each template file at most once, and then just call the function each time you want to display the template with the specific data for that item.
Edit
It would probably be even better to include all template files at the beginning, then just call the appropriate function in the switch. PHP's *_once() functions are slow, as they must consult the list of previously included/required files every time they are called.
create an array of allowed templates. have you function look to see if the requested template is in the array. if it is, then use the $type variable to include the file. yes, in general you shouldn't use user-supplied data in an include file name, but since you've validated it against a known-good array of values, it's safe.
If your concern is performance, I personally wouldn't get into this loop at all.
Presuming that items in the list are viewed more frequently than they're created, I would generate the HTML as the items are created and store the output alongside the data in the database. (Or in memcache or files or somewhere else - but generate it and store it.)
In doing so you'd move this logic back into the creation process of the items so you're doing the same switch statement, but only for one item at a time - you're cutting out the loop.
Then at display time, instead of calling display_listing(), you just echo out the HTML you've already stored.
I think you ought to look at a few things. Firstly, is there even a possibility you will include the same "template" 100 times? That seems like a massive amount of content to put on a page.
If I'm using tiny "snippets" - say, a table row that's repeated many times - I tend to use a function that returns a string, like this:
/* snippets.php */
function tableRow( $row )
{
return
'<tr><td>' . $row['var1'] . '</td>' .
'<td>' . $row['var2'] . '</td></tr>';
}
/* main page/view */
foreach ( $data as $row )
echo tableRow( $row );
The main advantage here is you can have loops and all sorts in the function.
If you're looking for a straight variable-replacement, you could create your own mini-templates in an HTML file; something like:
<p>{name}<br />
Posted {date} by {author}</p>
Then read in the template, pass the whole string to your display_listing function, which runs str_replace on all the {variables}. I don't think there would be too much of a performance hit, but you'd have to try it to be sure.
You want to use the include_once function instead of include.
The include_once() statement includes
and evaluates the specified file
during the execution of the script.
This is a behavior similar to the
include() statement, with the only
difference being that if the code from
a file has already been included, it
will not be included again. As the
name suggests, it will be included
just once.
If you're going to be including templates using a switch for different keywords, then you should set a variable, say $template_filename, in the switch and then once you break out of the switch, do the include like so:
include_once("/templates/{$filename}.php");
If you don't want to use including at all, then you might as well use a templating engine...
This method seems reasonable to me however.
I want to define something like this in php:
$EL = "\n<br />\n";
and then use that variable as an "endline" marker all over my site, like this:
echo "Blah blah blah{$EL}";
How do I define $EL once (in only 1 file), include it on every page on my site, and not have to reference it using the (strangely backwards) global $EL; statement in every page function?
Most PHP sites should have a file (I call it a header) that you include on every single page of the site. If you put that first line of code in the header file, then include it like this on every page:
include 'header.php';
you won't have to use the global keyword or anything, the second line of code you wrote should work.
Edit: Oh sorry, that won't work inside functions... now I see your problem.
Edit #2: Ok, take my original advice with the header, but use a define() rather than a variable. Those work inside functions after being included.
Sounds like the job of a constant. See the function define().
Do this
define ('el','\n\<\br/>\n');
save it as el.php
then you can include any files you want to use, i.e
echo 'something'.el; // note I just add el at end of line or in front
Hope this help
NOTE please remove the '\' after < br since I had to put it in or it wont show br tag on the answer...
Are you using PHP5? If you define the __autoload() function and use a class with some constants, you can call them where you need them. The only aggravating thing about this is that you have to type something a little longer, like
MyClass::MY_CONST
The benefit is that if you ever decide to change the way that you handle new lines, you only have to change it in one place.
Of course, a possible negative is that you're calling including an extra function (__autoload()), running that function (when you reference the class), which then loads another file (your class file). That might be more overhead than it's worth.
If I may offer a suggestion, it would be avoiding this sort of echoing that requires echoing tags (like <br />). If you could set up something a little more template-esque, you could handle the nl's without having to explicitly type them. So instead of
echo "Blah Blah Blah\n<br />\n";
try:
<?php
if($condition) {
?>
<p>Blah blah blah
<br />
</p>
<?php
}
?>
It just seems to me like calling up classes or including variables within functions as well as out is a lot of work that doesn't need to be done, and, if at all possible, those sorts of situations are best avoided.
#svec yes this will, you just have to include the file inside the function also. This is how most of my software works.
function myFunc()
{
require 'config.php';
//Variables from config are available now.
}
Another option is to use an object with public static properties. I used to use $GLOBALS but most editors don't auto complete $GLOBALS. Also, un-instantiated classes are available everywhere (because you can instatiate everywhere without telling PHP you are going to use the class). Example:
<?php
class SITE {
public static $el;
}
SITE::$el = "\n<br />\n";
function Test() {
echo SITE::$el;
}
Test();
?>
This will output <br />
This is also easier to deal with than costants as you can put any type of value within the property (array, string, int, etc) whereas constants cannot contain arrays.
This was suggested to my by a user on the PhpEd forums.
svec, use a PHP framework. Just any - there's plenty of them out there.
This is the right way to do it. With framework you have single entry
point for your application, so defining site-wide variables is easy and
natural. Also you don't need to care about including header files nor
checking if user is logged in on every page - decent framework will do
it for you.
See:
Zend framework
CakePHP
Symfony
Kohana
Invest some time in learning one of them and it will pay back very soon.
You can use the auto_prepend_file directive to pre parse a file. Add the directive to your configuration, and point it to a file in your include path. In that file add your constants, global variables, functions or whatever you like.
So if your prepend file contains:
<?php
define('FOO', 'badger');
In another Php file you could access the constant:
echo 'this is my '. FOO;
You might consider using a framework to achieve this. Better still you can use
Include 'functions.php';
require('functions');
Doing OOP is another alternative
IIRC a common solution is a plain file that contains your declarations, that you include in every source file, something like 'constants.inc.php'. There you can define a bunch of application-wide variables that are then imported in every file.
Still, you have to provide the include directive in every single source file you use. I even saw some projects using this technique to provide localizations for several languages. I'd prefer the gettext way, but maybe this variant is easier to work with for the average user.
edit For your problem I recomment the use of $GLOBALS[], see Example #2 for details.
If that's still not applicable, I'd try to digg down PHP5 objects and create a static Singleton that provides needed static constants (http://www.developer.com/lang/php/article.php/3345121)
Sessions are going to be your best bet, if the data is user specific, else just use a conifg file.
config.php:
<?php
$EL = "\n<br />\n";
?>
Then on each page add
require 'config.php'
the you will be able to access $EL on that page.