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>
开发者_StackOverflow社区</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><a href="<!-- [categories][parents][url] -->"><!-- [categories][parents][name] --></a></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.
精彩评论