Иметь класс php, возвращающий значения массива и продолжающий цикл до конца

#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-комментария

Затем вновь созданная страница записывается в фактический файл, который затем включается.

Я совершенно новичок в ООП, так что для меня это довольно сложный материал. Я хотел бы знать, является ли это хорошим способом решения моей проблемы. А также, возможно ли предотвратить необходимость переписывать весь этот класс для каждой страницы?

В качестве примера, если бы я также хотел создать гостевую книгу, я бы хотел переписать класс таким образом, чтобы он мог принимать переданные переменные и создавать страницу оттуда, а не предварительно устанавливать много вещей, ограничивающих его одной «задачей», такой как извлечение продуктов. Но прежде чем я пойду дальше, я хотел бы знать, является ли это приемлемым способом сделать это.