there's something that's giving me a bit of a headache at the moment. I am querying a database retrieving some data after clicking a link from a previous page.
Easy enough I get to play about with some code in the 'echo'. Problem is in the ‘echo’ as I need to put in php includes and general html/design code for design purposes. Is there a way or a method where I can write the code but then call variables again later and have the ability to place other php code such as includes? Basically something which is going to let me have to have the code but then allow me to concentrate on the design aspect of my page.
Any help much appreciated.
<?php
if(!empty($_GET['book_url']))
{
$sql = "
SELECT articles.id, articles.order_ref, articles.art_title, articles.art_book, articles.art_url, book.id AS bookid, book.book_name AS book_name, book.book_url AS book_url
FROM articles
LEFT JOIN book ON articles.art_book = book.id
WHERE book_name = \"" .$_GET['book_url'] . "\"
ORDER BY id ASC
";
// then do the query, etc....
}
$results = $db->query($sql);
if($results->num_rows) {
While($row = $results->fetch_object()) {
echo "
////////Show Stuff
";
?>
You can separate the code and the HTML by putting the code in <?php ?>. Then, in your HTML you can have short code snippets that print the work you did in the code sections. Like this (there might be a syntax error or two, I don't have Apache to test):
<?php
$name = $_GET['name'];
function stuff() {
// this would normally be long and complicated
return "stuff";
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>title</title>
<link rel="stylesheet" href="stylesheet.css" type="text/css">
</head>
<body>
<!-- try to keep these short so you can focus on design-->
<h1>The name is: <?php echo $name; ?></h1>
<h1>The stuff is: <?php echo stuff(); ?></h1>
</body>
</html>
Alternatively, you can use a framework like Laravel which will provide a templating system.
Related
I am new to PHP and I'm currently working through 'PHP for absolute beginners' book. In the book it is currently teaching about templating and using the StdClass() Object to avoid naming conflicts.
I have a file for templating called page.php and a file for my homepage called index.php.
My page.php code
<?php
return "<!DOCTYPE html>
<html>
<head>
<title>$pageData->title</title>
<meta http-equiv='Content-Type' content='text/html;charset=utf-8'/>
</head>
<body>
$pageData->$content
</body>
</html>";
My index.php
<?php
//this correctly outputs any errors
error_reporting( E_ALL );
ini_set("display_errors", 1);
$pageData = new stdClass();
$pageData->title = "Test title";
$pageData->content = "<h1>Hello World</h1>";
$page = include_once "templates/page.php";
echo $page;
The errors i am receiving are
Warning: Undefined variable $title in C:\xampp\htdocs\ch2\templates\page.php on line 5
Warning: Undefined variable $content in C:\xampp\htdocs\ch2\templates\page.php on line 9
I don't understand this as it is exactly what the book is teaching any help would be appreciated and please if there are any better ways to use templating please remember I am a beginner so keep it simple!
Your page.php looks a little odd. return is not something I would use in context of printing html. Also, you are using php and html within the php tag which can't work. Try this:
<!DOCTYPE html>
<html>
<head>
<title><?php echo $pageData->title; ?></title>
<meta http-equiv='Content-Type' content='text/html;charset=utf-8'/>
</head>
<body>
<?php echo $pageData->content; ?>
</body>
</html>
You don't need echo $page in your index.php, let the page.php do that.
/Edit: There is also a typo in line 9: $pageData->$content; I corrected that.
I have a webpage called search.php
I want it to have a title/tab tag that looks like this:
<head>
<title><?php echo $number_count; ?> items found - Mysearch </title>
<head>
But the variable $number_count is 0 until later php scripts are called to query the database and display the items one at a time. At the end of the HTML I can easily display <p> <?php echo $number_count; echo "items found" ?> </p> and it works with the correct count.
It must be defined first.
Best (and only in this case) approach to do it is to do calculations first, then generate website output.
EDIT:
You can do it like that:
<?php
$count = 125;
?><!DOCTYPE html>
....
<title>Title count: <?php echo $count ?></title>
....
I am using (or at least tying to) PHP HEREDOC function as a templating engine. I have implemented external caller string that can directly process external functions in HEREDOC, and that works successfully.
The problem I am facing now is that the order of certain functions appear to take precedence and execute first, regardless of other functions and/or code inside the specific HEREDOC.
How to fix that?
(Please note I am a PHP beginner. I have done my homework, but couldn't find a solution. Thanks.)
FUNCTION PROCESOR:
function heredoc($input)
{
return $input;
}
$heredoc = "heredoc";
HEREDOC TEMPLATE:
function splicemaster_return_full_page()
{
global $heredoc;
$title ="This is document title";
echo <<<HEREDOC
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
{$heredoc(splice_html_title($title))}
</head>
<body>
{$heredoc(splicemaster_return_message())}
{$heredoc(splice_quick_add_article_form())}
{$heredoc(display_all_articles_in_a_html_table())}
</body>
</html>
HEREDOC;
}
The issue at hand is with "{$heredoc(display_all_articles_in_a_html_table())}" call, which outputs before everything else, resulting in a broken HTML.
Any help appreciated, I am banging my head with this for quite a while now.
UPDATE:
using stuff posted in comments i tried to do something else, but this is ugly as hell, and I would have issues editing this at later date.
function testout()
{
$title = "This is document title";
echo "<!DOCTYPE html>";
echo '<html lang="en">';
echo "<head>";
echo '<meta charset="utf-8">';
echo "<title>". $title . "</title>";
echo "</head>";
echo "<body>";
echo splicemaster_return_message();
echo splice_quick_add_article_form();
echo display_all_articles_in_a_html_table();
echo "</body>";
echo "</html>";
}
(How it looks like is not important - I have a HTML processor function.)
UPDATE 2
OK, so I found "dirty" fix, tho that doesn't explain why the engine works as it does. (I also tested on another machine, with diff. php):
function splicemaster_return_full_page()
{
global $heredoc;
$title ="This is document title";
echo <<<HEREDOC
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
{$heredoc(splice_html_title($title))}
</head>
<body>
{$heredoc(splicemaster_return_message())}
{$heredoc(splice_quick_add_article_form())}
HEREDOC;
echo <<<HEREDOC
{$heredoc(display_all_articles_in_a_html_table())}
</body>
</html>
HEREDOC;
}
You shouldn't be using heredoc here. Or really be trying to render an entire html document within a function. This is how html should be rendered with php.
Note: I'm also pretty sure you can't call functions in a heredoc statement.
<?php $title = "This is document title"; ?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<?php echo splice_html_title($title); ?>
</head>
<body>
<?php
echo splicemaster_return_message()
. splice_quick_add_article_form()
. display_all_articles_in_a_html_table();
?>
</body>
</html>
You can see how much cleaner this is, which makes it much easier to edit, when needed. You just put this in a file 'page.php' for example.
include_once('page.php');
And include it where ever you would call that function splicemaster_return_full_page.
I asked this (similar) question on other site while seeking why this happens, and found the culprit.
The problem was in called functions that echo (or print) output, instead returning it. When I switched to return, the code outputs appropriately.
I'm trying to avoid to query my database twice: for set <title> attribute and also for echo the page title. I want to query it just one time:
Example:
<html>
<head>
<?php
// how should I use here ob_start() ? Is there any other possible way to achieve this?
$title = "";
echo '<title>', $title, '</title>'; // this should be in the end <title>value of $row['page_title']</title>
?>
</head>
<body>
<?php
$sql = $mysqli->query("MY QUERY");
$row = $sql->fetch_assoc();
$title = $row['page_title']; // I want that this assignment to set the variable in the top
// I know that for this job I can use ob_start() but I didn't used it until now
// and I will really appreciate any help from you.
?>
<h1><?php echo $title; ?></h1>
</body>
</html>
I know that I can do the query before echo the title attribute but I don't want to do it like that. Do you have any suggestion? or can you show me how to use that ob_start() / ob_clean() functions?
Thank you!
Shift the query to the top of the code and reuse the variables!
<?php
$sql = $mysqli->query("MY QUERY");
$row = $sql->fetch_assoc();
$title = $row['page_title'];
?>
<html>
<head>
<?php echo '<title>', $title, '</title>'; ?>
</head>
<body>
<h1><?php echo $title; ?></h1>
</body>
</html>
ob_start();, in usual sense, won't help you have. However, you can use ugly solution like this:
ob_start();
echo '
<html>
<head>
<title>{title}</title>
</head>
<body>
';
$header = ob_get_clean();
// and then, when you know your title
echo str_replace('{title}', $known_title, $header);
But I strongly recommend taking another approach. You need to choose and fill the template after all data has been gathered and you know all details about which template you want. If you start echoing different parts preemptively, you will get more and more troubles. Now you need to change title for some pages. Then you will need to add css file for specific page and you will have to do that ugly business again. Why not do it the right way?
So I decided to give codeigniter a chance and convert my existing site which is all custom php to the codeigniter framework. But trying to figure out how to do this best in codeigniter that I was doing from my original site. In the original site a person would visit a page such as index.php. In the index.php code its broken into sections like so (This is just a very simple example):
index.php:
<html>
<head></head>
<body>
<div id="top">{$SECTION1}</div>
<div id="main">{$SECTION2}</div>
<div id="bottom">{$SECTION3}</div>
</body>
</html>
Then in my main php file that is included in every single page I run a query that grabs all "modules" that are assigned to each section above for the index.php page. So give me all modules that are assigned to {$SECTION1}, {$SECTION2} and {$SECTION3} for index.php. A module in my original system is simply a php file that does a specific job so I might have a module called latest_story.php and in the script it gets the last 10 stories from the database and display the results.
latest_story.php
include('class/story/story_class.php');
$story = new Story($databaseconn);
$latest_story = $story->findLatestStory(10);
//If results back from $latest_story loop through it
//and display it however I want
Then using output buffering I execute each module then take the outputted information from each module assigned to each section and replace that section with the outputted data.
Can this be done in codeigniter? If so can someone point me in the right direction in doing this in codeigniter?
EDIT
To give a more clear view of what Im doing in the original system I run a query on every single page to determine what "modules" to grab for the current page the person is viewing then run this code
foreach($page_modules AS $curr_module)
{
$module_section = intval($curr_module->section);
$module_file = $global_function->cleanData($curr_module->modfile);
$module_path = MODS .$module_file;
if(is_file($module_path))
{
ob_start();
include($module_path);
${'global_pagemod' .$module_section} .= ob_get_contents();
ob_end_clean();
}
}
Then I simply take each variable created for each section and replace {$SECTION[n]} with that variable in the template.
ADDITIONAL EDIT
What Im trying to do is be able to create "modules" that do specific tasks and then in the backend be able to dynamically place these modules in different sections throughout the site. I guess you can say its like wordpress, but a more simplier approach. Wordpress you can add a module and then assign it to your pages either in the left column, middle or right column. Im trying to do pretty much the same thing.
Basically, Codeigniter is an MVC framework. To use it, you really want to embrace that rather than include files. You can rejig your code as:
In your controller:
function example()
{
$this->load->model('story_model','story');
$data['section1'] = $this->story->latest();
$data['section2'] = $this->story->top_stories(5);
$data['section3'] = $this->story->most_popular();
$this->load->view('example', $data );
}
In your model:
function latest()
{
return $this->db->limit(1)->get('stories');
}
etc.
In your view:
<html>
....
<div id="latest">
<h2><?php echo $section1->title; ?></h2>
<?php echo $section1->body; ?>
</div>
<div id="top">
<?php foreach $section2 as $popular { ?>
<h2><?php echo $popular->title; ?></h2>
<?php echo $popular->body; ?>
<?php foreach} ?>
</div>
</html>
If you wanted a second page, with different content but the same layout, you'd add this to your controller:
function second_page()
{
$this->load->model('tags_model','tag');
$this->load->model('authors_model','author');
$data['section1'] = $this->tag->latest();
$data['section2'] = $this->tag->top_tags(5);
$data['section3'] = $this->author->most_popular();
$this->load->view('example', $data );
}
and add in new models etc.
You can pass the retrieved data as an array to the main view and then access that data on the subviews.
For example:
Main View
$posts = $this->post_model->fetch_all();
$top_data = $this->more_data_model->fetch_more_data();
$data = array('posts'=>$posts,'top_data'=>$top_data);
$this->load->view('main_view',$data);
Then on the main view you load the subviews:
$data = array('data_name'=>$top_data);
$this->load->view('top_view',$data);
And then on the subview you just use the data however you want. There might be a more effective way to do this, but i believe this'll do the trick. :)
I do it like this:
Controller:
function about()
{
$user_session = $this->model_user_lite->Session_Check();
$data['auth'] = $user_session;
$user_id = $this->model_user_lite->Session_UserID();
$data['user_id'] = $user_id;
$this->load->view( 'main_about.php', $data );
}
View:
<? $this->load->view('header_base.php'); ?>
<? $this->load->view('include_standart.php'); ?>
<? $this->load->view('header_standart.php'); ?>
<div class="box">
<div class="box-top"></div>
<div class="box-center">
<div class="content">
<center>
<h2><?= lang('MAIN_ABOUT_CAPTION_TEAM'); ?></h2>
<div class="hr"></div>
...
Header Base:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<link rel="shortcut icon" href="<?= base_url(); ?>/favicon.ico" type="image/x-icon">
<link rel="icon" href="<?= base_url(); ?>/favicon_animated.ico" type="image/x-icon">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta property="fb:admin_id" content="677920913" />
<meta property="fb:app_id" content="<?= FACEBOOK_APPID; ?>" />
<meta property="og:site_name" content="<?= SITE_NAME; ?>" />
<?php if ( empty( $og_title ) === FALSE ): ?>
<meta property="og:title" content="<?= $og_title; ?>" />
<?php endif ?>
...
This way you have a clean file system, seperate header, you can even have more headers just as you like, and can assign all the data from the controller to the view.
**Variables that are assigned from the controller, also go to views loaded by your "main view".
I'm using it in a major dating website and it works like a charm.