我不确定我的数据模型是否正确。但这里有一个小例子,如何使用 PHP 过滤数据结构。在 PHP 部分之后,我将解释如何设置您的 HTML 表单,以便在您的 HTML 表格中输出所需的项目。
PHP 部分
我假设您从数据库表或 API 中读取数据。所以让我们假设我们的模型看起来像这样。该模型只是一个示例,用于展示 PHP 中面向对象的方法的外观。
<?php
declare(strict_types=1);
namespace Marcel\Model;
class Item
{
protected $id;
protected $systemID;
protected $anotherProperty;
public function getId(): ?int
{
return $this->id;
}
public function setId(int $id): self
{
$this->id = $id;
return $this;
}
public function getSystemId(): ?int
{
return $this->systemId;
}
public function setSystemId(int $systemId): self
{
$this->systemId = $systemId;
return $this;
}
public function getAnotherProperty(): ?string
{
return $this->anotherProperty;
}
public function setAnotherProperty(string $anotherProperty): self
{
$this->anotherProperty = $anotherProperty;
return $this;
}
}
如您所见,我们的项目模型只有三个属性。重要的属性将是系统 ID。稍后我们将按此属性过滤项目集合。在我们这样做之前,我们使用一个集合来存储我们所有的项目对象。为什么这个系列?在过滤集合时,集合为我们提供了一种类型安全性并使处理变得更容易。
<?php
declare(strict_types=1);
namespace Marcel\Model;
use InvalidArgumentException;
use SplObjectStorage;
class ItemCollection extends SplObjectStorage
{
public function attach($object, $data = null): self
{
if (!$object instanceof Item) {
throw new InvalidArgumentException(sprintf(
'The given object must be of the type Item. Given: "%s"',
get_class($object)
));
}
parent::attach($object, $data);
return $this;
}
}
这是我们的项目集合。该集合扩展了 PHP 内置类 SplObjectStorage,专为存储对象而设计。在这种情况下,集合只接受 Item 类型的对象。我们的集合实现了Iterator 接口,这使得集合可迭代。非常适合过滤。
接下来我们需要一个过滤器。 PHP 带来了一个内置的FilterIterator 类,这使得过滤数据结构变得容易。
<?php
declare(strict_types=1);
namespace Marcel\Filter;
class ItemFilterIterator extends FilterIterator
{
protected $systemId;
public function __construct(Iterator $iterator, int $systemId = 0)
{
parent::__construct($iterator);
$this->systemId = $systemId;
}
public function accept(): bool
{
// if system id is 0 return all items
if ($this->systemId === 0) {
return true;
}
$item = $this->getInnerIterator()->current();
return $item->getSystemId() === $this->systemId;
}
}
这是我们的FilterIterator 实现。扩展需要系统 ID 作为构造函数中的第二个参数。系统 ID 将是我们的过滤器参数。 accept 方法将返回 true,当项目的系统 id 属性等于系统 id 过滤器参数时。如果不是,accept 方法返回 false。
让我们看看,这三个类可以为你做什么。这是一个实用的例子。首先,我将创建一些项目以用于示例目的。
<?php
declare(strict_types=1);
namspace Marcel;
use Marcel\Filter\ItemFilterIterator;
use Marcel\Model\Item;
use Marcel\Model\ItemCollection;
$item1 = (new Item())
->setId(1)
->setSystemId(1)
->setAnotherProperty('item 1');
$item2 = (new Item())
->setId(2)
->setSystemId(1)
->setAnotherProperty('item 2');
$item3 = (new Item())
->setId(3)
->setSystemId(2)
->setAnotherProperty('item 3');
$collection = (new ItemCollection())
->attach($item1)
->attach($item2)
->attach($item3);
// here comes the magic
$filter = new ItemFilterIterator($collection, 2);
foreach ($filter as $item) {
var_dump($item);
}
在此示例中,我们有三个项目,它们属于由 sysmtem id 属性设置的两个不同系统。通常,这些项目应该来自您的数据库或您的数据集来自哪里。这些项目被设置为集合,我们使用过滤器迭代器类对其进行过滤。在这个例子中,我们只想要属于系统 2 的项目。使用此设置,foreach 循环只输出项目 3,因为系统 id 等于 2。
HTML 部分
您的 HTML 模板看起来不错。我会为你扩展一点。
<form id="my-filter-form" method="post" action="index.php">
<label for="filter">Filter</label>
<select name="filter" id="filter">
<option value="">all</option>
<option value="1">1</option>
<option value="2">2</option>
</select>
<button type="submit">Filter results</button>
</form>
如你所见,我们使用了一个普通的形式,它将选择的过滤选项发送到一个名为index.php的php文件。每次有人点击“过滤结果”按钮时,都会发送表单并刷新页面。
这是一个示例 index.php 文件。
<?php
declare(strict_types=1);
namespace Marcel;
use Marcel\Filter\ItemFilterIterator;
use Marcel\Model\Item;
use Marcel\Model\ItemCollection;
// first get your items from somewhere and fill the item collection
$collection = new ItemCollection();
$collection->attach(...); // attach all the items
// check, if there 's a filter - if not use 0 to display all items
$systemID = (isset($_POST['filter'])) ? intval($_POST['filter']) : 0;
// init the filter iterator
$filter = new ItemFilterIterator($collection, $systemID);
$items = new ItemCollection();
// attach all filtered items to a new collection
foreach ($filter as $item) {
$items->attach($item);
}
?>
<form id="my-filter-form" method="post" action="index.php">
<label for="filter">Filter:</label>
<select id="filter" name="filter">
<option>all</option>
<option value="1">system 1</option>
<option value="2">system 2</option>
</select>
<button type="submit">Filter me!</button>
</form>
<table>
<thead>
<tr>
<th>ID</th>
<th>System</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<?php foreach ($items as $item) : ?>
<tr>
<td><?= $item->getId() ?></td>
<td><?= $item->getSystemId() ?></td>
<td><?= $item->getAnotherProperty() ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
请记住,每次发送表单时页面都会重新加载。如果你想避免重新加载,你必须使用 ajax(异步 javascript 请求)。
希望这个小过滤示例有所帮助。