nattapong99 / book

0 stars 0 forks source link

Sylius Resource Layer #4

Open nattapong99 opened 6 years ago

nattapong99 commented 6 years ago

Sylius - Resource Layer

เพื่อให้มีวิธีการที่สอดคล้องและยืดหยุ่นในการจัดการ resource ทั้งหมด โดย “resource” นั้นตามที่เราเข้าใจจะหมายถึงทุก ๆ model ในแอพพลิเคชั่น โดยตัวอย่างของ Sylius resource ได้แก่ “product”, “order”, “tax_category”, “promotion”, “user”, “shipping_method” เป็นต้น

ใน Sylius มี resource อยู่สองประเภท

สำหรับระบบการจัดการ Sylius resource ที่อยู่ใน SyliusResourceBundle สามารถใช้ใน Symfony2 project ได้

Services

จะมี 4 services ที่สำคัญในทุก ๆ resource ได้แก่

ในที่นี้จะใช้ “product” resource เป็นตัวอย่าง โดยค่าเริ่มต้นจะแสดงโดยอ็อบเจ็กต์ของคลาสที่ใช้งาน Sylius\Component\Core\Model\ProductInterface

Factory

Factory services มีความสามารถในการสร้าง new object โดยสามารถใช้งาน service นี้ ได้จาก sylius.factory.product (โค้ดตัวอย่างสำหรับ Product resource)

<?php

public function myAction()
{
    $factory = $this->container->get('sylius.factory.product');

    /** @var ProductInterface $product **/
    $product = $factory->createNew();
}

Note การสร้าง resource ผ่านเมธอดของ factory จะทำให้โค้ดสามารถทดสอบได้มากขึ้นและช่วยให้สามารถเปลี่ยนแปลง model class ได้ง่าย

Manager

Manager services เป็นเพียงชื่อที่เหมาะสมสำหรับ ObjectManager ของ Doctrine โดยสามารถใช้งาน service นี้ได้จาก sylius.manager.product API จะเป็นเหมือนกันและคุณอาจจะคุ้นเคยกับมันแล้ว

<?php

public function myAction()
{
    $manager = $this->container->get('sylius.manager.product');

    // สมมติว่า $product1 มีอยู่ในฐานข้อมูลที่เราสามารถดำเนินการกับมันได้
    $manager->remove($product1);

    // ถ้าเราสร้าง $product2 โดยใช้ factory, เราสามารถ persist มันในฐานข้อมูล
    $manager->persist($product2);

    // ก่อนการ flush, ความเปลี่ยนแปลงที่เราได้ทำ จะยังไม่ถูกบันทึก โดยในฐานข้อมูลจะยังมีแค่ข้อมูล $product1
    $manager->flush(); // บันทึกการเปลี่ยนแปลงลงในฐานข้อมูล

    // หลังการ flush ในฐานข้อมูลจะมีแค่ข้อมูลของ $product2 โดยข้อมูลของ $product1 ถูกลบไปแล้ว
}

Repository

Repository ถูกกำหนดให้เป็น service สำหรับทุก resource และแชร์ API กับ มาตรฐานของ Doctrine โดย ObjectRepository มีสองวิธีเพิ่มเติมในการสร้างอินสแตนซ์อ็อบเจ็กต์ใหม่และการใช้ paginator

โดยสามารถใช้ repository service ได้จาก sylius.repository.product 

<?php

public function myAction()
{
    $repository = $this->container->get('sylius.repository.product');
    $product = $repository->find(4); //ดึงข้อมูล product ที่มี id เท่ากับ 4, จะคืนค่าเป็น null หาไม่มีข้อมูล 
    $product = $repository->findOneBy(['slug' => 'my-super-product']); 
    // ดึงข้อมูล product มา 1 record จากเงื่อนไขที่กำหนด

    $products = $repository->findAll(); // ดึงข้อมูล product ที่มีอยู่ มาทั้งหมด
    $products = $repository->findBy(['special' => true]); // ค้นหาข้อมูล product ที่ตรงกับเงื่อนไขที่กำหนด
}

ข้อแนะนำ Feature ที่สำคัญของ repository คือเมธอด add($resource) และ remove($resource) โดยเมื่อส่ง argument resource ไป จะเกิดการเพิ่มและลบในทันทีเนื่องจากมีการ flush ภายใน

โดยวิธีการนี้สามารถใช้เมื่อต้องการดำเนินการกับข้อมูลที่ไม่ต้องการ แต่ถ้าต้องการที่จะดำเนินการ set of data แนะนำให้ใช้การ manager แทน

ทุก ๆ Sylius repository สนับสนุน paginating resource โดยสามารถสร้าง Pagerfanta instance โดยใช้เมทอด createPaginator (การแบ่งหน้า)

<?php

public function myAction(Request $request)
{
    $repository = $this->container->get('sylius.repository.product');

    $products = $repository->createPaginator();
    $products->setMaxPerPage(3);
    $products->setCurrentPage($request->query->get('page', 1));

    // Now you can return products to template and iterate over it to get products from current page.
}

การแบ่งหน้าสามารถใส่เงื่อนไขและเรียงลำดับที่ต้องการ

<?php

public function myAction(Request $request)
{
    $repository = $this->container->get('sylius.repository.product');

    $products = $repository->createPaginator(['foo' => true], ['createdAt' => 'desc']);
    $products->setMaxPerPage(3);
    $products->setCurrentPage($request->query->get('page', 1));
}

Controller

Controller เป็น service ที่สำคัญที่สุดสำหรับทุก ๆ resource และกำหนดรูปแบบ CRUD Controller ตามรูปแบบข้างล่าง

•   [GET] showAction() สำหรับดึงข้อมูลแบบเดี่ยว ๆ
•   [GET] indexAction() สำหรับการเข้าถึงข้อมูลแบบ collection
•   [GET/POST] createAction() สำหรับการสร้าง resource ใหม่
•   [GET/PUT] updateAction() สำหรับการอัพเดท resource ที่มีอยู่แล้ว
•   [DELETE] deleteAction() สำหรับการลบ resource ที่มีอยู่แล้ว

จากที่เห็น action เหล่านี้สอดคล้องกับการดำเนินการใน REST API นั่นหมายความว่าทุก Sylius controller สามารถทำงานกับ HTML, JSON, XML ได้ ขึ้นอยู่กับความต้องการใช้

Action ทั้งหมดนี้มีความยืดหยุ่นมากและช่วยให้คุณสามารถใช้เทมเพลตรูปแบบต่าง ๆ วิธีการเก็บข้อมูลของแต่ละ route โดย bundle นี้มึประสิทธิภาพมากและช่วยให้สามารถลงทะเบียน resource ได้ เพื่อให้มองเห็นภาพจึงขอยกตัวอย่าง

การแสดงการตั้งค่า resource ด้วย custom template และ repository method

# routing.yml
app_product_show:
    path: /products/{slug}
    methods: [GET]
    defaults:
        _controller: sylius.controller.product:showAction
        _sylius:
            template: AppStoreBundle:Product:show.html.twig # ระบุ template ที่จะใช้
            repository:
                method: findForStore # ระบุ repository method ที่จะใช้
                arguments: [$slug] # ส่งตัวแปร slug จาก url ไปที่ repository.

สร้าง product โดยใช้ custom form และ redirect

# routing.yml
app_product_create:
    path: /my-stores/{store}/products/new
    methods: [GET, POST]
    defaults:
        _controller: sylius.controller.product:createAction
        _sylius:
            form: AppStoreBundle/Form/Type/CustomFormType # ระบุฟอร์มที่จะใช้
            template: AppStoreBundle:Product:create.html.twig # ระบุ template ที่จะใช้.
            factory:
                method: createForStore # ใช้ factory ในการสร้าง                          
                arguments: [$store] # ส่งตัวแปรชื่อ store จาก url
            redirect:
                route: app_product_index # Redirect กลับมาที่หน้า product
                parameters: [$store]

source