I am facing the problem that I'm not really sure how to develop without a framework or a template engine. I started coding that way and now I want to go to basics.
I used to work with this MVC schema, using Codeigniter and Smarty as a template engine. What I want to do now is to use raw php without both tools mentioned.
I don't know how to "copy" the concept of Smarty's "block" and "extends".
I used to define a base.tpl file which had html head, only the body tag, and the base css and js files (the ones that are always used in every page of the site), like this: (snippet)
<!DOCTYPE html>
<head>
<meta charset="utf-8" />
<title>Dashboard</title>
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport" />
<meta content="" name="description" />
<meta content="" name="author" />
<!-- ================== BEGIN BASE CSS STYLE ================== -->
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link href="{site_url()}assets/css/animate.min.css" rel="stylesheet" />
<!-- ================== END BASE CSS STYLE ================== -->
<!-- ================== BEGIN PAGE LEVEL CSS STYLE ================== -->
{block name='custom_css'}{/block}
<!-- ================== END PAGE LEVEL CSS STYLE ================== -->
<!-- ================== BEGIN BASE JS ================== -->
<script src="{site_url()}assets/plugins/pace/pace.min.js"></script>
<!-- ================== END BASE JS ================== -->
</head>
<body>
<div id="page-container" class="fade page-sidebar-fixed page-header-fixed">
<div id="header" class="header navbar navbar-default navbar-fixed-top">
<div class="container-fluid">
{include file='base/header.tpl'}
</div>
</div>
<!-- BEGIN PAGE -->
<div class="page-content">
<!-- BEGIN PAGE CONTAINER-->
<div class="container-fluid">
<!-- BEGIN PAGE HEADER-->
<div class="row-fluid">
<div class="span12">
<!-- BEGIN PAGE TITLE & BREADCRUMB-->
{include file='admin/base/breadcrumb.tpl'}
<!-- END PAGE TITLE & BREADCRUMB-->
</div>
</div>
<!-- END PAGE HEADER-->
{block name='content'}{/block}
</div>
<!-- END PAGE CONTAINER-->
</div>
<!-- END PAGE -->
and then when I need to call this base.tpl I did this:
{extends file='base/base.tpl'}
{block name='custom_css}
<link href="{site_url()}assets/css/pages/blog.css" rel="stylesheet" type="text/css"/>
{/block}
{block name='content'}
<div class="row">
<div class="col-md-3 col-sm-6">
<div class="widget widget-stats bg-green">
<div class="stats-icon stats-icon-lg"><i class="fa fa-globe fa-fw"></i></div>
<div class="stats-title">TODAY'S VISITS</div>
<div class="stats-number">7,842,900</div>
<div class="stats-progress progress">
<div class="progress-bar" style="width: 70.1%;"></div>
</div>
<div class="stats-desc">Better than last week (70.1%)</div>
</div>
</div>
I have been searching but I am affraid I'm missing the right words to search because I am not finding answers.
I would like to be guided please!
Another way could be to do something like this. I feel like this is probably closer to what a template engine ends up with, but with using the {block} syntax instead.
index.php
<?php
$blocks = array();
function add_block($name, $callback){
global $blocks;
ob_start();
$callback();
$output = ob_get_flush();
$blocks[$name] = $output;
}
function get_block($name){
global $blocks;
if(!empty($blocks[$name])){
return $blocks[$name];
}
return '';
}
//stop any errors from being output.
ob_start();
//include the page code
include 'page.php';
$cleanup = ob_end_clean();
//now output the template
include 'template.php';
page.php
<?php
add_block('head', function(){
?><script type="text/javascript">/* Some JS */</script><?php
});
add_block('body', function(){
?><p>Some body text goes here</p><?php
});
template.php
<html>
<head>
<title>Site Title</title>
<?php echo get_block('head'); ?>
</head>
<body>
<?php echo get_block('body'); ?>
</body>
<?php echo get_block('after_body'); ?>
</html>
I'm not sure how smarty does it and have actually never used a templating engine myself. But maybe this could be how it's done.
Say we have:
index.php
page.php
template.php
When we go to index.php it could start and output buffer and include page.php. After the include catch the output buffer and use some regular expressions to match and blocks found within it and put them into variables.
Now do the same for the template.php and find all the blocks in there too and replace the blocks with the blocks found in page.php.
I don't actually think that's how templating engines do it. But that's one possible way.
A very tiny self made, templating engine
based on regex replace using an array hook
to "manually" parse templates
(but i grant you, smarty is more functional)
To any question, feel free to answer me here
The regex match whole file's term like {term-_},
and replace it by a php condition who will be executed on at rendering time.
if a mark" doesn't found in $vars, it will simply replaced by an empty string
Engine
function parse($vars, $tpl)
{
return preg_replace
(
'#\{([a-z0-9\-_]*?)\}#Ssie',
'( ( isset($vars[\'\1\']) )
? $vars[\'\1\']
: \'\'
);',
file_get_contents(TEMPLATE_DIR.$tpl)
);
}
part of index
<html>
<head>...</head>
{body}
</html>
part of body
<body>
<div class='ui'>{username}</div>
</body>
Usage
<?php
// include engine function
define("TEMPLATE_DIR", __DIR__."templates/");
require_once("library/parse.php");
// just init $vars on top of index
$vars = [];
// and access and fill it anywhere
$vars = ["username" => $_SESSION["user"]];
// prepare the body including previous $vars declarations
$vars["body"] = parse($vars, 'body');
echo parse($vars, 'index');
Output
<html>
<head>...</head>
<body>
<div class='ui'>Stack Overflow :)</div>
</body>
</html>
You can improve it by using constant and prevent double wrap marker {{}} or more, or placing debug trace...
Add this to start of engine to prevent templates containing object bracket can be bad interpreted as a templates marker :
$out = file_get_contents(TEMPLATE_DIR.$tpl);
$out = str_replace("{{}}", "{}", $out);
To use constant, you can use perform as like :
$empty = (DEBUG) ? "_EMPTY_" : "";
return preg_replace
(
'#\{([a-z0-9\-_]*?)\}#Ssie',
'( ( isset($vars[\'\1\']) )
? $vars[\'\1\']
: ( defined(\'_\'.strtoupper(\'\1\').\'_\')
? constant(\'_\'.strtoupper(\'\1\').\'_\')
: $empty
)
);',
$out
);
Note:
__DIR__
used in my code is valid for PHP >= 5.3.0 try
but you can use
dirname(__FILE__)
For PHP < 5.3.0 try
Related
I'm trying to convert a large website into PHP. All the files have almost similar head/header portion and footer section.
I'm trying to unify all these header section, and footer section by putting it into a seperate file.
So I need to replace all of my
header section (which spans anywhere from 1045 to 1535 lines) with
<?php include_once "include/header.php" ?>
And
footer section (which spans anywhere from 80 to 140 lines) with
<?php include_once "include/footer.php" ?>
from all the files in a directory..
This is a rough figure of what I need to do.. Please look the code below..
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="">
<meta name="description" content="">
<meta name="author" content="">
<title></title>
<link rel="apple-touch-icon" href="">
<link rel="shortcut icon" href="">
<!-- Stylesheets -->
<link rel="stylesheet" href=""> <!-- Some Stylesheets -->
<link rel="stylesheet" href=""> <!-- Some Stylesheets -->
<link rel="stylesheet" href=""> <!-- Some Stylesheets -->
<!-- Scripts -->
<script src=""></script>
</head>
<body class="">
<nav class="nav1" role="navigation">
<!-- Some HTML -->
</nav>
<div class="menubar1">
<!-- Some HTML -->
</div>
<div class="menubar2">
<!-- Some HTML -->
</div>
<!-- ========================================================= -->
<!-- ========================================================= -->
<!-- PAGE CONTENTS -->
<!-- ========================================================= -->
<!-- ========================================================= -->
<!-- Footer -->
<footer class="site-footer">
<!-- Some HTML -->
</footer>
<script src=""></script> <!-- Some Script Tags -->
<script src=""></script> <!-- Some Script Tags -->
<script src=""></script> <!-- Some Script Tags -->
<script src=""></script> <!-- Some Script Tags -->
<!-- Page -->
<!-- Google Analytics -->
<script>
/* Some Scripts */
</script>
</body>
</html>
In the above given code, I need to replace everything from top to
<div class="menubar2">
(Until it's closing Tag)
with
<?php include_once "include/header.php" ?>
Also, I need to replace everything below footer
with
<?php include_once "include/footer.php" ?>
Please help me replace that portion of the file with my string..
Thanks in advance🙂..
First, note that regular expressions should generally never be used with DOM. However, since we're talking mass replacing within files, I suppose this is acceptable in this case (you don't want to lose the formatting, and mass deleting nodes with DOM would be awkward as well).
Now, taking into account what you said in the other comment about the structure of your menubar2 div, this should do it.
Edit: now with dynamic number of divs under menubar2:
// Compute the amount of divs within `menubar2` div
libxml_use_internal_errors(true);
$doc = new \DOMDocument();
$doc->loadHTML($html);
$menubar2_inner_div_count = (new \DOMXPath($doc))
->query('//div[#class="menubar2"]//div')
->length;
// Header
$html = preg_replace(
'/^.*?<div class="menubar2">' . str_repeat('.*?<\/div>', $menubar2_inner_div_count + 1) . '/s',
'<!-- Header -->' . PHP_EOL . '<?php include_once "include/header.php" ?>',
$html
);
// Footer
$html = preg_replace(
'/<footer class="site-footer">.*?<\/html>/s',
'<?php include_once "include/footer.php" ?>',
$html
);
// (Optional) Remove now useless indentation (supposes your indent is 8 spaces,
// otherwise replace accordingly)
$html = preg_replace('/^ {8}/m', '', $html);
Demo: https://3v4l.org/G3HbK
This is a quick rough fix... didn't test it but hope it works!
Quick heads up! If you are planning on adding <div> inside <div class="menubar2"></div> then add this <div class="match-hidden"></div> after </div> closing tag of class .menubar2.
Change first preg_match with preg_match('/<!DOCTYPE html>(.*?)<div class="match-hidden">(.*?)<\/div>/s',$file,$newfile);
$file = file_get_contents('replace_head.html');
preg_match('/<!DOCTYPE html>(.*?)<div class="menubar2">(.*?)<\/div>/s',$file,$newfile);
preg_match('/<footer class="site-footer">(.*?)<\/html>(.*?)/s',$file,$newfile2);
if($newfile == TRUE){
$file1 = str_replace([$newfile[0]],['<?php include_once "include/header.php" ?>'],$file);
if($newfile2 == TRUE){
$file2 = str_replace([$newfile2[0]],['<?php include_once "include/footer.php" ?>'],$file1);
//header('content-type:plain/text');
//Un-comment this if you want to download current file
header('content-type:application/json');
//Comment this if you want to see it as html
echo($file2);
}
}
If anyone can think of a better title, please let me know.
Right now I'm using a technique from this tutorial to get the width and height of the user's viewing window. It works, but only on the index.php page. I'm using a php based css file.
In the php based css file, everything would normally work fine, except that the first line at the top *$width_div_center = $GET['width']0.8; thinks the width is in string form. (Or something like that.) As a result, the $width_div_center variable is set to zero which causes a lot of issues. What am I doing wrong, or how can I get the php based css file to do a multiplication on *$GET['width']0.8 properly? Thank you for your assistance.
<html>
<head>
<title>Taylor Love</title>
<!--
<link rel="stylesheet" media="only screen and (color)" href="main.css" />
<link rel="stylesheet" href="main.css"/>
-->
<link rel="stylesheet" type="text/css" href="css/style.php" />
<?php
$content = "null";
include_once('content.php');
?>
</head>
<body class="body">
<!-- top header -->
<div class="div-center decorated-white">
<div class="header-background">
<div style="margin:10px;">
<font color="#AAA" >
hello, universe!
<?php
echo $_GET['width'] *.8;
echo "<h1>Screen Resolution:</h1>";
echo "Width : ".$_GET['width']."<br>";
echo "Height : ".$_GET['height']."<br>";
?>
</font>
</div>
</div>
</div><!-- div-center-->
<div class="div-center" style="margin-top:10px;">
<?php
include('sidenav.php');
?>
<div id="div-content" class = "decorated-white">
<?php echo $content; ?>
</div><!-- div-content-->
</div><!-- div-center-->
<div class="clear"></div>
<!-- top header
<div class="div-center decorated-white" style="margin-top:10px">
<?php
for ($i = 0; $i < 5; $i++){
echo "</br>";
}
?>
</div>-->
</body>
</html>
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
I appear to be having issues separating two different pages of code.
You seem to be calling style.php without any $_GET parameters.
The $_GET parameters you use in index.php are not automatically passed to the style.php. script.
Try temporary hard-coding the 'width' parameter to see if it makes any difference
<link rel="stylesheet" type="text/css" href="css/style.php?width=100" />
This is because the request for the stylesheet is a separate GET request which has no idea about the referrer's get parameters.
this is probably because $_GET variables are usually strings. That is probably the cause of your problem. You could use the function floatval() to convert it to a float.
The first line should be $width_div_center = floatval($_GET['width'])*0.8;
I've been attempting to use jquery and jqueryui to make tabs on my website. However, I can't seem to get them to work. The main page is in PHP, and I am using the Codeigniter framework. If the page fully renders, then the tabs won't work. If I change something that creates a fatal error in the php the tabs appear. While I was attempting to figure out what was going on I created a very basic page with only the jquery demo script, and it wouldn't work either. If it makes any difference, I am hosting on HostGator.
Please advise.
Header:
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Sign Up!</title>
<link rel="stylesheet" href="<?php echo base_url();?>css/style.css" type="text/css" media="screen" />
<link rel="stylesheet" href="<?php echo base_url();?>css/jquery-ui-1.8.11.custom.css" type="text/css" media="screen" />
<!-- Java includes -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js" type="text/javascript"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/jquery-ui.min.js" type="text/javascript"></script>
</head>
<body>
<div class = "header">
<span class="nav_bar"><?php if($this->session->userdata('is_logged_in')){ echo 'Welcome, ' . ucfirst($this->session->userdata('first_name')). " " . ucfirst($this->session->userdata('last_name')) . ' | ' . anchor('site/logout' , 'Logout');} else { echo anchor('site/is_logged_in', 'Login');} ?></span>
</div>
<div class="content">
Body:
<!-- Tab Script -->
<script>
$(function() {
$( "#tabs" ).tabs();
});
</script>
<!-- end Tab Script -->
<div id="tabs">
<ul>
<li>All Contacts</li>
<li>Place Holder Tab</li>
</ul>
<div id="tabs-1">
<?php $this->load->view('all_contacts_tab_view'); ?>
</div>
<div id="tabs-2">
Place Holder tab
</div>
</div>
Footer:
</div> <!-- end content div -->
<div class="footer">
<div class="footer_left">
<div id="copyright"> © 2011 NetworkIgniter. All rights reserved. NetworkIgniter, networkigniter.com and the all designs are trademarks of NetworkIgniter. Created with CodeIgniter and hosted on HostGator.</div>
<div id="legal">Terms and Conditions | Privacy Policy</div>
<div id="benchmarking">{elapsed_time} | {memory_usage}</div>
</div>
</div>
</body>
</html>
I did track down a java error after all, but I'm not sure how to fix it.
Error: $("#tabs").tabs is not a function
Line: 23
it looks like your calling tabs before it generated I would put that in doc ready
$(document).ready(function() {
$( "#tabs" ).tabs();
});
Figured it out.
It was the Google tracking script at the end. It was claiming the $. the reason why it was working when php crashed was because it wasn't getting down to the footer where the Google script was.
Errors on tabs are often due to a missing end of tag such as a </div> or </li> or whatever. Check the code generated by the PHP script to see if everything's fine. You might wanna use the Developper Tools Plugin on FireFox to detect any validation problems (including the missing tags).
Hello friends a newbie question...
The Issue is like this:
I have a static HTML file and I want to import just a portion of that file into another page. How can I do that.
Example Code:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Some title here</title>
<link rel="stylesheet" type="text/css" href="styles.css" />
</head>
<body>
<div id="box-1">
<div class="block">
<!-- Some code here -->
</div>
</div>
<div id="box-2">
<div class="block">
<!-- Some code here -->
</div>
</div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script src="script.js"></script>
</body>
</html>
Now what I want is to read this HTML file and import just this bit:
<div id="box-1">
<div class="block">
<!-- Some code here -->
</div>
</div>
Is there a way of doing it?
Kindly help.
Even a PHP, jQuery, Ajax or any other solution will also do. Please help me.
You can use jQuery's load() to specify only a certain container to be loaded:
$('#targetdiv').load('static.html #box-1');
Here's a solution that differs from the others: It performs a one-time import of a section of content from a large number of static html files/pages (in case that was what you were wanting). I used it successfully to import about 700 pages from straight html to a cms database.
// get the pages you want to import
$pages = array('page1.html',
'page2.html',
'page3.html'
);
foreach($pages as $p) {
$url = 'http://yourDomain.com/' . $p;
// load the webpage
$file = file_get_contents($url);
if($file) {
list($before,$content) = explode('<body>',$file); // chop off beginning
unset($before);
list($content) = explode('<div id="box-2">',$content); // chop off end;
$resultArray[] = trim($content);
// or do it this way to keep the filename associated with the content
// $resultArray[$p] = $content;
}//if file
} //endforeach;
// $resultArray holds your stripped content
// do something with $resultArray;
At the moment, I have a base HTML template file. When ever I want to make a new page, I copy the template and place some require_once statements in between specific tags. I was wondering if there's a better way that would make it unnecessary to copy the template each time. Here's a typical example:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" type="text/css" href="css/second.css" />
<script language="JavaScript" type="text/javascript"
src="js/validation_functions.js"></script>
<title>Order a Ticket for the ball</title>
</head>
<body>
<div id="banner">St. Tom's Ambulance Ball</div>
<!-- START[container] -->
<!-- "body" -->
<div id="container">
<!-- START[header] -->
<div id="header">
<!-- header -->
<div id="header_text">introduction</div>
<div id="header_cell2">the process</div>
<div id="header_cell3">start</div>
</div>
<!-- END[header -->
<!-- START[content] -->
<!-- "other container" -->
<div id="content">
<!-- START[form] -->
<div id="form">
<?php
require_once(realpath($config["directories"]["views"]."/index.form.view.php"));
?>
</div>
<!-- END[form] -->
<!-- START[data] -->
<!-- "main content" -->
<div id="data">
<?php
require_once(realpath($config["directories"]["views"]."/index.data.view.php"));
?>
</div>
<!-- END[data] -->
<!-- START[side] -->
<div id="side">
<?php
require_once(realpath($config["directories"]["views"]."/index.side.view.php"));
?>
</div>
<!-- END[side] -->
</div>
<!-- END[content] -->
<!-- START[footer] -->
<div id="footer">
<!-- footer -->
<div id="footer_text">
<ul>
<li>home</li>
<li>partners</li>
<li>projects</li>
<li>contact us</li>
</ul>
</div>
<div id="footer_cell2"> </div>
<div id="footer_cell3"> </div>
</div>
<!-- END[footer] -->
</div>
<!-- END[container] -->
</body>
</html>
EDIT: I have taken note of your suggestions to use GET. The new idea is to have each request url formed as index.php?page=page_name. This request would then be dealt with by a main controller which then sets the variables of the template based on the value of $_GET['page']. For this, the template will now be:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" type="text/css" href="css/second.css" />
<script language="JavaScript" type="text/javascript"
src="js/validation_functions.js"></script>
<title><?php h($title) ?></title>
</head>
<body>
<div id="banner">St. Tom's Ambulance Ball</div>
<!-- START[container] -->
<!-- "body" -->
<div id="container">
<!-- START[header] -->
<div id="header">
<!-- header -->
<div id="header_text"><?php h($header_1) ?></div>
<div id="header_cell2"><?php h($header_2) ?></div>
<div id="header_cell3"><?php h($header_3) ?></div>
</div>
<!-- END[header -->
<!-- START[content] -->
<!-- "other container" -->
<div id="content">
<!-- START[form] -->
<div id="form">
<?php
require_once(realpath($view_1));
?>
</div>
<!-- END[form] -->
<!-- START[data] -->
<!-- "main content" -->
<div id="data">
<?php
require_once(realpath($view_2));
?>
</div>
<!-- END[data] -->
<!-- START[side] -->
<div id="side">
<?php
require_once(realpath($view_3));
?>
</div>
<!-- END[side] -->
</div>
<!-- END[content] -->
<!-- START[footer] -->
<div id="footer">
<!-- footer -->
<div id="footer_text">
<ul>
<li>home</li>
<li>partners</li>
<li>projects</li>
<li>contact us</li>
</ul>
</div>
<div id="footer_cell2"> </div>
<div id="footer_cell3"> </div>
</div>
<!-- END[footer] -->
</div>
<!-- END[container] -->
</body>
</html>
Note: h() is a function that first of all removes all undesired entity tags before echoing a string.
On a related note, at the top of each page I have some controller files which are included with require_once. I was wondering if it would be possible to implement a function that simply includes files based on a specific input string (name of the functionality/page) i.e "index" in this way:
function include_controller($page){
switch($page){
case "index":
require_once(realpath($config["directories"]["controllers"]."/index_.php"));
break;
case "checkout":
require_once(realpath($config["directories"]["controllers"]."/checkout_.php"));
break;
default:
break;
}
}
Instead of hard coding the includes into each file, you could have a controller file in which you pass the page to be displayed through a $_GET variable. The controller then handles the logic and includes the appropriate page or pages. This is the way a lot of MVC frameworks do it.
Edit: To answer your second question, instead of using a switch, you could just check to make sure the file exists. If it does, include that file, otherwise output an error ("Page doesn't exists" or something similar).
function include_controller($page){
if (file_exists($config["directories"]["controllers"]."/$page_.php")) {
// page exists, include it
require_once($config["directories"]["controllers"]."/$page_.php"));
} else {
// page not found
}
}
Obviously you should probably make the function a little more robust and probably limit the files that will be included to a certain directory or something. Also make sure you properly filter the $page variable so users aren't able to access any file.
Keep this one file as your template file. Then for all the functionality in your site always hit this file. Lets sat this file is index.php. So all functionality requests go to index.php. But with different parameters so for functionality A.
index.php?function=a
For functionality b
index.php?function=b
you can add more parameters also.
Now on the basis of a,b and the set of parameters see what files you want to include as require once.
Like the others already said, it would be better to use some kind of MVC framework. Or at least use a template engine (e.g. Smarty). Your example is ok though, for the 90ies :)
You can get by with one template if you choose a different way of specifying what page is being requested, such as using a GET variable. You can load the pages in a database and specify each of the included pieces, then have one php 'template engine' that loads the requested page from the database and outputs the template with the right includes.
If your server supports it, you can references to things you want to include on all pages in .htaccess:
php_value auto_prepend_file "header.php"
php_value auto_append_file "footer.php"
(Found this on codingforums.com)