Ok, here's the deal where I'm really stuck.
I use my cms with design patterns.
Where's the last final output(in design template's main file: 'design.php'):
<div>{CONTENT_HEADER}</div>
<div style='float:left;width:25%'>{CONTENT_LEFT}</div>
<div style='float:left;width:50%'>{CONTENT_CENTER}</div>
<div style='float:left;width:25%'>{CONTENT_RIGHT}</div>
<div>{CONTENT_FOOTER}</div>
Where is CONTENT_XXXX is generater thought site modules:
ob_start("gz_handler");
<....... LOAD ALL THE HEADER MODULES .......>
$output0 = ob_get_contents();
ob_end_clean();
ob_start("gz_handler");
<....... LOAD ALL THE LEFT SIDE MODULES .......>
$output1 = ob_get_contents();
ob_end_clean();
ob_start("gz_handler");
<....... LOAD ALL THE CENTER SIDE MODULES .......>
$output2 = ob_get_contents();
ob_end_clean();
ob_start("gz_handler");
<....... LOAD ALL THE RIGHT SIDE MODULES .......>
....
// That's I talk about, but this is just for static html, not variables
// Push to header finalizers to override default <title></title>
$header_finalizers_array['change_head_title_attr_to'] = $thread_data['topic_title'];
<....... END OF ALL THE RIGHT SIDE MODULES .......>
$output3 = ob_get_contents();
ob_end_clean();
ob_start("gz_handler");
<....... LOAD ALL THE FOOTER MODULES .......>
$output5 = ob_get_contents();
ob_end_clean();
define("CONTENT_HEADER", finalize_output($output0,$header_finalizers_array));
define("CONTENT_LEFT", finalize_output($output2,$left_finalizers_array));
define("CONTENT_CENTER", finalize_output($output3,$center_finalizers_array));
define("CONTENT_RIGHT", finalize_output($output4,$right_finalizers_array));
// No need finalizations, because there are no more parts, which call content changes
define("CONTENT_FOOTER", $output5);
All is ok in 95% of cases. But, there are some cases, where I need TO GET THE CONTENT OF VARIABLE(in left side modules) which ONLY will be defined in NEXT SIDE(ex. in right side modules)
With my code, I can define the site headers in 'header modules', but then if I want that, I'm able to change it in ex. right side, because I'm able add to array the replace data requirement, which will be executed after all the side content will be generater to variables but BEFORE printing in to client browser.
All this could be done only with 1 line in function:
function finalize_output($output="",$fin_array=array()) {
<...>
$output = preg_replace("#<title>.*</title>#i", "<title>".$fin_array['change_head_title_attr_to']."</title>", $output, 1);
<...>
}
Now about my problem.
How to do the same with VARIABLES:
IN LEFT SIDE modules I have a sentence (PROBLEM: $object ):
if(isset($object)) {
$best_product = sqlArray(sqlQuery("SELECT * FROM tableA WHERE b='$object'"));
<..All the rest code of BEST's product..>
}
IN RIGHT SIDE modules I have the sencence (PROBLEM: $object ):
<... Print LAST 10 PRODUCTS ***>
$res = sqlquery("SELECT * FROM tableA ORDER BY id DESC LIMIT 100);
while($data = sqlarray($res)) { <..PRINT PRODUCT INFO..> }
$new = rand(0,secured($_POST['user_input_new_products']));
for($i=1;$i<=$new;$i++) {
$price_diff_old_new1 = change_products_to_sql('fish_$i', 19.99);
$price_diff_old_new2 = push_product_to_sql('crab_$i', 16.99);
if($i==$new) {
$object = $price_diff_old_new1+$price_diff_old_new2;
}
}
THIS IS JUST EXAMPLE CODE OF WHAT I NEED TO DO(so don't go to details), but THE POINT IS THAT, that I need somehow to submit the variable to earlier point of source:
One of solutions would be " USE GOTO ", but is it variable will be remebered.
I mean:
echo "JOB IS STARTED";
LABEL HOME:
<INCLUDED FILE : procuts.php >
if(isset($object) && check_is_number($object)) {
$a = $object;
}
if(isset($break_me) && $break_me) {
GOTO FINAL;
}
<END OF INCLUDE>
...
<INCLUDED FILE : upload.php >
$object = 999;
$break_me = true;
GOTO HOME;
<END OF INCLUDE>
}
LABEL FINAL:
echo "JOB IS DONE";
AND, is there are any other way to do this WITHOUT GOTO(if GOTO solution is possible(?)) ?
I personally thought that is not possible to code it, but since Php 5.3.0 it is possible, I become likely to be coded. Misfortunelly I'm not sure the company will use Php 5.3.0 on their servers, so I hope there is another solutions.
Also I'm still not sure even the GOTO will help there.
I suggest rethinking your architecture.
No offense, but the code looks rather messy to me.
To point out a few things:
you said you use Design Patterns, but the only pattern seems to be a Template View. You don't seem to be using MVC, nor a Two-Step View, which would both be appropriate in your case.
is there any particular reason why you are not using OOP? It's not that procedural coding is a bad thing, but proper encapsulation of things that conceptually go together and separation of concerns will make your app much more maintainable.
your variable names are not meaningful. An $output0 really tells you nothing about what is inside. Why does $object hold a number? The same is true for your function names: push_to_sql() and change_to_sql() sound alike. I guess one means insert and one means update, but the semantics could be much clearer.
Why are you assigning the variables holding your content-blocks to constants? That step is completely superfluous as you can use the variables in your template view as well.
Now, I understand you used example code in your question's description, so bear with me if I addressed points not applicable to your production code. But still, the simple fact that your modules cannot be rearranged without affecting the other indicates a code smell. Modules should be self-contained.
But let's get to your issue now.
You say you need to submit the variable to an earlier point in the source. I do not understand the example code enough to figure out why. But if you have to keep your Big Ball of Mudcurrent architecture, you could refactor all the code that will be shared among modules into a separate function. Then preload all required data and inject it into the functions rendering the content-blocks. This way, you should be able to push them around as wanted.
If you don't have to keep your current architecture, do yourself a favor and have a look at the patterns linked above. Most PHP frameworks utilize them and you might want to consider migrating your app onto one. To further improve your code, have a look at these QA tools and check out these sites:
http://www.tuxradar.com/practicalphp
http://www.php.net/manual/en/language.oop5.patterns.php
http://www.ibm.com/developerworks/library/os-php-designptrns/
http://www.fluffycat.com/PHP-Design-Patterns/
http://sourcemaking.com/design%5Fpatterns
Related
I am building a website using php. I would want to separate the php from the html. Smarty engine, I guess does that, but right now its too complicated for me. Looking for a quick fix and easy to learn solution, one which is an accepted standard as well. Anyone helping please.
Consider frameworks or choose a template engine
Use a framework. Depending on your project, either a micro framework like Slim or something more complete like Laravel.
What I sometimes do when writing complex systems with quite much php code is separating it the following way (don't know your exact project, but it might work for you):
You create a php file with all the functions and variables you need. Then, you load every wepgage through the index.php file using .htaccess (so that a user actually always loads the index.php with a query string). Now, you can load the html page using file_get_contents (or similar) into a variable (I call this $body now); this variable can be modified using preg_replace.
An example: In the html file, you write {title} instead of <title>Sometext</title>
The replacement replaces {title} with the code you actually need:
$body = str_replace('{title}', $title, $body);
When all replacements are done, simply echo $body...
Just declare a lot of variables and use them in the template:
In your application:
function renderUserInformation($user)
{
$userName = $user->userName;
$userFullName = $user->fullName;
$userAge = $user->age;
include 'user.tpl.php';
}
In user.tpl.php:
User name: <?=$username?><br>
Full name: <?=userFullName?><br>
Age: <?=$userAge?>
By putting it in a function, you can limit the scope of the variables, so you won't pollute your global scope and/or accidentally overwrite existing variables.
This way, you can just 'prepare' the information needed to display and in a separate php file, all you need to do is output those variables.
Of course, if you must, you can still add more complex PHP code to the template, but try to do it as little as possible.
In the future, you might move this 'render' function to a separate class. In a way, this class is a view (a User View, in this case), and it is one step in creating a MVC structure. (But don't worry about that for now.)
Looking for a quick fix and easy to learn solution
METHOD 1 (the laziest; yet you preserve highlighting on editors like notepad++)
<?php
// my php
echo "foo";
$a = 4;
// now close the php tag -temporary-
// to render some html in the laziest of ways
?>
<!-- my html -->
<div></div>
<?php
// continue my php code
METHOD 2 (more organized; use template files, after you passed some values on it)
<?php
// my php
$var1 = "foo";
$title = "bar";
$v = array("var1"=>"foo","title"=>"bar"); // preferrable
include("template.php");
?>
template.php
<?php
// $var1, $var2 are known, also the array.
?>
<div>
<span> <?php echo $v["title"]; ?> </span>
</div>
Personally, i prefer method 2 and im using it in my own CMS which uses lots and lots of templates and arrays of data.
Another solution is of course advanced template engines like Smarty, PHPTemplate and the likes. You need a lot of time to learn them though and personally i dont like their approach (new language style)
function renderUserInformation($user)
{
$userName = $user->userName;
$userFullName = $user->fullName;
$userAge = $user->age;
include 'user.tpl.php';
}
I'm trying to find the best way of structuring a multi-language site navigation,.
I'm aware of the language class in CI but it seems to be more for defining random words and lines of text that are used commonly throughout the site. It appears that creating lang files for each language and then defining translations of all the links seems like the standard approach?
In past on non-codeigniter projects I’ve setup one class like this
class Link{
var $name = array();
var $url;
var $links = array();
function add_link($links){
$this->links[] = $links;
}
}
$all_sections = array();
$section = new Link();
$section->name['en'] = "Home";
$section->name['fr']] = "Uberdurky";
$section->url = "/";
$sub_section = new Link();
$sub_section->name['en'] = "About Acme Ltd";
$sub_section->name['fr'] = "Fabuka Acme Ltd";
$sub_section->url = "/about/";
$section->add_link($sub_section);
Then I have a function to loop through and output the nav, which just looks at the current name[Lang] as defined by session or URL
This to me seems simpler and less overhead - with the benefit that both the nav structure and translations are defined in one place. But I’m new to CI so I might be misunderstanding the standard approach… ? I've googled quite a bit and haven't seen a solution here in detail.
The important thing is that it works for you. There are a lot of benefits to using separate language files:
Clean separation
Only load what you need
Easy to keep track of which languages are available
Ability to let others easily translate the files
I don't see anything wrong with the way you're doing it, but if you want to optimize - don't bother defining all the different language lines. You don't need the French version defined if the language is English. Use only the ones you need, you shouldn't have to pass the whole array to add_link(), the Link class should be detecting the language and loading the appropriate array only...
...it's starting to sound like a language file might be a good idea actually.
For now you just have French and English. I'm assuming you know both languages and (Uberdurky?) are the only one working on this aspect, so it's easier for you to define them "inline". What happens when you want to support 3, 4, or 10 languages? Things will quickly become disorganized and cluttered.
However, you don't have to use the Codeigniter Language class, you might be better off using your own system for something like navigation, which tends to be littered with 1 or two word translations, and changes somewhat frequently (either per site or between sites).
Once again, it's your call. Do what works best for you now and optimize later.
This might be helpful to anyone coming across this question.
https://github.com/cflynn07/CodeIgniterInternationalizationUtility
It's a script to take a cleanly structed HTML table of language translations, and convert them into the required language files used in codeigniter.
I am a PHP dev trying to start using HAML, using this implementation:
http://phphaml.sourceforge.net/
HAML looks awesome, but I don't understand if/how it supports partials (or includes, as they are called in the PHP world).
I would like to have a master template HAML file that then goes and loads up a bunch of partials for all the little pieces. (Then I can reuse those pieces in other templates too.)
In PHP or Ruby this would be really easy, is there any way to do this with HAML? thanks!
dylan
You could create a global render_haml_partial method by analogy with phpHaml's existing display_haml method that might look something like:
function render_haml_partial($sFilename, $aVariables = array(), $sTmp = true, $bGPSSC = false)
{
$sPath = realpath($sFilename);
$haml = new HamlParser(dirname($sPath), $sTmp);
$haml->append($GLOBALS);
if ($bGPSSC)
{
$haml->append($_GET);
$haml->append($_POST);
$haml->append($_SESSION);
$haml->append($_SERVER);
$haml->append($_COOKIE);
}
$haml->append($aVariables);
return $haml->fetch($sFilename);
}
This method could be placed in phpHaml's HamlParser.class.php file so it is available to all your templates.
The only difference between this and display_haml is that it invokes fetch instead of display at the end and returns the result so you can then insert it in-place into the invoking template.
You would then use it in your PHP/HAML templates as follows:
= render_haml_template("path to partial")
This would then be very similar to the Rails/HAML syntax:
= render :partial => 'path to partial'
Note that using display_haml directly does not have quite the same effect since it renders the template directly to the output instead of returning the result to the caller. Thus you could do the following:
- display_haml("path to partial")
But this doesn't capture the result of the render.
I'm guessing that somebody who cares enough about phpHaml might add such a render_haml_partial or something similar eventually - I might suggest it to the author some time.
Quite an old question, but I've updated the source code of phpHaml to reflect this new functionality!
Check out the commit #github
https://github.com/endorama/phphaml/commit/8d95d5ebff06275db8b14438e566c6e41ec91b7f
I am building a English/french website and was wondering if there is a best practice for such a job.
Duplicating the site and making a french and english folder with the appropriate site inside.
Using PHP to swap the content with html tags.
eg. if($lang=='en'):
Use php to swap only the content leaving the html tags the same for both. eg. if statements all over the place. Would this be bad for efficiency?
Any other suggestions would be appreciated
We have a framework in place for when (if) our site goes international that works like this...
Folder structure;
/
lang/
english/
images/
text/
dutch/
images/
text/
Any text or images that are language specific are removed from the page directly and replaced by constants. eg On the login screen, we drop in;
echo TEXT_LOGIN_WELCOME;
which is defined in /lang/english/text/login.php as;
define('TEXT_LOGIN_WELCOME', 'Welcome, please login:');
but in /lang/dutch/text/login.php it's defined as;
define('TEXT_LOGIN_WELCOME', 'Welcome, please login (in dutch):');
;-)
Each language define file is named exactly the same as the page it is used for, so when we load a public-facing page, we only need to figure out which language the user speaks and we can include the relevant language define file.
The good thing about this system is that all the language info is centralised. When you need to add a new language, simply copy the main (english?) folder, rename it, zip the whole thing up and send it to a translation service to work their magic. Of course, the downside of this system is the maintenance as both languages and content grow... If anyone has any bright ideas with regard to this then I'd love to hear them!
Btw, if you end up needing to guess a user's location by IP, you might want to check out geoIP.
Use a templating system. Smarty Template Engine is probably one of the most well-known PHP ones. Not only does a templating system serve the exact purpose you're trying to accomplish, it also makes maintaining pages far easier by separating the display code from the content (which also allows you to use the same template for lots of different content pages of a similar nature).
As the simplest way I recommend you to use i18n internationalization method & gettext catalogs (.po files).
The famous WordPress project is using it as well.
1 - Duplicating the entire site will force you to repeat every code touch-up into the 2 folders :-[
2 - If you mean somenting like
<?php if($lang=='en') { ?>
<p>English text</p>
<? } else { ?>
<p>Text français</p>
<? } ?>
This solution is perfect to manage two languages in the same page.
But you still have duplicated tags.
3 - Change only content it's really satisfaction.
Maybe proliferate of if statements can weigh down php compiling... I don't know.
Anyway document can be more concise with this approach:
<?php
function interpreter($buffer) {
$pieces = explode('#', $buffer);
if (isset($_GET['lang'])) $begin=$_GET['lang'];
else $begin = 1; // 1 to display français, 2 to display english
$tot = count($pieces);
for ($i=$begin; $i<$tot; $i+=3) { // remove one language
unset($pieces[$i]); }
foreach ($pieces as $value) { // recompose the text
$output .= $value; }
return $output;
}
ob_start("interpreter");
?>
#Français#English#
<p>#English text#Texte français#.</p>
<?php ob_end_flush() ?>
The text between ob_start and ob_end_flush is parsed AFTER php compiling.
That means are affected strings coming eg. from echo statement, not inside < ?php ?> tags.
Also content coming from php include IS affected.
But NOT external css or javascript.
Keep attention delimiter # isn't a caracter yet used elsewhere.
Maybe you'll prefer to replace with || or ^^
Of course in the future you can adapt this solution into 3 languages or more. But if you have to insert the "Third language translation#" in many lines of a big site, maybe the solution from MatW fits you.
I've experienced first hand the extent of the horror and foot-shooting that the ugliness of PHP can cause. I'm onto my next project (you may be wondering why I'm not just switching languages but that's not why I'm here) and I've decided to try doing it right, or at least better, this time.
I've got some models defined, and I've started on a main controller. I'm at a fork in my decisions about how to implement the view. So far, the main controller can be given lists of display functions to call, and then it can spew out the whole page with one call. It looks like:
function Parse_Body()
{
foreach ($this->body_calls as $command)
{
$call = $command['call'];
if (isset($command['args'])) $call($command['args']);
else $call();
}
}
My dilemma is this:
Would it be better to have all of my display functions return the HTML they generate, so that the main controller can just echo $page; or should the display files use raw HTML outside of PHP, which gets output as soon as it's read?
With the former, the main app controller can precisely control when things get output, without just relinquishing complete control to the whim of the displays. Not to mention, all those lists of display functions to call (above) can't really be executed from a display file unless they got passed along. With the latter method, I get the benefit of doing HTML in actual HTML, instead of doing huge PHP string blocks. Plus I can just include the file to run it, instead of calling a function. So I guess with that method, a file is like a function.
Any input or advice please?
Would it be better to have all of my
display functions return the HTML they
generate, so that the main controller
can just echo $page; or should the
display files use raw HTML outside of
PHP, which gets output as soon as it's
read?
One of the advantages of php is that the processing is similar to the output:
So:
<h1> <?= $myHeading; ?> </h1>
Is more clear than:
echo "<h1>$myHeading</h1>";
An even more than:
echo heading1($myHeading); //heading1() being an hypothethical user defined function.
Based on that I consider that it is better to in the view to have HTML and and just print the appropriate dynamic fields using php.
In order to get finner control over the output you can use: ob_start as gurunu recommended.
You could of course use any of the several php MVC frameworks out there.
My prefered one, now is: Solarphp
but Zend Framework and Cakephp could help you too.
And finally if you don't want to use any framework
You could still use a pretty slim templating engine: phpSavant.
That will save you a few headaches in the development of your view.
th
You can get the benefit of both, obtaining a string of HTML while also embedding HTML within PHP code, by using the output control functions:
From the PHP manual # http://www.php.net/manual/en/ref.outcontrol.php:
<?php
function callback($buffer)
{
// replace all the apples with oranges
return (str_replace("apples", "oranges", $buffer));
}
ob_start("callback");
?>
<html>
<body>
<p>It's like comparing apples to oranges.</p>
</body>
</html>
<?php
ob_end_flush();
?>
First buffer everything. then replace tags using a parser at end of script.
<?php
$page_buffer = '';
function p($s){
global $page_buffer;
$page_buffer .= $s;
}
$page_buffer = str_replace(
array('<$content$>','<$title$>'),
array($pagecontent,$pagetitle),
$page_buffer);
echo $page_buffer;
?>
Samstyle PHP Framework implements output buffering and View model this way
And did I mention about benefits of buffering your output in a variable before "echo-ing"? http://thephpcode.blogspot.com/2009/02/php-output-buffering.html