วิธีการใช้ RESTful API ภายนอกด้วย Symfony


10

เรากำลังสร้างสถาปัตยกรรม Microservice สำหรับโครงการของเราโดยส่วนใหญ่แล้วแอพพลิเคชั่นส่วนหน้าของ Symfony จะโต้ตอบกับ RESTful APIs ส่วนหลัง

ปัญหาคือวิธีนี้กำลังทำลายการจัดการเอนทิตี้ของ Symfony ที่อาศัยหลักคำสอนกับฐานข้อมูลเป็นอย่างมาก โดยที่ Symfony มักจะจัดการเอนทิตีกับ Doctrine โดยอัตโนมัติงานส่วนใหญ่สิ่งนี้ไม่สามารถทำซ้ำได้ง่ายเมื่อเราต้องเข้าถึงข้อมูลภายนอกจาก API

ตัวอย่างเช่นกับเอนทิตีของลูกค้า:

  • ด้วยการใช้ Doctrine เราต้องกำหนดคลาสลูกค้าของเราและตอนนี้มันเป็นเรื่องง่ายที่จะสร้างปรับปรุงเรียกลูกค้าของเรา
  • การใช้วิธี REST API ลูกค้าสามารถเข้าถึงได้ผ่าน API แต่เรามีงานจำนวนมากเพื่อกำหนดวิธีสร้างไคลเอ็นต์ (POST), อัปเดต (PUT), ดึง (GET) ฯลฯ

เพื่อให้ลูกค้าสังเกตเห็นมีการใช้งานโดยแอปพลิเคชั่นหลายแห่งไม่เพียง แต่แอพพลิเคชั่นส่วนหน้าเท่านั้นดังนั้นจึงเป็น API เฉพาะ

เราควรสร้างคลาสที่มีวิธีคล้ายเอนทิตีที่ซ่อนความซับซ้อนในการเรียก API การนำเข้าข้อมูล API ทั้งหมดในพื้นที่และเข้าถึงพวกเขาผ่าน Doctrine หรือวิธีอื่นใด?


ฉันอยู่ในเรือลำเดียวกันกับคุณ การบริโภค API ภายนอกกับลูกค้าที่สร้างจากข้อกำหนด OpenApi / Swagger สงสัยเกี่ยวกับแนวทางปฏิบัติที่ดีที่สุดสำหรับ 'วงจรชีวิต' การบริโภคการดำเนินงานที่ไม่แน่นอนพารามิเตอร์และการสร้างแบบฟอร์มตัวกรอง ขณะนี้กำลังขยายการค้นหาของฉันเพื่อรวมวิธีการใด ๆ ไม่ว่าจะเป็น Symfony เฉพาะหรือไม่ก็ตาม
ต้นน้ำ

ต้องทำงานกับปัญหานี้เป็นเวลาหลายเดือนและกลับมาที่คำถามนี้ทั้งสองคำตอบเพื่อให้การแก้ปัญหาที่คล้ายกัน: สรุปการเรียก API กับ popo นั่นคือวิธีการที่เราใช้งานแม้ว่าจะมีวิธีแก้ไขปัญหาอื่น ๆ อยู่ก็ตาม ในบริบทการสื่อสาร Webapp <> API ที่คล้ายกันการใช้ระดับ abstraction ในการซ่อนการเรียก API จาก Webapp ดูเหมือนจะเป็นทางออกที่ดี ด้วยการเพิ่มขึ้นของไมโครไซต์และแนวทางลูกค้าเป้าหมาย API ไม่ต้องสงสัยเลยว่าแนวทางปฏิบัติที่ดีที่สุดและเครื่องมือที่เกี่ยวข้องจะปรากฏขึ้นเพื่อแก้ไขสิ่งที่ดูเหมือนจะเป็นปัญหาทั่วไป
Pierre B.

ตรงนี้ก็ใช้วิธีที่คล้ายกัน ขณะนี้ตรรกะทางธุรกิจมีอยู่ในเลเยอร์ 'การกระทำ' ซึ่งไม่สนใจว่าจะเป็น REST api หรือคำสั่ง cli ที่เรียกมันว่า การออกแบบรูปหกเหลี่ยมของ Alistair Cockburn เป็นจุดเริ่มต้นที่ยอดเยี่ยมในกรณีของเรา: alistair.cockburn.us/Hexagonal+ar Architecture
upstream

คำตอบ:


2

ฉันได้สร้างโปรเจกต์แบบ symfony ซึ่งใช้ API ภายนอก (JSON); สิ่งที่ฉันทำคือการสร้างไลบรารี่ของลูกค้าอิสระ ("ไคลเอนต์ไลบรารี่" - ชิ้นส่วนของซอฟต์แวร์, แพ็คเกจผู้แต่ง), ด้วยชุดเอนทิตีของตัวเอง (POPOs); มันรวมเข้ากับเฟรมเวิร์กโดยใช้อินเตอร์เฟสที่จัดทำโดย Symfony (ตัวอย่างเช่นเพียงแค่สร้างผู้ให้บริการผู้ใช้ที่กำหนดเอง )

ไคลเอนต์ทำการโทร http "เบื้องหลัง" ซึ่งเป็นสิ่งสำคัญสำหรับความสามารถในการทดสอบในอนาคต คุณไม่ต้องการเปิดเผยวิธีการสื่อสารกับแหล่งข้อมูลของคุณและคุณไม่ต้องการให้การทดสอบของคุณเชื่อถือ API แบบสด

ส่วนต่อประสานห้องสมุดลูกค้า (ตัวอย่างว่ามีลักษณะอย่างไร):

class ApiClient {

   /**
    * @throws SomeApiException If credentials are invalid
    * @return ApiUser
    */
   public function authenticate($username, $password);

   /**
    * @return ApiUser
    */
   public function findUserByEmail($email);

   /**
    * @throws SomeApiException If email is invalid
    * @return void
    */
   public function changeUserEmail(User $user, $newEmail);
}

ไลบรารีไคลเอ็นต์ใช้ Guzzle สำหรับการสื่อสารและคอมโพเนนต์ Doctrine Cache ภายในเพื่อแคชผลลัพธ์ การแมประหว่างเอนทิตีออบเจ็กต์และเจสันถูกสร้างโดยผู้ทำแผนที่ซึ่งครั้งหนึ่งเคยเขียน - ไม่ได้เปลี่ยนแปลงบ่อยนัก (หรือเหตุการณ์เลย) ในกรณีนี้ฉันขอแนะนำให้ใช้ JMS Serializer สำหรับการแปลงอัตโนมัติเป็นและจาก JSON (ฉันถือว่าคุณใช้ JSON)

คุณจะต้องมีกลไกการแคชที่ดีและที่จัดเก็บในตัวเครื่องเช่น Redis การเรียก api บนคำขอแต่ละแอปจะฆ่าเซิร์ฟเวอร์ของคุณและทำให้แอปพลิเคชันของคุณช้าลงอย่างมาก มันสำคัญมากที่จะต้องเข้าใจว่าแคช http ทำงานอย่างไร หาก API ของคุณไม่ได้ใช้ส่วนหัวแคช (หรือใช้ในส่วนที่คลุมเครือ) จะเป็นเรื่องยากมากและใช้ทรัพยากรในการติดตามการเปลี่ยนแปลง

นอกจากนี้คุณยังจะต้องคิดว่าลูกค้าควรปฏิบัติตัวอย่างไรหากการเชื่อมต่อขาด - ลูกค้าควรใช้ข้อมูลที่ค้างอยู่หรือไม่ จะเป็นการดีถ้าคุณใช้พร็อกซีเซิร์ฟเวอร์ระหว่างแอปของคุณกับ API ในกรณีนี้พร็อกซี (เช่นวานิช) สามารถเร่งความเร็วคำขอของคุณและยังรีเฟรชข้อมูลที่ค้างในพื้นหลังโดยไม่ทำให้แอปของคุณช้าลง มันจะทำให้เว็บไซต์ของคุณออนไลน์ในกรณีที่ API ล้มเหลว คุณอาจไม่สามารถเขียนข้อมูลในระหว่างนี้ แต่ผู้ใช้ของคุณจะยังสามารถเรียกดูข้อมูลที่แคชได้

และการพูดหลักคำสอนให้ดู " กฎของเครื่องดนตรี "


1

Doctrine เป็นเลเยอร์การเข้าถึงฐานข้อมูล คุณไม่ต้องการเข้าถึงฐานข้อมูล แต่เป็น apis คุณยังสามารถสร้างเอนทิตี้ได้ แต่จากนั้นเป็นวัตถุง่าย ๆ ที่ไม่จำเป็นต้องขยายการใช้งานของเรา (ป็อบอัพ) มันควรจะมีพื้นที่เก็บข้อมูลที่ใช้วิธีการ CRUD ทั้งหมด ในกรณีนี้เรียกใช้ API แทนฐานข้อมูล ฉันจะสร้างส่วนต่อประสานนั้น ไม่ต้องรู้สึกแตกต่างสำหรับแอปพลิเคชันของคุณที่จะใช้ยกเว้นว่าคุณต้องคำนึงถึงทุกที่ที่บริการไมโครอาจไม่ตอบสนอง


0

FYI ขณะนี้มีองค์ประกอบ HttpClient สำหรับ v4.3

https://symfony.com/blog/new-in-symfony-4-3-httpclient-component


HttpClient เป็นทางเลือกที่น่าสนใจ แต่คำตอบนี้ใช้ได้ผลสำหรับฉันอย่าคิดว่ามันสมควรได้รับการโหวตที่ลดลง
ราศีเมษปกเกล้าเจ้าอยู่หัว
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.