Keeping HTML files separated from the PHP files (template based) - php

I am trying to keep all the PHP files separated from the HTML files. Sort of a template based project but without using any template engines as they are mostly bloated and the fact that you will need to learn another language which is not PHP at all.
Anyway, I have the following code in my index.php file:
<?php
$query = "SELECT id FROM products ORDER by id";
$product_list = "";
if ($stmt = mysqli_prepare($db_conx, $query)) {
/* execute statement */
mysqli_stmt_execute($stmt);
/* bind result variables */
mysqli_stmt_bind_result($stmt, $id);
/* fetch values */
while (mysqli_stmt_fetch($stmt)) {
$product_list .= "
}
}
?>
<?php include "template.php"; ?>
And I have this code in my template.php file:
<html>
<head>
</head>
<body>
<div class='prod_box'>
<div class='center_prod_box'>
<div class='product_title'><a href='#'>$product_name</a></div>
<div class='product_img'><a href='#'><img src='images/" . $id . "Image1.jpg' alt='' border='0' /></a></div>
<div class='prod_price'><span class='reduce'>350$</span> <span class='price'>270$</span></div>
</div>
<div class='prod_details_tab'> <a href='#' class='prod_buy'>Add to Cart</a> <a href='#' class='prod_details'>Details</a> </div>
</div>
</body>
</html>
When I run the code, I basically get the HTML page displayed exactly as you see it above. So no data is being shown from the MySQL database!
EDIT:
I tried using the following code in my while loop and still the same:
$id = $row["id"];
$product_name = $row["product_name"];
$price = $row["price"];
$shipping = $row["shipping"];
$category = $row["category"];
Could someone please help me out with this?

I would suggest using a template system to parse your template file.
Just something quick and dirty:
class Example {
// This will be used to save all the variables set trough the set() function within the class as an array
private $variables = array();
function set($name,$value) {
// Here we are going to put the key and value in the variables array
$this->variables[$name] = $value;
}
function Template($file) {
// First set the file path of the template, the filename comes from the Template({filename}) function.
$file = '/templates/'.$file.'.php';
// Here we are going to extract our array, every key will be a variable from here!
extract($this->variables);
// Check if it is actually a file
if (!is_file($file)) {
throw new Exception("$file not found");
// Check if the file is readable
} elseif(!is_readable($file)) {
throw new Exception("No access to $file");
} else {
// if both are fine we are going to include the template file :)
include($file);
}
}
}
and use it like this:
$class = new Example;
$class->set("data", $data);
// like passing a name:
$class->set("user", $username);
$class->Template("filename");
Then in your template file you can use $data and $user with their contents.
Also, in your template file you're not displaying the variable because it's not in between of PHP tags. Here's two examples for you, one short and the other in the normal format:
<?=$productname?>
// or :
<?php echo $productname; ?>
Oh, and you actually do nothing here:
while (mysqli_stmt_fetch($stmt)) {
$product_list .= "
}
}
You NEED to close the opening " with "; and nothing is added to $product_list.

Honestly, you should use a template system. If you don't want to hinder with learning how they work, there is a very easy approach: create a very simple one yourself. You'll need it sooner or later. The below solution should be very easy, and it's copy-pasteable.
The basic operation of such system is that you:
Load the template file with placeholder strings.
Process the template file (replace placeholders with actual values).
Output (or return) the HTML with now processed text.
An example class that is very easy to comprehend might be this:
class HtmlPage
{
private $html;
# Loads specified template file into $html
public function Load($template)
{
if (!file_exists($template)) {
echo "Specified template ($template) does not exist.";
return false;
}
$this->html = file_get_contents($template);
return true;
}
# Takes in an array of data, key is the placeholder replaced, value is the new text
public function Process($data_array)
{
if (!is_array($data_array)) return;
foreach ($data_array as $search => $replace)
{
# Add brackets so they don't have to be manually typed out when calling HtmlPage::Process()
$search = "{$search}";
$this->html = str_replace($search, $replace, $this->html);
}
}
# Returns the page
public function GetHtml()
{
return $this->html;
}
}
Can be used as:
$page_title = "My fancy page title";
$page_text = "All your base are belong to us.";
$page = new HtmlPage();
$page->Load('html/templates/mypage.html');
$page->Process(array(
'TITLE' => $page_title,
'TEXT' => $page_text
));
echo $page->GetHtml();
The above code will replace
<html>
<head>
{TITLE}
</head>
<body>
<p>{TEXT}</p>
</body>
</html>
...to...
<html>
<head>
My fancy page title
</head>
<body>
<p>All your base are belong to us.</p>
</body>
</html>
In your case, this will work like the following:
html/templates/product-item.html:
<div class='prod_box'>
<div class='center_prod_box'>
<div class='product_title'>
<a href='#'>{PRODUCT_NAME}</a>
</div>
<div class='product_img'>
<a href='#'><img src='images/{PRODUCT_ID}/Image1.jpg' alt='' border='0' /></a>
</div>
<div class='prod_price'>
<span class='reduce'>{PRODUCT_PRICE_REDUCE}</span> <span class='price'>{PRODUCT_PRICE}</span>
</div>
</div>
<div class='prod_details_tab'>
<a href='#' class='prod_buy'>Add to Cart</a> <a href='#' class='prod_details'>Details</a>
</div>
</div>
PHP code:
<?php
$query = "SELECT * FROM products ORDER by id";
$product_list = "";
if ($stmt = mysqli_prepare($db_conx, $query))
{
/* execute statement */
mysqli_stmt_execute($stmt);
/* bind result variables */
mysqli_stmt_bind_result($stmt, $id);
/* fetch values */
$result = mysqli_stmt_get_result($stmt);
while ($product = mysqli_fetch_array($result)) {
$product_html = new HtmlPage();
$product_html->Load('html/templates/product-list.html');
$product_html->Process(array(
'PRODUCT_NAME' => $product['name'];
'PRODUCT_ID' => $product['id'];
'PRODUCT_PRICE' => $product['price'];
'PRODUCT_PRICE_REDUCE' => $product['price_reduce'];
));
$product_list .= $product_html->GetHtml();
}
}

In index.php
<?php
$query = "SELECT id FROM products ORDER by id";
$product_list = "";
if ($stmt = mysqli_prepare($db_conx, $query)) {
/* execute statement */
mysqli_stmt_execute($stmt);
/* bind result variables */
mysqli_stmt_bind_result($stmt, $id);
/* fetch values */
}
define("PRODUCT_NAME",$row["product_name"]);
define("PRODUCT_ID",$row["id"]);
define("PRODUCT_PRICE",$row["price"]);
define("PRODUCT_SHIPPING",$row["shipping"]);
define("PRODUCT_CATEGORY",$row["category"]);
?>
<?php include "template.php"; ?>
and in template.php
<html>
<head>
</head>
<body>
<div class='prod_box'>
<div class='center_prod_box'>
<div class='product_title'><a href='#'><?=PRODUCT_NAME?></a></div>
<div class='product_img'><a href='#'><img src='images/<?=PRODUCT_ID?>/Image1.jpg' alt='' border='0' /></a></div>
<div class='prod_price'><span class='reduce'>350$</span> <span class='price'>270$</span></div>
</div>
<div class='prod_details_tab'> <a href='#' class='prod_buy'>Add to Cart</a> <a href='#' class='prod_details'>Details</a> </div>
</div>
</body>
</html>

Your code is a bit of a mess, you need to go back to the basics: your statement is returning $id and not $product as you mentioned. To return anything from the database, in your template.html do:
<html>
<body>
<!-- More html here ... -->
<div class='product_title'>
<!-- Return value like this -->
<a href='#'><?php echo $product_name; ?></a>
</div>
</body>
</html>
Make sure you check the value exists first.

You need to use the extract() function in PHP to get this sorted out. It will then start working as a Controller - View architecture that you are looking for.
For example:
<?php
$query = "SELECT id FROM products ORDER by id";
$product_list = "";
if ($stmt = mysqli_prepare($db_conx, $query)) {
/* execute statement */
mysqli_stmt_execute($stmt);
/* bind result variables */
mysqli_stmt_bind_result($stmt, $id);
/* fetch values */
while (mysqli_stmt_fetch($stmt)) {
$product_list .= "";
}
}
$data['product_list'] = $product_list;
$view = 'template.php';
loadTemplate($view, $data);
function loadTemplate($view, $data)
{
extract($data);
include($template);
}
?>
Then directly use $product_list in the view section. This should do it.
Working example:
<?php
$data['test'] = 'This is a working example';
$view = 'workingExampleView.php';
loadTemplate($view,$data);
function loadTemplate($viewName,$viewData)
{
extract($viewData);
include($viewName);
}
?>
Create a new File naming it workingExampleView.php:
<html>
<body>
<span><?php echo $test; ?></span>
</body>
</html>

Related

Why can't i access variable inside if loops in php

I am making simple shopping cart and i got really stucked with final price a.k.a $fp variable.
there is always: Notice: Undefined variable: fp in C:\xampp\htdocs...
the thing is everything is working, data from database are fetched on site, price included but when i want to display $fp(final price) it shows that error.
I tried setting it to 0 in else statement after if($row['ID'] == $id) loop, nothing happened
I tried to make it global like:
global $fp;
$fp = $fp + intval($row['price']);
when i did that, error disappeared but it just didnt do anything(empty space). maybe i am just sitting too long looking at that but i just can't wrap my head around why i cant acess that variable or what is happening.
<section class="cart">
<?php
if(isset($_SESSION['cart'])){
$product_id = array_column($_SESSION['cart'],'product_id');
$sql = "SELECT * FROM muzi;";
$result = mysqli_query($conn, $sql);
while($row = mysqli_fetch_assoc($result)){
foreach($product_id as $id){
if($row['ID'] == $id){
echoItem($row['fotografia'],$row['price'],$row['znacka'],$row['konkretne'],$size);
$fp = $fp + intval($row['price']);
}
}
}
}else{
echo "<h5>Cart is empty</h5>";
}
?>
<h2 class="h2-cart-item">PRICE: <?php $fp;?> €</h2>
</section>
function echoItem($productIMG, $productPrice, $znacka, $typ_oblecenia){
$product = "
<article class='clearfix'>
<img src='../img/$productIMG' alt='hihi' style='width: 10%;'>
<div class='info-text-cart'>
<p>specific type: $typ_oblecenia</p>
<p>Brand: $znacka</p>
<button><i class='fas fa-times'></i></button>
</div>
<div class='important-info-cart'>
<p>Price: $productPrice €</p>
<p>quantity: 1</p>
</div>
</article>
";
echo $product;
}
ps: i have everything in terms of typing right. I just translated some things that are involved in this to english so it makes more sense.
$fp has never been declared as mentioned before.
If you declare it as global (or not) you should be able to use it on the second code block, the reason that you didn't see anything when you tried is because you forgot to echo it.
A working example would be:
<section class="cart">
<?php
$fp = 0;
if(isset($_SESSION['cart'])){
$product_id = array_column($_SESSION['cart'],'product_id');
$sql = "SELECT * FROM muzi;";
$result = mysqli_query($conn, $sql);
while($row = mysqli_fetch_assoc($result)){
foreach($product_id as $id){
if($row['ID'] == $id){
echoItem($row['fotografia'],$row['price'],$row['znacka'],$row['konkretne'],$size);
$fp = $fp + intval($row['price']);
}
}
}
}else{
echo "<h5>Cart is empty</h5>";
}
?>
<h2 class="h2-cart-item">PRICE: <?php echo $fp;?> €</h2>
</section>

Menu created with MySQL only works within website not outside

I hope somebody can help me, because i got an menu that is auto generated via my MySQL db.
Because i got the menu to work inside the website and with that i mean it works with "test.dk/about" but the a href is empty when it's going out of the website like "http://google.com"...
btw it's just a very simple UL LI menu no dropdown or something.
Here is my script
static function build_menu()
{
$result = mysql_query("SELECT * FROM menu");
$menu = array();
while ($row = mysql_fetch_assoc($result)) {
if ($row["is_external"]) {
$url = $row["url"];
} else if (empty($row["is_external"])) {
$url = get_page_url($row["page_id"]);
}
$menu[] = array("name" => $row["name"], "page_id" => $row["page_id"], "is_external" => $row["url"], "url" => $url);
}
return $menu;
}
static function get_page_url($page_id)
{
$result = mysql_query("SELECT view_id FROM page WHERE id = '$page_id'");
$result = mysql_fetch_assoc($result);
$view_id = $result["view_id"];
$result = mysql_query("SELECT listen_path FROM view WHERE id = '$view_id'");
$result = mysql_fetch_assoc($result);
$listen_path = $result["listen_path"];
return $listen_path;
}
static function render()
{
$result = mysql_query("SELECT * FROM menu"); ?>
<div class="menu">
<ul><?php while ($item = mysql_fetch_assoc($result)) { ?>
<li><?php echo $item["name"] ?>
</li> <?php } ?></ul></div><?php
}
How can i fix it, so it works both internal and external?
<div class="menu"> <ul> <li>Homepage</li> <li>About</li> <li>Develop</li> <li>Support</li>
This should be <li>Support</li>; </ul> </div>
You only check for an external link in the function build_menu(), but this function isn't called anywhere from your render() function.
The render() function only calls get_page_url() which doesn't distinguish between internal and external links.
Href parameter of external URL must start with protocol declaration, so with "http://" in your case.
So change your code in condition inside the function "build_menu", if the URL is external, add "http://" to it, something like this:
$url = 'http://'.$row["url"];
I got it work after a while!
I simply just created an If else statement in the render function
static function render(){
$menu_items = self::get();
?><div class="menu"><ul><?php while ($item = mysql_fetch_assoc($menu_items)) { ?>
<li><a href="<?php
if(empty($item["is_external"]))
{
echo self::get_page_url($item["page_id"]);
}
else if($item["is_external"] = 1)
{
echo $item["url"];
}
?>"><?php echo $item["name"] ?></a>
</li> <?php } ?></ul></div><?php
}

OOP PHP MySQL return multiple rows and variable

I am new w/ OPP and big pardon if my question maybe too simple :)
Table category, navigation, etc contains multiple rows (category : samsung, apple, etc; and navigation : about us, terms, etc) and both stand as Menu in all pages (home, product,etc)
My old php code and work good is below
<div id="categories">
<ul>
<?
$mydbcategories = new myDBC();
$resultcategories = $mydbcategories->runQuery("SELECT * FROM `category`");
while ($rowcategories = $mydbcategories->runFetchArray($resultcategories)) {
echo '<li>'.$rowcategories[title].'</li>';
}
?>
</ul>
</div>
<div id="navigation">
<ul>
<?
$mydbnavigation = new myDBC();
$resultnavigation = $mydbnavigation->runQuery("SELECT * FROM `navigation`");
while ($rownavigation = $mydbnavigation->runFetchArray($resultnavigation)) { echo '<li>'.$rownavigation [title].'</li>';
}
?>
</ul>
</div>
I would like to implement OOP PHP and create class then store in classes.php
<?
class Menu{
var $title;
var $url;
function setMenu($db){
$mydbMenu= new myDBC();
$resultmenu = $mydbMenu->runQuery("SELECT * FROM `$db`");
$resultmenurows = mysqli_num_rows($resultmenu);
while ($rowmenu = $mydbMenu->runFetchArray($resultmenu)){
$this->title = $rowmenu[title];
$this->url = $rowmenu[url];
}
}
function getTitle() { return $this->title;}
function getUrl() { return $this->url;}
}
?>
Then i'm edit my old code with new one below;
<div id="categories">
<ul>
<?
$catmenu = new Menu();
while ($catmenu ->setMenu('category')) {
echo '<li>'.$catmenu->getTitle().'</li>';
}
?>
</ul>
</div>
<div id="navigation">
<ul>
<?
$navmenu = new Menu();
while ($navmenu ->setMenu('category')) {
echo '<li>'.$navmenu ->getTitle().'</li>';
}
?>
</ul>
</div>
I tested and error maybe because there are multiple rows (from table) in the setMenu func.
How can i return this multiple rows ? should i use array ?
Please help me to solve this and any reply really very appreciate
You are coding PHP4 OOP style, this is very outdated. Don't use var, use public, protected, private.
$this->title = $rowmenu[title] in here, title is used as a constant (no quotes), proper: $this->title = $rowmenu['title'], same with $rowcategories[title]
"SELECT * FROM $db" is this correct? Or do you mean SELECT * FROM menu WHERE xxx='" . $db . "', do you catch errors if the lookup fails?
You should also look at PHP design patterns and code style to improve!
Try following PHP code
<?
class Menu {
var $title;
var $url;
function setMenu($db) {
$mydbMenu = new myDBC();
$resultmenu = $mydbMenu->runQuery("SELECT * FROM `$db`");
$resultmenurows = mysqli_num_rows($resultmenu);
$this->title = array();
$this->url = array();
while ($rowmenu = $mydbMenu->runFetchArray($resultmenu)) {
$this->title[] = $rowmenu['title'];
$this->url[] = $rowmenu['url'];
}
}
function getTitle($ind) {
return $this->title[$ind];
}
function getUrl($ind) {
return $this->url[$ind];
}
}
?>
And HTML
<div id="categories">
<ul>
<?
$catmenu = new Menu();
$catmenu->setMenu('category');
$i = 0;
while ($catmenu->getTitle($i)) {
echo '<li>' . $catmenu->getTitle($i) . '</li>';
$i++;
}
?>
</ul>
</div>
<div id="navigation">
<ul>
<?
$navmenu = new Menu();
$navmenu->setMenu('navigation');
while ($navmenu->getTitle($i)) {
echo '<li>' . $navmenu->getTitle($i) . '</li>';
$i++;
}
?>
</ul>
</div>

Have a php class return array values and keep looping until end

I'm trying to create a website that allows for easy theme adding/manipulation like wordpress and other CMS systems do. To do this I'd like to make it so the theme file that delivers the content uses as little php code as possible. At the moment this is the (extremely simplified) class
class getparents {
var $parentsarray;
function get_parents() {
$this->parentsarray = array();
$this->parentsarray[] = array('Parent0',3,1);
$this->parentsarray[] = array('Parent1',8,2);
$this->parentsarray[] = array('Parent2',2,3);
return $this->parentsarray;
}
}
And retrieving it like this:
$parents = new getparents();
?><table><?php
foreach($parents->get_parents() as $rowtable)
{
echo "<tr><td>$rowtable[0] has category ID $rowtable[1] and is on level $rowtable[2] </td></tr>";
}
?></table><?php
But I want to make the retrieving more like this:
<table>
<tr><td><?php echo $cat_title; ?> has category ID <?php echo $cat_id; ?> and is on level <?php echo $cat_level; ?> </td></tr>
</table>
Which basically mean the class would just return the value in an understandable way and automatically keep on looping without the user having to add *foreach($parents->get_parents() as $rowtable)* or something similar in their theme file.
Here's an example wordpress page to (hopefully) illustrate what I mean. This page retrieves all posts for the current wordpress category which is what I'm trying to mimic in my script, but instead of retrieving posts I want to retrieve the category's parents, but I don't think it's important to explain that in detail.
<?php
/**
* The template for displaying Category Archive pages.
*
* #package WordPress
* #subpackage Twenty_Ten
* #since Twenty Ten 1.0
*/
get_header(); ?>
<div id="container">
<div id="content" role="main">
<h1 class="page-title"><?php
printf( __( 'Category Archives: %s', 'twentyten' ), '<span>' . single_cat_title( '', false ) . '</span>' );
?></h1>
<?php
$category_description = category_description();
if ( ! empty( $category_description ) )
echo '<div class="archive-meta">' . $category_description . '</div>';
/* Run the loop for the category page to output the posts.
* If you want to overload this in a child theme then include a file
* called loop-category.php and that will be used instead.
*/
get_template_part( 'loop', 'category' );
?>
</div><!-- #content -->
</div><!-- #container -->
<?php get_sidebar(); ?>
<?php get_footer(); ?>
Note: My actual question doesn't have anything to do with wordpress at all so I didn't add it as a tag.
UPDATE: I think my question may have been unclear. Here's a messy example (that works nevertheless)
index.php
<?php
include_once("class.php");
include_once("config.php");
if(isset($_GET['catid']))
{
$getproducts = new getproducts($_GET['catid']);
$catproductsarray = $getproducts->getarray();
$indexxx = 0;
foreach($catproductsarray as $rowtable)
{
include("templates/$template/all_products.php");
$indexxx++;
}
}
class.php
class getproducts {
var $thearrayset = array();
public function __construct($indexx) {
$this->thearrayset = $this->makearray($indexx);
}
public function get_id($indexxx) {
echo $this->thearrayset[$indexxx]['id'];
}
public function get_catID($indexxx) {
echo $this->thearrayset[$indexxx]['catID'];
}
public function get_product($indexxx) {
echo $this->thearrayset[$indexxx]['name'];
}
public function makearray($indexx) {
$thearray = array();
if(!is_numeric($indexx)){ die("That's not a number, catid."); };
$resulttable = mysql_query("SELECT * FROM products WHERE catID=$indexx");
while($rowtable = mysql_fetch_array($resulttable)){
$thearray[] = $rowtable;
}
return $thearray;
}
public function getarray() {
return $this->thearrayset;
}
}
templates/default/all_products.php
<!-- The below code will repeat itself for every product found -->
<table>
<tr><td><?php $getproducts->get_id($indexxx); ?> </td><td> <?php $getproducts->get_catID($indexxx); ?> </td><td> <?php $getproducts->get_product($indexxx); ?> </td></tr>
</table>
So basically, index.php gets loaded by user after which the amount of products in mysql database is taken from the class. For every product, all_products.php gets called with $indexxx upped by one.
Now the only thing the user has to do is edit the HTML all_products.php and the products will all be displayed differently. This is what I'm going for, but in a clean, responsible way. Not like this, this is a mess!
UPDATE2: I found a better way to do it, but added it as an answer. Seemed more fitting and pevents this question from getting any longer/messyer than it already is.
Ok I'm getting a little bit closer to what I want, so I'm adding this as an answer.
The template:
<?php include("templates/$template/header.php"); ?>
<!-- [product][description][maxchars=##80##][append=##...##] -->
<!-- [categories][parents][name][append= ->] --><!-- maxchars=false means dont cut description -->
<!-- [categories][children][prepend=nothing] --><!-- prepend=nothing means no prepend -->
<div id="middle-left-section">
<table>
{start-loop-categories-parents}
<tr><td><!-- [categories][parents][name] --></td><td>
{end-loop-categories-parents}
</table>
<table>
<tr><td><!-- [categories][current] --></tr></td>
{start-loop-categories}
<tr><td> <!-- [categories][children] --></td><td>
{end-loop-categories}
</table>
</div>
<div id="middle-right-section">
<table id="hor-minimalist-a">
<thead>
<th scope="col"> </th>
<th scope="col">Name</th>
<th scope="col" width="200px">Description</th>
<th scope="col">Price</th>
</thead>
<tbody>
{start-loop-product}
<tr><td><img src="fotos/<!-- [product][thumb] -->"></img></td><td><!-- [product][name] --></td><td><!-- [product][description] --></td><td><!-- [product][price] --></td></tr>
{end-loop-product}
</tbody>
</table>
</div>
<div style="clear: both;"/>
</div>
<?php include("templates/$template/footer.php"); ?>
The class:
<?php
///////////////////////////
//Includes and functions//
/////////////////////////
include_once("config.php");
include_once("includesandfunctions.php");
function get_between($input, $start, $end)
{
$substr = substr($input, strlen($start)+strpos($input, $start), (strlen($input) - strpos($input, $end))*(-1));
return $substr;
}
function get_between_keepall($input, $start, $end)
{
$substr = substr($input, strlen($start)+strpos($input, $start), (strlen($input) - strpos($input, $end))*(-1));
return $start.$substr.$end;
}
class listproducts {
var $thearrayset = array();
var $file;
var $fp;
var $text;
var $products;
var $productskeepall;
var $done;
var $returnthisloopdone;
public function __construct() {
global $template;
//Get items from mysql database and put in array
$this->thearrayset = $this->makearray();
//Read file
$this->file = "templates/$template/all_products.php";
$this->fp = fopen($this->file,"r");
$this->text = fread($this->fp,filesize($this->file));
//Set other vars
$this->products = '';
$this->productskeepall = '';
$this->returnthisloopdone = '';
$this->done = ''; //Start $done empty
}
public function makearray() {
$thearray = array();
$resulttable = mysql_query("SELECT * FROM products");
while($rowtable = mysql_fetch_array($resulttable)){
$thearray[] = $rowtable; //All items from database to array
}
return $thearray;
}
public function getthumb($indexxx) {
$resulttable = mysql_query("SELECT name FROM mainfoto where productID=$indexxx");
while($rowtable = mysql_fetch_array($resulttable)){
return $rowtable['name']; //Get picture filename that belongs to requested product ID
}
}
public function listproduct()
{
global $template;
$this->products = get_between($this->done,"{start-loop-product}","{end-loop-product}"); //Retrieve what's between starting brackets and ending brackets and cuts out the brackets
$this->productskeepall = get_between_keepall($this->done,"{start-loop-product}","{end-loop-product}"); //Retrieve what's between starting brackets and ending brackets and keeps the brackets intact
$this->returnthisloopdone = ''; //Make loop empty in case it's set elsewhere
for ($indexxx = 0; $indexxx <= count($this->thearrayset) - 1; $indexxx++) //Loop through items in array, for each item replace the HTML comments with the values in the array
{
$this->returnthis = $this->products;
$this->returnthis = str_replace("<!-- [product][thumb] -->", $this->getthumb($this->thearrayset[$indexxx]['id']), $this->returnthis);
$this->returnthis = str_replace("<!-- [product][catid] -->", $this->thearrayset[$indexxx]['catID'], $this->returnthis);
$this->returnthis = str_replace("<!-- [product][name] -->", $this->thearrayset[$indexxx]['name'], $this->returnthis);
preg_match('/(.*)\[product\]\[description\]\[maxchars=##(.*)##\]\[append=##(.*)##\](.*)/', $this->done, $matches); //Check if user wants to cut off description after a certain amount of characters and if we need to append something if we do (like 3 dots or something)
$maxchars = $matches[2];
$appendeez = $matches[3];
if($maxchars == 'false'){ $this->returnthis = str_replace("<!-- [product][description] -->", $this->thearrayset[$indexxx]['description'], $this->returnthis);
}else{ $this->returnthis = str_replace("<!-- [product][description] -->", substr($this->thearrayset[$indexxx]['description'],0,$maxchars).$appendeez, $this->returnthis);
}
$this->returnthis = str_replace("<!-- [product][price] -->", $this->thearrayset[$indexxx]['price'], $this->returnthis);
$this->returnthisloopdone .= $this->returnthis; //Append string_replaced products section for every item in array
}
$this->done = str_replace($this->productskeepall, $this->returnthisloopdone, $this->done);
//Write our complete page to a php file
$myFile = "templates/$template/cache/testfile.php";
$fh = fopen($myFile, 'w') or die("can't open file");
$stringData = $this->done;
fwrite($fh, $stringData);
fclose($fh);
return $myFile; //Return filename so we can include it in whatever page requests it.
}
} //End class
?>
The php requested by the website visitor, which will call the current template's all_products.php
include_once("class.php");
$listproducts = new listproducts();
include_once($listproducts->listproduct());
So what this really is, is just string_replacing the HTML comments in the template file with the PHP result I want there. If it's a loop, I Single out the html code I want to loop -> Start an empty string variable -> Repeat that HTML code, appending each loop to the string variable -> Use this string variable to replace the HTML comment
The newly built page is then written to an actual file, which is then included.
I'm completely new to OOP, so this is pretty elaborate stuff for me. I'd like to know if this is a good way to tackle my problem. And also, is it possible to prevent having to rewrite that entire class for every page?
As an example, if I also wanted to build a guestbook I'd like to rewrite the class in a way that it can accept passed variables and build the page from there, rather than pre-setting alot of stuff limiting it to one 'task' such as retrieving products. But before I go any further I'd like to know if this is an a-okay way to do this.

PHP Procedural To OOP

I'm trying to convert my procedural code to oop.
<?php
$dbc = get_dbc();
$info = mysqli_query($dbc, "SELECT info_id, info_title FROM text") or die("Error: ".mysqli_error($dbc));
while ($info_row = mysqli_fetch_array($info))
{
$info_id = $info_row['info_id'];
$info_title = $info_row['info_title'];
?>
<div style="width: 100%;">
<div style="float: left;">
<?php echo $info_id; ?>
</div>
<div style="float: left;">
<?php echo $info_title; ?>
</div>
<div style="clear: both;"></div>
</div>
<?php } ?>
My incomplete attempt at classes/objects without the HTML styling:
<?php
class InfoTest {
private $info_id;
private $info_title;
public function __construct() {
$dbc = get_dbc();
$info = $dbc->query ("SELECT info_id, info_title FROM text");
if ($dbc->error) {
printf("Error: %s\n", $dbc->error);
}
while ($info_row = $info->fetch_array())
{
$info_id = $info_row['info_id'];
$info_title = $info_row['info_title'];
}
$info->free();
$this->info_id = $info_id;
$this->info_title = $info_title;
}
public function setInfoID() {
$this->info_id = $info_id;
}
public function getInfoID() {
return $this->info_id;
}
public function setInfoTitle() {
$this->info_title = $info_title;
}
public function getInfoTitle() {
return $this->info_title;
}
public function __destruct() {
}
}
?>
<?php
$display = new InfoTest();
echo $display->getInfoID();
echo $display->getInfoTitle();
?>
My procedural code prints out: 1 One 2 Two.
My oop code prints out: 2 Two
From my understanding the oop prints out that way because $info_id and $info_title aren't arrays, and only print out the last stored information.
So, if I change:
$info_id = $info_row['info_id'];
$info_title = $info_row['info_title'];
To:
$info_id[] = $info_row['info_id'];
$info_title[] = $info_row['info_title'];
And print the arrays, it displays all the information I want, but how to display it in non-array form?
Is what I'm doing so far correct or am I approaching this wrong?
You're doing it wrong. In your procedural example you're iterating over the data a row at a time; in your OO example, if you treat them as arrays and then print them, you're going through the data a column at a time instead. Rather than separating the data into separate ids and titles, I would treat them as a bundle (i.e. similar to how you did it in the procedural version) - an id goes with a title, not other ids, right?
So, for example, you might have a member variable
private $texts = array();
and then in your constructor, do:
while ($info_row = $info->fetch_array()) {
$text = array(
'id' => $info_row['info_id'],
'title' => $info_row['info_title']
);
$this->texts[] = $text;
}
and then provide a method to get at this array of arrays:
public function getTexts() {
return $this->texts;
}
Finally, you could iterate over it very similarly to how you did in the procedural example:
<?php
$display = new InfoTest();
foreach ($display->getTexts() as $text) {
?>
<!-- html goes here -->
<?php echo $text['info_id']; ?>
<!-- more html -->
<?php echo $text['info_title']; ?>
<!-- other html -->
<?
}
?>
Stepping back - you could ask if all this is really necessary. There's nothing inherently wrong with procedural PHP - if it does what you need it to do and does it clearly, you might be better off favoring simple over complex here.
Because info id is an array in your object the corresponding function to get the value should take an offset. Or even better you should look at your class implementing iterator so that you can just do foreach over your object
Before switching to OOP I would first of all modularize the code and start to segment into functional parts that have separated logic from each other, e.g. database access and templating:
<?php
/**
* infos provider
*
* #return array
*/
function get_infos()
{
$infos = array();
$dbc = get_dbc();
$info = mysqli_query($dbc, "SELECT info_id, info_title FROM text") or die("Error: ".mysqli_error($dbc));
while ($info_row = mysqli_fetch_array($info))
{
$infos[] = (object) $info_row;
}
return $infos;
}
foreach(get_infos() as $info)
{
?>
<div style="width: 100%;">
<div style="float: left;">
<?php echo $info->info_id; ?>
</div>
<div style="float: left;">
<?php echo $info->info_title; ?>
</div>
<div style="clear: both;"></div>
</div>
<?php } ?>
Then move the database related functions into a file of it's own to decouple it from the "templates". After that's done you can think about further steps to refactor. I suggest the following read (which is merely independent to the named framework): When flat PHP meets symfony.

Categories