inklabs/kommerce-core

Zen Kommerce Core

v0.6.0 2016-06-30 17:25 UTC

This package is auto-updated.

Last update: 2024-09-12 10:18:56 UTC


README

Test Coverage Build Status Downloads Apache License 2.0

介绍

Zen Kommerce 是一个遵循 SOLID 设计原则的 PHP 购物车系统。它与 PSR 兼容,无依赖,并使用 TDD 实践实现 100% 代码覆盖率。

所有代码(包括测试)都符合 PSR-2 编码标准。命名空间和自动加载器使用 PSR-4 标准。

描述

此项目包含超过 62,000 行代码。单元测试占总代码的 30-40%,执行时间不到 10 秒。仓库测试使用内存中的 SQLite 数据库。

设计模式

架构

Flow of Control

  • 操作

    • 命令和查询是应用程序的主要用例和入口点。

    • 命令操作 被分发到 CommandBusInterface 以进行处理。

      $applyToShipping = true;
      $command = new CreateStateTaxRateCommand('CA', 9.5, $applyToShipping);
      $this->dispatch($command);
      • $this->dispatch(...) 方法没有返回值。如果命令无效,则抛出异常。
    • 查询操作 被分发到 QueryBusInterface 以进行处理。处理程序不会返回 Product 实体,而是将一个 ProductDTOBuilder 对象注入到响应中。DTO Builder 用于生成 ProductDTO 对象,可以使用 $response->getProductDTO() 方法检索。

      $productId = '15dc6044-910c-431a-a578-430759ef5dcf';
      $query = new GetProductQuery($productId);
      
      /** @var GetProductResponse $response */
      $response = $this->dispatchQuery($query);
      
      $productDTO = $response->getProductDTO();
      var_export($productDTO);
        inklabs\kommerce\EntityDTO\ProductDTO::__set_state([
            'slug' => 'test-product',
            'sku' => '5b6541751fd10',
            'name' => 'Test Product',
            'unitPrice' => 1200,
            'quantity' => 10,
            'isInventoryRequired' => false,
            'isPriceVisible' => true,
            'isActive' => true,
            'isVisible' => true,
            'isTaxable' => true,
            'isShippable' => true,
            'isInStock' => true,
            'areAttachmentsEnabled' => false,
            'shippingWeight' => 16,
            'description' => null,
            'rating' => null,
            'tags' => [],
            'images' => [],
            'tagImages' => [],
            'options' => [],
            'textOptions' => [],
            'productQuantityDiscounts' => [],
            'optionProducts' => [],
            'productAttributes' => [],
            'price' => inklabs\kommerce\EntityDTO\PriceDTO::__set_state([
                'origUnitPrice' => 1200,
                'unitPrice' => 1200,
                'origQuantityPrice' => 1200,
                'quantityPrice' => 1200,
                'catalogPromotions' => [],
                'productQuantityDiscounts' => []
            ]),
            'id' => inklabs\kommerce\Lib\UUID::fromString('15dc6044-910c-431a-a578-430759ef5dcf'),
            'created' => DateTime::__set_state([
                'date' => '2018-08-04 06:04:26.000000',
                'timezone_type' => 3,
                'timezone' => 'UTC',
            ]),
            'updated' => null,
            'createdFormatted' => 'August 3, 2018 11:04 pm PDT',
            'updatedFormatted' => null,
        ]);

      HTML 模板

      Product: <?=$productDTO->name?> - <?=$productDTO->sku?>
      Price: <?=$productDTO->price->unitPrice?>
      Tag: <?=$productDTO->tags[0]->name?>
    • 两种实现(CommandBusQueryBus)都委托给 MapperInterface 以确定处理执行的位置。

    • 这种 CQRS 策略允许我们在保持实体业务对象与主应用程序分离的同时,将命令与查询分开。我们更喜欢不暴露包含具有业务逻辑的方法的内部类。这也服务于将主应用程序与用例处理程序实现解耦。主应用程序只需要了解用例 操作

  • 领域事件

    • 领域事件可以在实体层触发并在服务层分发。
    // UserEntity:
    public function setPassword($password)
    {
        $this->passwordHash = // hash the password...
    
        $this->raise(
            new PasswordChangedEvent(
                $this->id,
                $this->email,
                $this->getFullName()
            )
        );
    }
    // UserService:
    $user = $this->userRepository->findOneById($userId);
    $user->setPassword($password);
    $this->userRepository->update($user);
    
    $this->eventDispatcher->dispatch($user->releaseEvents());
    • 事件可以直接在服务层分发。(已弃用)
    // CartService:
    $order = Order::fromCart($cart);
    $this->orderRepository->create($order);
    
    $this->eventDispatcher->dispatchEvent(
        new OrderCreatedFromCartEvent($order->getId())
    );
  • 服务

    • 这些是领域服务,用于通过存储库将领域状态持久化到数据库。它们包含与多个实体相关的行为以及不适合任何特定实体或单个用例的业务逻辑。
  • 实体

    • 这些都是普通的PHP对象。在这里您找不到任何ORM代码或外部依赖。这是构建对象之间关系的地方。实体包含与自身属性高度耦合的业务逻辑和行为。与实体单个实例的数据相关的业务逻辑属于这里。

      $tag = new Entity\Tag
      $tag->setName('Test Tag');
      
      $product = new Entity\Product;
      $product->setName('Test Product');
      $product->setUnitPrice(500);
      $product->setQuantity(1);
      $product->setIsInventoryRequired(true);
      $product->addTag($tag);
      
      if ($product->inStock()) {
        // Show add to cart button
      }
  • 实体仓库

    • 该模块负责存储和检索实体。在这个层次使用Doctrine 2通过数据映射模式来初始化实体。

      $productRepository = $this->entityManager->getRepository(Product::class);
      
      $productId = 1;
      $product = $productRepository->findOneById($productId);
      $product->setUnitPrice(600);
      
      $productRepository->persist($product);
  • 实体DTO

    • 这些类是简单的贫血对象,没有业务逻辑。数据可以通过公共类成员变量访问。在调用build()之前,使用EntityDTOBuilder可以访问完整的网络图关系(例如,withAllData())。使用这些数据传输对象(DTO)的主要原因是为了从实体的延迟加载Doctrine代理对象中扁平化对象图,以便在视图模板中使用。这避免了延迟加载查询在核心应用程序外部执行,或者在某些不合适的地方执行,例如在视图模板中。

      $product = new Entity\Product;
      $product->addTag(new Entity\Tag);
      
      $productDTO = $product->getDTOBuilder()
        ->withAllData(new Lib\Pricing)
        ->build();
      
      echo $productDTO->sku;
      echo $productDTO->price->unitPrice;
      echo $productDTO->tags[0]->name;
    • 在这里,您可以找到各种实用代码,包括支付网关(src/Lib/PaymentGateway)。

      $creditCard = new Entity\CreditCard;
      $creditCard->setName('John Doe');
      $creditCard->setZip5('90210');
      $creditCard->setNumber('4242424242424242');
      $creditCard->setCvc('123');
      $creditCard->setExpirationMonth('1');
      $creditCard->setExpirationYear('2020');
      
      $chargeRequest = new Lib\PaymentGateway\ChargeRequest;
      $chargeRequest->setCreditCard($creditCard);
      $chargeRequest->setAmount(2000);
      $chargeRequest->setCurrency('usd');
      $chargeRequest->setDescription('test@example.com');
      
      $stripe = new Lib\PaymentGateway\StripeFake;
      $charge = $stripe->getCharge($chargeRequest);

安装

将以下行添加到您的composer.json文件中。

{
    "require": {
        "inklabs/kommerce-core": "dev-master"
    }
}
   composer install

单元测试

    vendor/bin/phpunit

带有代码覆盖率

    vendor/bin/phpunit --coverage-text --coverage-html coverage_report

运行编码标准测试

    vendor/bin/phpcs -p --standard=PSR2 src/ tests/

统计代码行数

    vendor/bin/phploc src/ tests/ --names="*.php,*.xml"

导出SQL

    vendor/bin/doctrine orm:schema-tool:create --dump-sql
    vendor/bin/doctrine orm:schema-tool:update --dump-sql

许可证

Copyright 2014 Jamie Isaacs pdt256@gmail.com

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    https://apache.ac.cn/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.