PHP OOP购物车设计/类型提示建议

use*_*too 0 php shopping-cart type-hinting

我创建了一个我的第一堂课,一个购物车课.它很棒,并且完成了我所需要的一切.但是,总有一个......

我已经阅读了很多关于类型提示的内容,并被建议只通过我的shoppingcart类一个暗示变量:

$cart = new cart(item $id);
Run Code Online (Sandbox Code Playgroud)

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

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

您是否觉得我实施网站的方式受益于项目类?

Col*_*n M 6

类型提示是一种向用户通知您的方法如何调用它们的方法.它还允许您(作为实现该方法的方法)依赖于您传递的参数的某些功能.

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

<?php
class Cart {
    protected $items = array();

    public function addItem($item) {
        $this->items[] = $item;
    }
}

$cart = new Cart();
$cart->addItem('My Super Cool Toy');
Run Code Online (Sandbox Code Playgroud)

$cart在运行上述内容之后,您所拥有的是Cart一个项目"My Super Cool Toy" 的实例.但是,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));
Run Code Online (Sandbox Code Playgroud)

现在我处于一个完全不同的境地.我知道我Cart满满Item的.我知道,我可以getPrice()Item.我可以依靠那里,因为你可以调用我的addItem方法的唯一方法是给我一个Item对象.

没有类型暗示可以做同样的事吗?是.但是,没有好的方法可以依赖任何特定的实现.作为调用者,我可能会给你一个Item对象.但我也可以给你一个字符串或数字.如果你只有一个字符串或一个数字,你怎么能最终给我一个价格?

现在让我们让它变得更好一些

并快速进入接口编码.假设我有各种类型的玩具:遥控车和玩偶.据推测,我们与他们玩的方式不同.在这种情况下,一个"item"对象不起作用,因为它们可以做不同的事情.但是,它们都表现出相同类型的行为.他们都是玩具.所以让我们为它创建一个接口:

<?php
interface Toy {
    public function play();
}
Run Code Online (Sandbox Code Playgroud)

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

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

class Doll implements Toy {
    public function play() {
        print "GI Joe";
    }
}
Run Code Online (Sandbox Code Playgroud)

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

<?php
class ToyBin {
    protected $toys = array();

    public function addToy(Toy $toy) {
        $this->toys[] = $toy;
    }

    public function playWithMyToys() {
        foreach ($this->toys as $toy) {
            $toy->play();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

为什么这样更好? 由于几个原因,接口实际上是编程的方式

  1. 它们需要界面创建者很少的努力.接口不需要任何功能.它只是作为其他人实施的"契约".
  2. 它们让您依赖于可用的特定功能.在我的例子中,你知道任何进入你的"玩具" ToyBin都可以play()编辑.而且你不必担心如何.
  3. 它们允许在不牺牲代码质量的情况下实现灵活性.您可以编程任何可以以任何方式玩的玩具.

希望这有助于清理事情.