PHP对象扩展问题

时间:2009-06-28 05:31:56

标签: php class oop object extension-methods

所以我有一个项目类如下:


class Item
{
    private $db;
    private $data = array(
        'AltItem1' => null,
        'AltItem2' => null,
        'BaseUOM' => null,
        'Category1' => null,
        'Category2' => null,
        'Category3' => null,
        'Category4' => null,
        'Iden' => null,
        'IsHCS' => null,
        'ItemDesc' => null,
        'ItemNmbr' => null,
        'ItemType' => null,
        'MSDS' => null,
        'NoteText' => null,
        'NonStock' => null,
        'PrcLevel' => null,
        'TipPrice' => null,
        'DTM_UpdType' => null,
        'DTM_UpdDateTime' => null,
        'DTM_DownloadDateTime' => null,
        'DTM_UploadDateTime' => null
    );

    public function __construct(mysqli $db, $id = null){
        $this->db = $db;

        if(!empty($id)){
            $id = (int)$id;
            $this->populate($id);
        }
    }

    public function __get($key)
    {
        if(array_key_exists($key, $this->data)){
            return $this->data[$key];
        }
        error_log("Invalid key '$key'");
        return null;
    }

    public function __set($key, $value)
    {
        if(array_key_exists($key, $this->data)){
            $this->data[$key] = $value;
            return true;
        }
        return false;
    }

    public function populate($id)
    {
        $sql = sprintf(
            "SELECT %s FROM ItemMaster WHERE id = ?",
            implode(", ", array_keys($this->data))
        );

        $stmt = $this->db->stmt_init();
        $stmt->prepare($sql) or die ("Could not prepare statement:" . $stmt->error);
        $stmt->bind_param('i', $id);
        $stmt->execute() or die('exec');
        $stmt->store_result();
        if($stmt->num_rows == 1)
        {
            $params = array();
            foreach($this->data as $key => $val){
                $params[] = &$this->data[$key];
            }

            call_user_func_array(array($stmt, 'bind_result'), $params);
            $stmt->fetch();
            $return = true;
        }
        else{
            user_error("No rows returned for id '$id'");
            $return = false;
        }
        return $return;
    }
    public function insert()
    {   
        $params = $this->data;
        $values = array();

        foreach($params as $param){
            $values[] = "?";
        }

        $sql = sprintf(
            "INSERT INTO recurrence (%s) VALUES (%s)",
            implode(", ", array_keys($params)),
            implode(", ", $values)
        );

        $stmt = $this->db->stmt_init();
        $stmt->prepare($sql) or die ("Could not prepare statement:" . $stmt->error);

        $types = str_repeat("s", count($params));
        array_unshift($params, $types);
        call_user_func_array(array($stmt, "bind_param"), $params);

        $stmt->execute();

        $stmt->store_result();
        $result = $stmt->result_metadata();
    }
    public function update()
    {
        $sql = "UPDATE recurrence SET ";
        $params = array();
        foreach($this->data as $key => $value){
            $params[] = "$key = ?";
        }
        $sql .= implode(", ", $params) . " WHERE id = ?";

        $stmt = $this->db->stmt_init();
        $stmt->prepare($sql) or die ("Could not prepare statement:" . $stmt->error);

        $params = $this->data;
        $params[] = $this->data['id'];
        $types = str_repeat("s", count($params));
        array_unshift($params, $types);
        call_user_func_array(array($stmt, "bind_param"), $params);

        $stmt->execute();

        $stmt->store_result();
        $result = $stmt->result_metadata();
    } 

    }

我的问题是,以我的方式使用数据结构扩展此类的最佳方法是什么?我基本上想要一个购物车中的物品的另一个类。所以一些额外的字段将是数量,购物车ID等。或者有更好的方法来做到这一点而不扩展类?

另一方面,我说有另一个变量$ price不能直接存储在数据库中。所以我把它变成了一个公共变量,但我不得不制作帮助方法来访问它不是吗?如果是这种情况,我的$ data数组是这类项目的最佳解决方案吗?

提前致谢。

2 个答案:

答案 0 :(得分:2)

我不是100%确定您可能正在使用的私有$data变量的用法,因此我的倾向是采用稍微不同的方法。

不是将所有数据字段分组到对象的单个私有变量中,而是将每个字段设置为私有变量,即:

class Item
{
    private $db;
    private $AltItem1;
    private $AltItem2;
...
etc.

这样可以立即解决您公开数据字段的问题,因为您可以简单地将这些字段声明为公共成员。公共成员不需要getter和setter,因此您不必担心......您可以通过$this->price(内部)或$item->price(外部)访问它们。为您节省一些代码。而且,您可以快速修改populate()功能来设置所有新属性,因为您只需要设置$this->$$key而不是$this->data[$key]

现在,通过使用__set()__get(),您似乎希望能够访问私有$data成员,甚至可以访问对象外部。没有理由你不能通过将每个字段单独声明为私有来继续这样做。 __set()__get()将以完全相同的方式运作,您只需要进行微调,即:

public function __get($varname)
{
    if ($this->$varname !== null) return $this->varname;
    error_log("Invalid key '$key'");
    return null;
}

作为最后的奖励,扩展课程变得更容易,因为如果要覆盖$data属性,则不必重新声明所有字段。您只需将子项的新字段添加为新的私有成员。

所以我不确定这是否会让你的生活更轻松,但我认为这将是我的方法。

答案 1 :(得分:1)

如果您需要具体信息,我无法帮助您,但就逻辑而言:

从纯粹面向对象的设计角度来看,我认为最好通过创建Cart类来跟踪项目来解决这个问题。它基本上可以是适当排序列表的包装类(特定于语言,我不太了解PHP = P)。

我没有看到让物品跟踪其所在车辆的特殊原因 - 在大多数情况下,让车辆保持跟踪更有意义。 (在现实世界的建模方面:物品是否记录了他们可能或可能不在的购物车?Nah。但推车基本上只是物品的容器。)

我不太确定你在第二个问题中提到了什么 - 你能详细说明吗? 对不起,我无法提供更多帮助。

大卫