#php #arrays #class
#php #массивы #класс
Вопрос:
Я пытаюсь создать веб-сайт, который позволяет легко добавлять / манипулировать темами, как это делают WordPress и другие системы CMS. Для этого я хотел бы сделать так, чтобы файл темы, который доставляет содержимое, использовал как можно меньше кода php. На данный момент это (чрезвычайно упрощенный) класс
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;
}
}
И извлекает его следующим образом:
$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
Но я хочу сделать извлечение более похожим на это:
<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>
Что в основном означает, что класс просто вернет значение понятным способом и автоматически продолжит цикл без необходимости пользователю добавлять *foreach($parents->get_parents() как $rowtable) * или что-то подобное в их файле темы.
Вот пример страницы WordPress, чтобы (надеюсь) проиллюстрировать, что я имею в виду. На этой странице извлекаются все сообщения для текущей категории WordPress, что я пытаюсь имитировать в своем скрипте, но вместо извлечения сообщений я хочу получить родительские элементы категории, но я не думаю, что важно объяснять это подробно.
<?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(); ?>
Примечание: Мой фактический вопрос вообще не имеет никакого отношения к WordPress, поэтому я не добавлял его в качестве тега.
ОБНОВЛЕНИЕ: я думаю, что мой вопрос, возможно, был неясен. Вот грязный пример (который, тем не менее, работает)
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>
Итак, в основном, index.php загружается пользователем, после чего количество продуктов в базе данных mysql берется из класса. Для каждого продукта, all_products.php вызывается с $indexxx, увеличенным на единицу.
Теперь единственное, что нужно сделать пользователю, это отредактировать HTML all_products.php и все продукты будут отображаться по-разному. Это то, к чему я стремлюсь, но чистым и ответственным способом. Не так, это беспорядок!
UPDATE2: я нашел лучший способ сделать это, но добавил его в качестве ответа. Казалось более подходящим и позволяет избежать того, чтобы этот вопрос становился длиннее / запутаннее, чем он есть.
Комментарии:
1. Если вы несколько форсируете определенный вывод (например, этот набор таблиц, например), ваши темы вообще не будут легко управляемыми. Вам следует рассмотреть возможность использования какого-либо механизма шаблонов, такого как Smarty, или создать пользовательский более простой. Если вы не хотите рассматривать сам php как механизм создания шаблонов, конечно
2. @DamienPirsy Я просто использовал его в качестве примера. Проблема, с которой я сталкиваюсь, заключается в автоматическом цикле и переменных php, которые имеют смысл, а не возвращают весь массив и используют $arrayname[x] для эха значения. И как она стоит в этом примере пользователь может выбрать, чтобы не использовать таблицы на всех и просто поставить <?php echo $cat_title; ?> есть ID категории <?php echo $cat_id; ?> и на уровне <?php echo $cat_level; ?> <br /> который является точно, что я хочу, чтобы они были в состоянии сделать.
Ответ №1:
Хорошо, я немного приближаюсь к тому, что хочу, поэтому я добавляю это в качестве ответа.
Шаблон:
<?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>amp;nbsp;<!-- [categories][children] --></td><td>
{end-loop-categories}
</table>
</div>
<div id="middle-right-section">
<table id="hor-minimalist-a">
<thead>
<th scope="col">amp;nbsp;</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"); ?>
Класс:
<?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
?>
php, запрошенный посетителем веб-сайта, который вызовет текущий шаблон all_products.php
include_once("class.php");
$listproducts = new listproducts();
include_once($listproducts->listproduct());
Итак, что это на самом деле, это просто string_replacing HTML-комментарии в файле шаблона с результатом PHP, который я хочу там. Если это цикл, я выделяю html-код, который я хочу зациклить -> Запускаю пустую строковую переменную -> Повторяю этот HTML-код, добавляя каждый цикл к строковой переменной -> Используйте эту строковую переменную для замены HTML-комментария
Затем вновь созданная страница записывается в фактический файл, который затем включается.
Я совершенно новичок в ООП, так что для меня это довольно сложный материал. Я хотел бы знать, является ли это хорошим способом решения моей проблемы. А также, возможно ли предотвратить необходимость переписывать весь этот класс для каждой страницы?
В качестве примера, если бы я также хотел создать гостевую книгу, я бы хотел переписать класс таким образом, чтобы он мог принимать переданные переменные и создавать страницу оттуда, а не предварительно устанавливать много вещей, ограничивающих его одной «задачей», такой как извлечение продуктов. Но прежде чем я пойду дальше, я хотел бы знать, является ли это приемлемым способом сделать это.