如何建立PHP多对多关系模型


How to model a PHP Many to Many Relationship

我需要为我们的一个客户建立一个项目系统。项目System具有如下(给定)数据库结构:

| item
+--------------------------
| id tinyint(4) primary key
| name varchar(30)
| attr
+--------------------------
| id tinyint(4) primary key
| name varchar(30)
| itemAttr
+--------------------------
| itemId foreign key
| attrid foreign key
| value varchar(255)

我得到了类结构:

<?php
abstract class Item {
    private $id;
    private $name;  
}
class ShopItem extends Item {
    private $itemType;
    private $price;
    private $imageHref;
    private $description;   
}

因为这是一个多对多关系,所以我可以有X行包含关于"item"的单个信息。

我如何捆绑/分组行,以便我可以将信息映射到模型?

我需要例如20个不同的"ShopItems"为一个页面

我想在一个查询中处理所有数据库操作(这就是我的任务所说的…)所以会有这样的结果:

| id | name     | attrId | value |
+----+----------+--------+-------+
| 1  | Item1    | 1      | 1     |
| 1  | Item1    | 2      | Text  |
| 1  | Item1    | 3      | 100   |

和我有不同的搜索条件:

项目需要具有以下属性:ItemType (attrId 1)描述(attrId 2)价格(attrId 3)

否则我不想从数据库中获取这个项目

我个人会添加一个属性数组作为Item类的成员。最佳实践可以在这里找到:PHP5。将数组声明为类成员

的两种方法

在数据库理论中,您需要这个数据透视表遵循规范化原则,其中禁止嵌套关系。但在Php中,类之间没有这个要求

基本类关系:

class Item
{
    private $id;
    private $name;
    public $attrs = array();
    public function addAttr(Attr &$attr) { $this->attrs[] = $attr; $attr->items[] = $this; }
    public function getAttrs() { return $this->attrs; }
    public function __construct($id, $name)
    {
        $this->id = $id;
        $this->name = $name;
    }
}
class Attr
{
    private $id;
    private $name;
    public $items = array();
    public function addItem(Item &$item) { $this->items[] = $item; $item->attrs[] = $attr; }
    public function getItems() { return $this->items; }
    public function __construct($id, $name)
    {
        $this->id = $id;
        $this->name = $name;
    }
}
$item1 = new Item(1, "I1");
$item2 = new Item(2, "I2");
$attr1 = new Attr(1, "A1");
$attr2 = new Attr(2, "A2");
$item1->addAttr($attr1);
$item1->addAttr($attr2);
var_dump($item1->getAttrs());
var_dump($attr1->getItems());

我建议使用ORM库

一个选项(通常有几个选项)是将它们存储在映射中,并通过泛型getter(使用属性名作为第一个参数)访问这些属性,或者使用魔术函数访问它们。

<?php
abstract class Item {
    private $id;
    private $name;
    protected $attributes = array();
    /**
     * @param $name The attribute key/name
     * @return null|mixed returns NULL if the attribute was not set
     */
    public function getAttribute( $name ) {
        if( isset( $this->attributes[$name] ) ) {
            return $this->attributes[$name];
        }
        else {
            return null;
        }
    }
}

使用魔法函数:

<?php
abstract class Item {
    private $id;
    private $name;
    protected $attributes = array();
    /**
     * @param $name The attribute key/name
     * @return null|mixed returns NULL if the attribute was not set
     */
    public function __get( $name ) {
        if( isset( $this->attributes[$name] ) ) {
            return $this->attributes[$name];
        }
        else {
            /* Trigger an error for unknown properties */
            $trace = debug_backtrace();
            trigger_error(
                'Undefined attribute: ' . $name .
                ' in ' . $trace[0]['file'] .
                ' line ' . $trace[0]['line'],
                E_USER_NOTICE);
            return null;
        }
    }
}