昨天已經完成了 ArrayStore
今天就將 ArrayStore 改造成 SessionStore
所以要做的第一件事請就是建立 Interface
// src/Store.php
namespace Recca0120\Cart;
interface Store
{
public function put($item);
public function remove($item);
public function items();
}
接下來則是修改 Cart.php 的程式碼
// src/Cart.php
namespace Recca0120\Cart;
class Cart
{
private $store;
public function __construct(Store $store = null)
{
$this->store = $store ?: new ArrayStore();
}
public function put($item)
{
$this->store->put($item);
return $this;
}
public function remove($item)
{
$this->store->remove($item);
}
public function items()
{
return $this->store->items();
}
public function total()
{
return array_sum(array_map(function ($item) {
return $item['total'];
}, $this->items()));
}
}
改完後再執行一次 unitest
確認沒問題後,我們就可以專心的來撰寫 SessionStore
// tests/SessionStoreTest.php
<?php
namespace Recca0120\Cart\Tests;
use Recca0120\Cart\Item;
use PHPUnit\Framework\TestCase;
use Recca0120\Cart\SessionStore;
class SessionStoreTest extends TestCase
{
/**
* @test
* @runInSeparateProcess
*/
public function 新增商品()
{
$item = $this->createItem('商品01', 100, 1);
$store = new SessionStore();
$store->put($item);
$this->assertArraySubset([$item], $store->items());
}
/**
* @test
* @runInSeparateProcess
*/
public function 移除商品()
{
$store = new SessionStore();
$store->put($item1 = $this->createItem('商品01', 100, 2));
$store->put($item2 = $this->createItem('商品02', 200, 1));
$store->remove($item1);
$this->assertEquals([$item2], $store->items());
}
private function createItem($name, $price, $qty)
{
return new Item([
'name' => $name,
'price' => $price,
'quantity' => $qty,
]);
}
}
// src/SessionStore.php
namespace Recca0120\Cart;
class SessionStore implements Store
{
public function put($item)
{
$this->initialize();
array_push($_SESSION['cart'], $item);
return $this;
}
public function remove($item)
{
$this->initialize();
$_SESSION['cart'] = array_values(array_filter($this->items(), function ($o) use ($item) {
return $o !== $item;
}));
}
public function items()
{
$this->initialize();
return $_SESSION['cart'];
}
private function initialize()
{
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
if (isset($_SESSION['cart']) === false) {
$_SESSION['cart'] = [];
}
}
}
接下來只要將 SessionStore 注入到 Cart 裡
這樣就算按 F5 之後,資訊也會保留住了
明天就來瀏覽器實際的執行看看