保持演示文稿(HTML)和逻辑(PHP)分开

时间:2016-06-17 04:55:14

标签: php mysql model-view-controller

我试图在不使用像Smarty这样的模板引擎的情况下保持演示和逻辑分离。到目前为止我所做的工作是有效的,但我不知道如果不在我的演示文稿中添加更多PHP而不是我想做的事情。例如,现在我有这样的事情:

product_list.php

    try {
        $query = $conn->prepare("SELECT p.id, p.name, p.description, IFNULL(url, title) AS url, GROUP_CONCAT(c.category SEPARATOR ', ') AS category,
            FROM products p
            LEFT JOIN product_categories pc ON p.id = pc.product_id
            LEFT JOIN categories c ON pc.category_id = c.id
            WHERE p.active = 1
            GROUP BY p.id");
        $query->execute();
        $result = $query->fetchAll(PDO::FETCH_ASSOC);
    }
    catch (PDOException $e) {
            echo $e->getMessage();
    }
include('templates/product_list_tpl.php');

product_list_tpl.php

<div class="card">
    <div class="product-list with-header">
        <div class="product-list-header center-align">
            <h2><?= $header_title; ?></h2>
        </div>
        <?php foreach ($result as $row): ?>
            <!-- Some Product Info -->
            Category:&nbsp;<?= $row['category']; ?>
        <?php endforeach; ?>
    </div>
</div>

在上面的例子中,有些产品会有一个类别,有些会有多个。它们在逗号分隔列表中很好地显示,但我想将类别名称变为链接。我知道我可以做类似下面的事情,但对我来说似乎很麻烦。

<div class="card">
    <div class="product-list with-header">
        <div class="product-list-header center-align">
            <h2><?= $div_title; ?></h2>
        </div>
        <?php foreach ($result as $row): ?>
            <?php $categories = explode(', ', $row['category']); ?>
            <div class="product-list-item avatar">
                <img src="img/product/<?= $row['id']; ?>.jpg" alt="<?= $row['title']; ?>" class="square">
                <a href="product/<?= generate_link($row['url']); ?>" class="title bold"><?= $row['title']; ?></a>
                <p class="caption"><?= $row['caption']; ?></p>
                <div class="item-bottom">
                    <span class="responsive"><?= $row['description']; ?></span>
                    <p>
                        Category:&nbsp;
                        <?php foreach ($categories as $key => $category): ?>
                            <a href="category/<?= strtolower($category); ?>"><?= $category; ?></a>
                            <?= (sizeof($categories) > 1 && $key == end($categories)) ? ',&nbsp;' : ''; ?>
                        <?php endforeach; ?>
                    </p>
                    <p>
                        <span>Rating:&nbsp;<?= $row['rating']; ?></span>
                        <span class="right">Rated&nbsp;<?= $row['rated']; echo ($row['rated'] == 1) ? '&nbsp;time' : '&nbsp;times'; ?></span>
                    </p>
                </div>
            </div>
        <?php endforeach; ?>
    </div>
</div>

提前感谢您的任何建议。此外,如果任何人对我在示例代码中使用的一般分离格式有任何输入,我很乐意听到它。我只是在休息了8年后重新开始编码。

编辑:根据评论中建议的@Devon添加了缺少的endforeach并改进了对第三个代码块的缩进。

编辑:我更新了第三个代码块以包含我之前遗漏的HTML,并添加了实现我正在寻找的输出所需的所有PHP功能。它有效,但IMO这样做可以消除我的分离。我现在基本上只有一个文件与我的数据库调用和另一个文件与此混乱。我觉得我没有朝着正确的方向进行正确的业务逻辑/表示逻辑分离。

我哪里错了?

1 个答案:

答案 0 :(得分:3)

冗长,复杂的逻辑,例如:
(sizeof($categories) > 1 && $key == end($categories)) ? ',&nbsp;' : '';
不应该在视图中打扰前端开发人员。 &#34;这段可怕的代码是什么? 它有什么作用?为什么后端开发人员没有给我一些更容易使用的东西?&#34; MVC的部分功能不仅在于关注点的分离,而且在于 同时保留后端和前端开发人员的资格。分开工作。

<?php foreach ($result as $row): ?>之类的代码不包含与其合作的内容。 DIV,Ps和SPAN也失控 这就是为什么我是视图助手的粉丝。

我建议:

  

product_list_tpl.php

<div class="card">
    <div class="product-list with-header">
        <div class="product-list-header center-align">
            <h2><?= $div_title; ?></h2>
        </div>
        <?= displayItems($items); ?>
    </div>
</div>

上面使用的视图助手:

function displayItems($items)
{
    foreach ($items as $item)
    {
        $categories = explode(', ', $item['category']);
        $id = $item['id'];
        $title = $item['title'];
        $url = $item['url'];
        $caption = $item['caption'];
        $description = $item['description'];
        $rating = $item['rating'];
        $rated = $item['rated'];
        include('product_list_item_tpl.php');
    }
}
  

product_list_item_tpl.php

<div class="product-list-item avatar">
  <img src="img/product/<?= $id; ?>.jpg" alt="<?= $title; ?>" class="square">
  <a href="product/<?= generate_link($url); ?>" class="title bold"><?= $title; ?></a>
  <p class="caption"><?= $caption; ?></p>
  <div class="item-bottom">
    <span class="responsive"><?= $description; ?></span>
    <p>
      Category:&nbsp;
      <?php displayCategories($categories); ?>
    </p>
    <p>
      <span>Rating:&nbsp;<?= $rating; ?></span>
      <span class="right">Rated&nbsp;<?= $rated; ?>&nbsp;<?= isPluarl($rated)?'times':'time'; ?></span>
    </p>
  </div>
</div>

上面使用的视图助手:

function isPlural($number)
{
    return $number != 1;
}

function displayCategories($categories)
{
    $last = end($categories);
    $count = sizeof($categories);
    foreach ($categories as $key => $category)
    {
        $cat = strtolower($category);
        $isLast = $category == $last;
        include('product_list_category_tpl.php');
    }
}
  

product_list_category_tpl.php

<a href="category/<?= $cat; ?>"><?= $category; ?></a>
<?= ($count > 1 && !$isLast) ? ',&nbsp;' : ''; ?>

注意我将$key == end($categories)部分与您之前使用的!$isLast部分颠倒了$key并将$category交换为count($categories)。这个逻辑仍然感觉很脏,因为两个类别可能具有相同的名称。将$i++function displayCategories($categories) { end($categories); $last = key($categories); $count = sizeof($categories); foreach ($categories as $key => $category) { $cat = strtolower($category); $isLast = $key == $last; include('product_list_category_tpl.php'); } } 结合使用以确定它是否是最后一个循环可能更好。

修改
这样可以很好地避免前面提到的问题,因为它依赖于键而不是值:

@echo off
title ProgName Compile & Run Script (c) 2016
cls
set FILETOZIP=C:\SourceDir\*.*
set TEMPDIR=C:\temp
: rmdir %TEMPDIR%
mkdir %TEMPDIR%
xcopy /s %FILETOZIP% %TEMPDIR%
cd C:\temp
copy /b *.* +,,
cd C:\DestinDir
echo Set objArgs = WScript.Arguments > Temp.vbs
echo InputFolder = objArgs(0) >> Temp.vbs
echo ZipFile = objArgs(1) >> Temp.vbs
echo CreateObject("Scripting.FileSystemObject").CreateTextFile(ZipFile, True).Write "PK" ^& Chr(5) ^& Chr(6) ^& String(18, vbNullChar) >> Temp.vbs
echo Set objShell = CreateObject("Shell.Application") >> Temp.vbs
echo Set source = objShell.NameSpace(InputFolder).Items >> Temp.vbs
echo objShell.NameSpace(ZipFile).CopyHere(source) >> Temp.vbs
echo wScript.Sleep 2000 >> Temp.vbs
del C:\DestinDir\ProgName.exe /f /s
CScript Temp.vbs  %TEMPDIR%  C:\DestinDir\ProgName.zip
ren C:\DestinDir\ProgName.zip ProgName.nw
copy /b nw.exe+ProgName.nw ProgName.exe
del C:\DestinDir\Temp.vbs /f /s
del C:\DestinDir\ProgName.nw /f /s
rmdir C:\temp /s /q
start ProgName.exe