【问题标题】:PHP OOP Shopping Cart design/type hinting advicePHP OOP 购物车设计/类型提示建议
【发布时间】:2013-02-21 18:55:20
【问题描述】:

我创建了我的第一个类,即购物车类。它很棒,可以满足我的所有需求。然而,总有一个然而,...

我已经阅读了很多关于类型提示的内容,并被建议只向我的购物车类传递一个提示变量:

$cart = new cart(item $id);

我理解这样做的原因,但我对我的项目类应该做什么以及如果我选择实现它在其中使用什么方法感到困惑。

目前我的网站使用受 MVC 启发的结构来分离方法/视图和控制器。我的视图包含一个发布表单,它将项目 ID 发送到创建对象并调用 additem 方法(或其他相关方法)的控制器。

你觉得我实现网站的方式受益于项目类吗?

【问题讨论】:

    标签: php shopping-cart type-hinting


    【解决方案1】:

    类型提示是一种告知用户您的方法如何他们应该调用它们的方式。它还允许您作为实现该方法的人,依赖您正在传递的参数的某些特性。

    这是一个没有类型提示的购物车示例

    <?php
    class Cart {
        protected $items = array();
    
        public function addItem($item) {
            $this->items[] = $item;
        }
    }
    
    $cart = new Cart();
    $cart->addItem('My Super Cool Toy');
    

    在运行上述操作后,$cart 中的内容是 Cart 的一个实例,其中包含一项“我的超酷玩具”。但是,Cart 对象不知道该项目是什么。它不知道如何与它交互或用它做什么。例如,我如何获得上面购物车的小计?我不能。

    这是一个带有类型提示的示例:

    <?php
    class Cart {
        protected $items = array();
    
        public function addItem(Item $item) {
            $this->items[] = $item;
        }
    
        public function getSubTotal() {
            $total = 0;
            foreach ($this->items as $item) {
                $total += $item->getPrice();
            }
            return $total;
        }
    }
    
    class Item {
        protected $name;
        protected $price;
    
        public function __construct($name, $price) {
            $this->name = $name;
            $this->price = $price;
        }
    
        public function getName() {
            return $this->name;
        }
    
        public function getPrice() {
            return $this->price;
        }
    }
    
    $cart = new Cart();
    $cart->addItem(new Item('My Super Cool Toy', 10.99));
    

    现在我处于完全不同的境地。我知道我的Cart 充满了Items。我知道我可以getPrice()Item。我可以依赖它,因为调用我的addItem 方法的唯一方法是给我一个Item 对象。

    在没有类型提示的情况下也可以这样做吗?是的。 但是没有什么好的方法可以依赖任何特定的实现。作为调用者,我可能给你一个 Item 对象。但我也可能会给你一个字符串或一个数字。如果你只有一个字符串或一个数字,你怎么能确定地给我一个价格?

    现在让我们做得更好一点

    然后快速进入接口编码。假设我有玩具类型:遥控车和洋娃娃。大概,我们以不同的方式玩它们。在这种情况下,一个“项目”对象不起作用,因为它们可以做不同的事情。 但是,它们都表现出相同类型的行为。它们都是玩具。所以让我们为此创建一个接口:

    <?php
    interface Toy {
        public function play();
    }
    

    让我们为我们的玩具创建一些具体的类:

    <?php
    class RemoteControlledCar implements Toy {
        public function play() {
            print "I'm driving a car";
        }
    }
    
    class Doll implements Toy {
        public function play() {
            print "GI Joe";
        }
    }
    

    现在,我们要将玩具存放在玩具箱中:

    <?php
    class ToyBin {
        protected $toys = array();
    
        public function addToy(Toy $toy) {
            $this->toys[] = $toy;
        }
    
        public function playWithMyToys() {
            foreach ($this->toys as $toy) {
                $toy->play();
            }
        }
    }
    

    看看,你已经成功正确地编程。你知道你有一个装满玩具物品的玩具箱。你不必关心它们是什么类型的玩具,也不必关心你将如何与它们互动。你只知道你可以用它们做某些事情(在这种情况下,play 用它们)。正因为如此,你有一个可以依赖的界面。

    为什么这样更好? 接口确实是编程的方式,原因有几个

    1. 界面的创建者只需要很少的努力。接口不需要具有任何功能。它只是作为其他人实施的“合同”。
    2. 它们让您依赖特定功能可用。在我的示例中,您知道将其放入您的ToyBin任何“玩具”可以与play() 一起使用。而且您不必担心如何操作。
    3. 它们允许在不牺牲代码质量的情况下灵活地实施。您可以对任何可以以任何方式玩的玩具进行编程。

    希望这有助于解决问题。

    【讨论】:

    • 感谢您的详尽解释,目前我的购物车有一个 get price 方法,我认为这在购物车类中非常适合,但现在看到了光明。我这样实现我的网站是否正确:1. 发布商品 id 2. 创建商品对象,3 将商品对象传递给购物车
    • @useyourillusiontoo 太棒了
    • 非常感谢。我是网站新手,但我为您勾选并增加了一个答案。我认为这就是例行公事。
    • @useyourillusiontoo 这是完美的。谢谢!
    【解决方案2】:

    充分遵循 MVC 的原则,您会期望将项目建模为一个类。即使这只是一个子类数据库记录,它也为将来的扩展提供了一个简单的平台。但是,我希望在addItem() 等方法上看到类“item”的这个类型提示变量,而不是cart 类的构造函数。是否意味着您的购物车将只有一件商品?

    从设计模式的角度来看,为您的项目设置一个类是有意义的。您现在可能没有任何这些要求,但在稍后阶段您可能希望将方法添加到项目类以:

    • 获取相关项目
    • 获取图片
    • 给项目评分

    等等。

    使用 PHP 面向对象,如果可以的话,通常最好使用类型提示(如果参数肯定需要是固定类型)。对于像整数这样的简单类型,始终值得检查或转换为该类型作为您在方法中做的第一件事。这样会更安全,并且通过随着时间的推移检查错误,您将了解代码库中可能存在的任何错误。

    【讨论】:

      猜你喜欢
      • 2011-10-29
      • 2011-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-24
      • 1970-01-01
      • 2011-01-29
      • 2011-04-10
      相关资源
      最近更新 更多