ไลบรารี PHP เพื่อรองรับการใช้งานการนำเสนอสำหรับบริการเว็บ HATEOAS REST
วิธีที่แนะนำในการติดตั้ง Hateoas คือผ่าน Composer ต้องการแพ็คเกจ willdurand/hateoas
โดยการรันคำสั่งต่อไปนี้:
composer require willdurand/hateoas
การดำเนินการนี้จะแก้ไขเวอร์ชันเสถียรล่าสุด
มิฉะนั้น ให้ติดตั้งไลบรารีและตั้งค่าตัวโหลดอัตโนมัติด้วยตนเอง
หากคุณต้องการใช้ คำอธิบายประกอบ สำหรับการกำหนดค่า คุณต้องติดตั้งแพ็คเกจ doctrine/annotations
:
composer require doctrine/annotations
หากแอปของคุณใช้ PHP 8.1 ขึ้นไป ขอแนะนำให้ใช้แอตทริบิวต์ PHP ดั้งเดิม ในกรณีนี้ คุณไม่จำเป็นต้องติดตั้งแพ็คเกจ Doctrine
มีมัดสำหรับสิ่งนั้น! ติดตั้ง BazingaHateoasBundle แล้วสนุกได้เลย!
สำคัญ:
สำหรับผู้ที่ใช้เวอร์ชัน
1.0
คุณสามารถข้ามไปที่หน้าเอกสารประกอบนี้ได้สำหรับผู้ที่ใช้เวอร์ชัน
2.0
คุณสามารถข้ามไปที่หน้าเอกสารประกอบนี้ได้เอกสารต่อไปนี้เขียนขึ้นสำหรับ Hateoas 3.0 ขึ้นไป
Hateoas ใช้ประโยชน์จากไลบรารี Serializer เพื่อมอบวิธีที่ดีในการสร้างบริการเว็บ HATEOAS REST HATEOAS ย่อมาจาก Hypermedia ในฐานะ Engine of Application State และเพิ่ม ลิงก์ไฮเปอร์มีเดีย ให้กับ การแสดง ของคุณ (เช่น การตอบสนอง API ของคุณ) HATEOAS เป็นเรื่องเกี่ยวกับการค้นพบการกระทำบนทรัพยากรได้
ตัวอย่างเช่น สมมติว่าคุณมี User API ซึ่งส่งคืนการ เป็นตัวแทน ของ ผู้ใช้ รายเดียวดังนี้:
{
"user" : {
"id" : 123 ,
"first_name" : " John " ,
"last_name" : " Doe "
}
}
ในการบอกผู้บริโภค API ของคุณถึงวิธีดึงข้อมูลสำหรับผู้ใช้รายนี้ คุณต้องเพิ่ม ลิงก์ แรกของคุณไปยังการนำเสนอนี้ หรือเรียก self
ว่า URI สำหรับผู้ใช้รายนี้:
{
"user" : {
"id" : 123 ,
"first_name" : " John " ,
"last_name" : " Doe " ,
"_links" : {
"self" : { "href" : " http://example.com/api/users/123 " }
}
}
}
มาเจาะลึกเรื่อง Hateoas กันดีกว่า
ในคำศัพท์เฉพาะทางของ Hateoas ลิงก์ จะถูกมองว่าเป็น ความสัมพันธ์ ที่เพิ่มเข้ากับทรัพยากร เป็นที่น่าสังเกตว่าความ สัมพันธ์ ยังอ้างถึง ทรัพยากรที่ฝังไว้ ด้วย แต่หัวข้อนี้จะครอบคลุมในส่วนทรัพยากรที่ฝัง
ลิงก์คือความสัมพันธ์ที่ระบุด้วย name
(เช่น self
) และมีพารามิเตอร์ href
:
use JMS Serializer Annotation as Serializer ;
use Hateoas Configuration Annotation as Hateoas ;
/ * *
* @ Serializer XmlRoot ( "user" )
*
* @ Hateoas Relation ( "self" , href = "expr('/api/users/' ~ object.getId())" )
* /
class User
{
/ * * @ Serializer XmlAttribute * /
private $ id ;
private $ firstName ;
private $ lastName ;
public function getId () {}
}
use JMS Serializer Annotation as Serializer ;
use Hateoas Configuration Annotation as Hateoas ;
#[ Serializer XmlRoot( ' user ' )]
#[ Hateoas Relation( ' self ' , href: " expr('/api/users/' ~ object.getId()) " )]
class User
{
#[ Serializer XmlAttribute]
private $ id ;
private $ firstName ;
private $ lastName ;
public function getId () {}
}
ในตัวอย่างข้างต้น เรากำหนดค่าความสัมพันธ์ self
ที่เป็นลิงก์เนื่องจากพารามิเตอร์ href
คุณค่าของมันซึ่งอาจดูแปลกเมื่อมองแวบแรก จะถูกกล่าวถึงอย่างครอบคลุมในส่วนภาษาของนิพจน์ ค่าพิเศษนี้ใช้เพื่อสร้าง URI
ในส่วนนี้ คำอธิบายประกอบ/คุณลักษณะ จะใช้ในการกำหนดค่า Hateoas รองรับรูปแบบ XML และ YAML ด้วย หากต้องการ คุณสามารถใช้ PHP ธรรมดาได้เช่นกัน
สำคัญ: คุณต้องกำหนดค่าทั้ง Serializer และ Hateoas ด้วยวิธีเดียวกัน เช่น หากคุณใช้ YAML เพื่อกำหนดค่า Serializer ให้ใช้ YAML เพื่อกำหนดค่า Hateoas
วิธีที่ง่ายที่สุดในการลองใช้ HATEOAS คือการใช้ HateoasBuilder
ตัวสร้างมีวิธีการมากมายในการกำหนดค่าเครื่องซีเรียลไลเซอร์ Hateoas แต่เราจะไม่เจาะลึกวิธีการเหล่านั้นในตอนนี้ (ดู The HateoasBuilder) ทุกอย่างทำงานได้ดีตั้งแต่แกะกล่อง:
use Hateoas HateoasBuilder ;
$ hateoas = HateoasBuilder:: create ()-> build ();
$ user = new User ( 42 , ' Adrien ' , ' Brault ' );
$ json = $ hateoas -> serialize ( $ user , ' json ' );
$ xml = $ hateoas -> serialize ( $ user , ' xml ' );
อ็อบเจ็กต์ $hateoas
เป็นอินสแตนซ์ของ JMSSerializerSerializerInterface
ที่มาจากไลบรารี Serializer Hateoas ไม่ได้มาพร้อมกับซีเรียลไลเซอร์ของตัวเอง แต่จะเชื่อมต่อกับ JMS Serializer
ตามค่าเริ่มต้น Hateoas จะใช้ Hypertext Application Language (HAL) สำหรับการทำให้เป็นอนุกรม JSON สิ่งนี้ระบุ โครงสร้าง ของการตอบสนอง (เช่น "ลิงก์" ควรอยู่ภายใต้คีย์ _links
):
{
"id" : 42 ,
"first_name" : " Adrien " ,
"last_name" : " Brault " ,
"_links" : {
"self" : {
"href" : " /api/users/42 "
}
}
}
สำหรับ XML นั้น Atom Links จะถูกใช้เป็นค่าเริ่มต้น:
< user id = " 42 " >
< first_name > <![CDATA[ Adrien ]]> </ first_name >
< last_name > <![CDATA[ Brault ]]> </ last_name >
< link rel = " self " href = " /api/users/42 " />
</ user >
เป็นมูลค่าการกล่าวขวัญว่ารูปแบบเหล่านี้เป็น รูปแบบเริ่มต้น ไม่ใช่รูปแบบเดียวที่มีอยู่ คุณสามารถใช้รูปแบบที่แตกต่างกันผ่านซีเรียลไลเซอร์ที่แตกต่างกัน และยังเพิ่มรูปแบบของคุณเองได้อีกด้วย
ตอนนี้คุณรู้วิธีเพิ่ม ลิงก์ แล้ว เรามาดูวิธีเพิ่ม ทรัพยากรแบบฝังกัน ดีกว่า
บางครั้ง การฝังทรัพยากรที่เกี่ยวข้องแทนที่จะลิงก์ไปยังทรัพยากรเหล่านั้นจะมีประสิทธิภาพมากกว่า เนื่องจากจะป้องกันไม่ให้ไคลเอ็นต์ส่งคำขอเพิ่มเติมเพื่อดึงทรัพยากรเหล่านั้น
ทรัพยากรที่ฝังตัว คือ ความสัมพันธ์ ที่มีชื่อซึ่งมีข้อมูล ซึ่งแสดงโดยพารามิเตอร์ embedded
use JMS Serializer Annotation as Serializer ;
use Hateoas Configuration Annotation as Hateoas ;
/ * *
* ...
*
* @ Hateoas Relation (
* "manager" ,
* href = "expr('/api/users/' ~ object.getManager().getId())" ,
* embedded = "expr(object.getManager())" ,
* exclusion = @ Hateoas Exclusion ( excludeIf = "expr(object.getManager() === null)" )
* )
* /
class User
{
...
/ * * @ Serializer Exclude * /
private $ manager ;
}
use JMS Serializer Annotation as Serializer ;
use Hateoas Configuration Annotation as Hateoas ;
#[ Hateoas Relation(
' manager ' ,
href: " expr('/api/users/' ~ object.getManager().getId()) " ,
embedded: " expr(object.getManager()) " ,
exclusion: new Hateoas Exclusion (excludeif: " expr(object.getManager() === null) " ),
)]
class User
{
...
#[ Serializer Exclude]
private $ manager ;
}
หมายเหตุ: คุณจะต้องแยกคุณสมบัติตัวจัดการออกจากการทำให้เป็นอนุกรม ไม่เช่นนั้นทั้งตัวซีเรียลไลเซอร์และ Hateoas จะทำให้เป็นอนุกรม คุณจะต้องแยกความสัมพันธ์ของผู้จัดการออกเมื่อผู้จัดการเป็น null
เพราะไม่เช่นนั้นจะเกิดข้อผิดพลาดเมื่อสร้างลิงก์ href
(เรียก getId()
บน null
)
เคล็ดลับ: หากคุณสมบัติผู้จัดการเป็นออบเจ็กต์ที่มีลิงก์ _self
อยู่แล้ว คุณสามารถใช้ค่านั้นซ้ำสำหรับ href
แทนที่จะทำซ้ำที่นี่ ดู LinkHelper
$ hateoas = HateoasBuilder:: create ()-> build ();
$ user = new User ( 42 , ' Adrien ' , ' Brault ' , new User ( 23 , ' Will ' , ' Durand ' ));
$ json = $ hateoas -> serialize ( $ user , ' json ' );
$ xml = $ hateoas -> serialize ( $ user , ' xml ' );
สำหรับ json
การเป็นตัวแทน HAL จะวางความสัมพันธ์ที่ฝังไว้เหล่านี้ไว้ในคีย์ _embedded
:
{
"id" : 42 ,
"first_name" : " Adrien " ,
"last_name" : " Brault " ,
"_links" : {
"self" : {
"href" : " /api/users/42 "
},
"manager" : {
"href" : " /api/users/23 "
}
},
"_embedded" : {
"manager" : {
"id" : 23 ,
"first_name" : " Will " ,
"last_name" : " Durand " ,
"_links" : {
"self" : {
"href" : " /api/users/23 "
}
}
}
}
}
ใน XML การเรียงลำดับความสัมพันธ์ embedded
จะสร้างองค์ประกอบใหม่:
< user id = " 42 " >
< first_name > <![CDATA[ Adrien ]]> </ first_name >
< last_name > <![CDATA[ Brault ]]> </ last_name >
< link rel = " self " href = " /api/users/42 " />
< link rel = " manager " href = " /api/users/23 " />
< manager rel = " manager " id = " 23 " >
< first_name > <![CDATA[ Will ]]> </ first_name >
< last_name > <![CDATA[ Durand ]]> </ last_name >
< link rel = " self " href = " /api/users/23 " />
</ manager >
</ user >
ชื่อแท็กของทรัพยากรที่ฝังอยู่อนุมานจากคำอธิบายประกอบ @XmlRoot
( xml_root_name
ใน YAML, xml-root-name
ใน XML) ที่มาจากการกำหนดค่า Serializer
ไลบรารีมีหลายคลาสในเนมสเปซ HateoasRepresentation*
เพื่อช่วยคุณในงานทั่วไป เหล่านี้เป็นคลาสง่ายๆ ที่กำหนดค่าด้วยคำอธิบายประกอบของไลบรารี
คลาส PaginatedRepresentation
, OffsetRepresentation
และ CollectionRepresentation
น่าจะเป็นคลาสที่น่าสนใจที่สุด สิ่งเหล่านี้มีประโยชน์เมื่อทรัพยากรของคุณคือชุดของทรัพยากรจริงๆ (เช่น /users
คือชุดของผู้ใช้) สิ่งเหล่านี้ช่วยให้คุณเป็นตัวแทนของคอลเลกชันและเพิ่มการแบ่งหน้าและขีดจำกัด:
use Hateoas Representation PaginatedRepresentation ;
use Hateoas Representation CollectionRepresentation ;
$ paginatedCollection = new PaginatedRepresentation (
new CollectionRepresentation ( array ( $ user1 , $ user2 , ...)),
' user_list ' , // route
array (), // route parameters
1 , // page number
20 , // limit
4 , // total pages
' page ' , // page route parameter name , optional , defaults to 'page'
' limit ' , // limit route parameter name , optional , defaults to 'limit'
false , // generate relative URIs , optional , defaults to `false`
75 // total collection size , optional , defaults to `null`
);
$ json = $ hateoas -> serialize ( $ paginatedCollection , ' json ' );
$ xml = $ hateoas -> serialize ( $ paginatedCollection , ' xml ' );
CollectionRepresentation
นำเสนอการแสดงพื้นฐานของคอลเลกชันแบบฝัง
PaginatedRepresentation
ได้รับการออกแบบมาเพื่อเพิ่มลิงก์ self
, first
และเมื่อเป็นไปได้ last
, next
และ previous
OffsetRepresentation
ทำงานเหมือนกับ PaginatedRepresentation
แต่มีประโยชน์เมื่อการแบ่งหน้าแสดงด้วย offset
, limit
และ total
RouteAwareRepresentation
เพิ่มความสัมพันธ์ self
ตามเส้นทางที่กำหนด
คุณสามารถสร้าง URI ที่สมบูรณ์ได้ โดยการตั้งค่าพารามิเตอร์ absolute
เป็น true
ทั้งใน PaginatedRepresentation
และ RouteAwareRepresentation
ไลบรารี Hateoas ยังมี PagerfantaFactory
เพื่อสร้าง PaginatedRepresentation
จากอินสแตนซ์ Pagerfanta ได้อย่างง่ายดาย หากคุณใช้ไลบรารี Pagerfanta นี่เป็นวิธีที่ง่ายกว่าในการสร้างการนำเสนอคอลเลกชัน:
use Hateoas Configuration Route ;
use Hateoas Representation Factory PagerfantaFactory ;
$ pagerfantaFactory = new PagerfantaFactory (); // you can pass the page ,
// and limit parameters name
$ paginatedCollection = $ pagerfantaFactory -> createRepresentation (
$ pager ,
new Route ( ' user_list ' , array ())
);
$ json = $ hateoas -> serialize ( $ paginatedCollection , ' json ' );
$ xml = $ hateoas -> serialize ( $ paginatedCollection , ' xml ' );
คุณจะได้รับเนื้อหา JSON ต่อไปนี้:
{
"page" : 1 ,
"limit" : 10 ,
"pages" : 1 ,
"_links" : {
"self" : {
"href" : " /api/users?page=1&limit=10 "
},
"first" : {
"href" : " /api/users?page=1&limit=10 "
},
"last" : {
"href" : " /api/users?page=1&limit=10 "
}
},
"_embedded" : {
"items" : [
{ "id" : 123 },
{ "id" : 456 }
]
}
}
และเนื้อหา XML ต่อไปนี้:
<? xml version = " 1.0 " encoding = " UTF-8 " ?>
< collection page = " 1 " limit = " 10 " pages = " 1 " >
< entry id = " 123 " ></ entry >
< entry id = " 456 " ></ entry >
< link rel = " self " href = " /api/users?page=1 & limit=10 " />
< link rel = " first " href = " /api/users?page=1 & limit=10 " />
< link rel = " last " href = " /api/users?page=1 & limit=10 " />
</ collection >
หากคุณต้องการปรับแต่ง CollectionRepresentation
แบบอินไลน์ ให้ส่งอาร์กิวเมนต์ตัวที่สามของเมธอด createRepresentation()
:
use Hateoas Representation Factory PagerfantaFactory ;
$ pagerfantaFactory = new PagerfantaFactory (); // you can pass the page and limit parameters name
$ paginatedCollection = $ pagerfantaFactory -> createRepresentation (
$ pager ,
new Route ( ' user_list ' , array ()),
new CollectionRepresentation ( $ pager -> getCurrentPageResults ())
);
$ json = $ hateoas -> serialize ( $ paginatedCollection , ' json ' );
$ xml = $ hateoas -> serialize ( $ paginatedCollection , ' xml ' );
หากคุณต้องการเปลี่ยนชื่อรูท xml ของคอลเลกชัน ให้สร้างคลาสใหม่ด้วยการกำหนดค่ารูท xml และใช้กลไกอินไลน์:
use JMS Serializer Annotation as Serializer ;
/ * *
* @ Serializer XmlRoot ( "users" )
* /
class UsersRepresentation
{
/ * *
* @ Serializer Inline
* /
private $ inline ;
public function __construct ( $ inline )
{
$ this -> inline = $ inline ;
}
}
$ paginatedCollection = . . . ;
$ paginatedCollection = new UsersRepresentation ( $ paginatedCollection );
use JMS Serializer Annotation as Serializer ;
#[ Serializer XmlRoot( ' users ' )]
class UsersRepresentation
{
#[ Serializer Inline]
private $ inline ;
public function __construct ( $ inline )
{
$ this -> inline = $ inline ;
}
}
$ paginatedCollection = . . . ;
$ paginatedCollection = new UsersRepresentation ( $ paginatedCollection );
ตามที่กล่าวไว้ในส่วนก่อนหน้า การแสดงแทน คือคลาสที่กำหนดค่าด้วยคำอธิบายประกอบของไลบรารีเพื่อช่วยคุณในงานทั่วไป การแสดงคอลเลกชัน มีอธิบายไว้ในการจัดการกับคอลเลกชัน
VndErrorRepresentation
ช่วยให้คุณสามารถอธิบายการตอบสนองข้อผิดพลาดตามข้อกำหนด vnd.error
$ error = new VndErrorRepresentation (
' Validation failed ' ,
42 ,
' http://.../ ' ,
' http://.../ '
);
การทำให้การแสดงเป็นอนุกรมใน XML และ JSON จะให้ผลลัพธ์ต่อไปนี้:
<? xml version = " 1.0 " encoding = " UTF-8 " ?>
< resource logref = " 42 " >
< message > <![CDATA[ Validation failed ]]> </ message >
< link rel = " help " href = " http://.../ " />
< link rel = " describes " href = " http://.../ " />
</ resource >
{
"message" : " Validation failed " ,
"logref" : 42 ,
"_links" : {
"help" : {
"href" : " http://.../ "
},
"describes" : {
"href" : " http://.../ "
}
}
}
คำแนะนำ: ขอแนะนำให้สร้างคลาสข้อผิดพลาดของคุณเองที่ขยายคลาส VndErrorRepresentation
Hateoas อาศัยส่วนประกอบ Symfony ExpressionLanguage อันทรงพลังเพื่อดึงค่าต่างๆ เช่น ลิงก์ รหัส หรืออ็อบเจ็กต์ที่จะฝัง
แต่ละครั้งที่คุณกรอกค่า (เช่น Relation href
ในคำอธิบายประกอบหรือ YAML) คุณสามารถส่งผ่าน ค่าฮาร์ดโค้ด หรือ นิพจน์ ได้ ในการใช้ Expression Language คุณต้องใช้เครื่องหมาย expr()
:
use Hateoas Configuration Annotation as Hateoas ;
/ * *
* @ Hateoas Relation ( "self" , href = "expr('/api/users/' ~ object.getId())" )
* /
use Hateoas Configuration Annotation as Hateoas ;
#[ Hateoas Relation( ' self ' , href: " expr('/api/users/' ~ object.getId()) " )]
คุณสามารถเรียนรู้เพิ่มเติมเกี่ยวกับไวยากรณ์ของนิพจน์ได้โดยอ่านเอกสารอย่างเป็นทางการ: ไวยากรณ์ของนิพจน์
โดยทั่วไปแล้ว object
ที่มีชื่อตัวแปรพิเศษจะพร้อมใช้งานในแต่ละนิพจน์ และแสดงถึงวัตถุปัจจุบัน:
expr(object.getId())
เราเรียกตัวแปรดังกล่าวว่า ตัวแปรบริบท
คุณสามารถเพิ่มตัวแปรบริบทของคุณเองลงในบริบทภาษาของนิพจน์ได้โดยการเพิ่มลงในตัวประเมินนิพจน์
การใช้ HateoasBuilder
เรียกเมธอด setExpressionContextVariable()
เพื่อเพิ่มตัวแปรบริบทใหม่:
use Hateoas HateoasBuilder ;
$ hateoas = HateoasBuilder:: create ()
-> setExpressionContextVariable ( ' foo ' , new Foo ())
-> build ();
ตัวแปร foo
พร้อมใช้งานแล้ว:
expr(foo !== null)
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีเพิ่มฟังก์ชันให้กับภาษานิพจน์ โปรดดูที่ https://symfony.com/doc/current/components/expression_language/extending.html
เนื่องจากคุณสามารถใช้ Expression Language เพื่อกำหนดลิงก์ความสัมพันธ์ (คีย์ href
) คุณจึงสามารถทำอะไรได้มากมายตามค่าเริ่มต้น อย่างไรก็ตาม หากคุณใช้เฟรมเวิร์ก มีโอกาสที่คุณจะต้องการใช้เส้นทางเพื่อสร้างลิงก์
ก่อนอื่นคุณจะต้องกำหนดค่า UrlGenerator
บนตัวสร้าง คุณสามารถใช้ HateoasUrlGeneratorUrlGeneratorInterface
หรือใช้ HateoasUrlGeneratorCallableUrlGenerator
:
use Hateoas UrlGenerator CallableUrlGenerator ;
$ hateoas = HateoasBuilder:: create ()
-> setUrlGenerator (
null , // By default all links uses the generator configured with the null name
new CallableUrlGenerator ( function ( $ route , array $ parameters , $ absolute ) use ( $ myFramework ) {
return $ myFramework -> generateTheUrl ( $ route , $ parameters , $ absolute );
})
)
-> build ()
;
จากนั้นคุณจะสามารถใช้คำอธิบายประกอบ @Route ได้:
use Hateoas Configuration Annotation as Hateoas ;
/ * *
* @ Hateoas Relation (
* "self" ,
* href = @ Hateoas Route (
* "user_get" ,
* parameters = {
* "id" = "expr(object.getId())"
* }
* )
* )
* /
class User
use Hateoas Configuration Annotation as Hateoas ;
#[ Hateoas Relation(
' self ' ,
href: new Hateoas Route (
' user_get ' ,
parameters: [
' id ' => ' expr(object.getId()) ' ,
],
)
)]
class User
{
"id" : 42 ,
"first_name" : " Adrien " ,
"last_name" : " Brault " ,
"_links" : {
"self" : {
"href" : " /api/users/42 "
}
}
}
โปรดทราบว่าไลบรารีมาพร้อมกับ SymfonyUrlGenerator
ตัวอย่างเช่น หากต้องการใช้ใน Silex:
use Hateoas UrlGenerator SymfonyUrlGenerator ;
$ hateoas = HateoasBuilder:: create ()
-> setUrlGenerator ( null , new SymfonyUrlGenerator ( $ app [ ' url_generator ' ]))
-> build ()
;
Hateoas จัดเตรียมชุดตัวช่วยเพื่อทำให้กระบวนการสร้าง API ง่ายขึ้น
คลาส LinkHelper
จัดเตรียมเมธอด getLinkHref($object, $rel, $absolute = false)
ที่ช่วยให้คุณได้รับค่า href ของอ็อบเจ็กต์ใดๆ สำหรับชื่อความสัมพันธ์ที่กำหนด สามารถสร้าง URI (ทั้งแบบสัมบูรณ์หรือแบบสัมพัทธ์) จากความสัมพันธ์ ของลิงก์ ใดๆ:
$ user = new User ( 123 , ' William ' , ' Durand ' );
$ linkHelper -> getLinkHref ( $ user , ' self ' );
// / api / users / 123
$ linkHelper -> getLinkHref ( $ user , ' self ' , true );
// http : // example . com / api / users / 123
link
คุณลักษณะข้างต้นยังมีให้ใช้งานในนิพจน์ของคุณ (เทียบกับภาษานิพจน์) ผ่านทาง ฟังก์ชัน link(object, rel, absolute)
:
/ * *
* @ Hateoas Relation (
* "self" ,
* href = @ Hateoas Route ( "post_get" , parameters = { "id" = "expr(object.getId())" })
* )
* /
class Post {}
/ * *
* @ Hateoas Relation (
* "self" ,
* href = @ Hateoas Route ( "user_get" , parameters = { "id" = "expr(object.getId())" })
* )
* @ Hateoas Relation (
* "post" ,
* href = "expr(link(object.getPost(), 'self', true))"
* )
* @ Hateoas Relation (
* "relative" ,
* href = "expr(link(object.getRelativePost(), 'self'))"
* )
* /
class User
{
...
public function getPost ()
{
return new Post ( 456 );
}
public function getRelativePost ()
{
return new Post ( 789 );
}
}
#[ Hateoas Relation(
' self ' ,
href: new Hateoas Route (
' post_get ' ,
parameters: [
' id ' => ' expr(object.getId()) ' ,
],
),
)]
class Post {}
#[ Hateoas Relation(
' self ' ,
href: new Hateoas Route (
' user_get ' ,
parameters: [
' id ' => ' expr(object.getId()) ' ,
],
),
)]
#[ Hateoas Relation(
' post ' ,
href: " expr(link(object.getPost(), 'self', true)) " ,
)]
#[ Hateoas Relation(
' relative ' ,
href: " expr(link(object.getRelativePost(), 'self')) " ,
)]
class User
{
...
public function getPost ()
{
return new Post ( 456 );
}
public function getRelativePost ()
{
return new Post ( 789 );
}
}
โปรดใส่ใจกับนิพจน์ href
สำหรับ post
และความสัมพันธ์ relative
รวมถึงค่าที่เกี่ยวข้องในเนื้อหา JSON ต่อไปนี้:
{
"user" : {
"id" : 123 ,
"first_name" : " William " ,
"last_name" : " Durand " ,
"_links" : {
"self" : { "href" : " http://example.com/api/users/123 " },
"post" : { "href" : " http://example.com/api/posts/456 " },
"relative" : { "href" : " /api/posts/789 " }
}
}
}
เป็นที่น่าสังเกตว่าคุณสามารถ บังคับ ว่าคุณต้องการ URI แบบสัมบูรณ์หรือแบบสัมพัทธ์โดยใช้อาร์กิวเมนต์ที่สามในทั้งเมธอด getLinkHref()
และฟังก์ชัน link
สำคัญ: โดยค่าเริ่มต้น URI ทั้งหมดจะ สัมพันธ์กัน แม้ว่าจะถูกกำหนดให้เป็น แบบสัมบูรณ์ ในการกำหนดค่าก็ตาม
$ linkHelper -> getLinkHref ( $ user , ' post ' );
// / api / posts / 456
$ linkHelper -> getLinkHref ( $ user , ' post ' , true );
// http : // example . com / api / posts / 456
$ linkHelper -> getLinkHref ( $ user , ' relative ' );
// / api / posts / 789
$ linkHelper -> getLinkHref ( $ user , ' relative ' , true );
// http : // example . com / api / posts / 789
Hateoas ยังมีชุดส่วนขยาย Twig อีกด้วย
LinkExtension
อนุญาตให้คุณใช้ LinkHelper ในเทมเพลต Twig ของคุณ เพื่อให้คุณสามารถสร้างลิงก์ในเทมเพลต HTML ของคุณได้ เป็นต้น
ส่วนขยายนี้เปิดเผยวิธีการของตัวช่วย getLinkHref()
ผ่านฟังก์ชัน link_href
Twig:
{{ link_href(user, 'self') }}
{# will generate: /users/123 #}
{{ link_href(will, 'self', false) }}
{# will generate: /users/123 #}
{{ link_href(will, 'self', true) }}
{# will generate: http://example.com/users/123 #}
Hateoas จัดให้มีชุด ซีเรียลไลเซอร์ ตัวซีเรียลไลเซอร์ แต่ละตัวช่วยให้คุณสร้างเนื้อหา XML หรือ JSON ตาม รูปแบบ เฉพาะ เช่น HAL หรือ Atom Links เป็นต้น
JsonHalSerializer
ช่วยให้คุณสร้างความสัมพันธ์ที่สอดคล้องกับ HAL ใน JSON มันเป็นซีเรียลไลเซอร์ JSON เริ่มต้นใน Hateoas
HAL จัดเตรียมความสามารถในการเชื่อมโยงด้วยแบบแผนซึ่งระบุว่าวัตถุทรัพยากรมีคุณสมบัติที่สงวนไว้ที่เรียกว่า _links
คุณสมบัตินี้เป็นออบเจ็กต์ที่มีลิงก์ ลิงก์เหล่านี้ถูกคีย์โดยความสัมพันธ์ของลิงก์
HAL ยังอธิบายแบบแผนอื่นที่ระบุว่าทรัพยากรอาจมีคุณสมบัติที่สงวนไว้อื่นชื่อ _embedded
คุณสมบัตินี้คล้ายกับ _links
ในทรัพยากรที่ฝังไว้นั้นถูกคีย์ด้วยชื่อความสัมพันธ์ ข้อแตกต่างหลักๆ ก็คือ แทนที่จะเป็นลิงก์ ค่าต่างๆ จะเป็นอ็อบเจ็กต์ทรัพยากร
{
"message" : " Hello, World! " ,
"_links" : {
"self" : {
"href" : " /notes/0 "
}
},
"_embedded" : {
"associated_events" : [
{
"name" : " SymfonyCon " ,
"date" : " 2013-12-12T00:00:00+0100 "
}
]
}
}
XmlSerializer
ช่วยให้คุณสร้าง Atom Links ลงในเอกสาร XML ของคุณได้ มันเป็นตัวสร้างอนุกรม XML เริ่มต้น
<? xml version = " 1.0 " encoding = " UTF-8 " ?>
< note >
< message > <![CDATA[ Hello, World! ]]> </ message >
< link rel = " self " href = " /notes/0 " />
< events rel = " associated_events " >
< event >
< name > <![CDATA[ SymfonyCon ]]> </ name >
< date > <![CDATA[ 2013-12-12T00:00:00+0100 ]]> </ date >
</ event >
</ events >
</ note >
XmlHalSerializer
ช่วยให้คุณสร้างความสัมพันธ์ที่สอดคล้องกับ HAL ใน XML
HAL ใน XML คล้ายกับ HAL ใน JSON ในแง่ที่อธิบายแท็ก link
และแท็ก resource
หมายเหตุ: ความสัมพันธ์ self
จะกลายเป็นคุณลักษณะของทรัพยากรหลักแทนที่จะเป็นแท็ก link
ลิงก์อื่นๆ จะถูกสร้างขึ้นเป็นแท็ก link
<? xml version = " 1.0 " encoding = " UTF-8 " ?>
< note href = " /notes/0 " >
< message > <![CDATA[ Hello, World! ]]> </ message >
< resource rel = " associated_events " >
< name > <![CDATA[ SymfonyCon ]]> </ name >
< date > <![CDATA[ 2013-12-12T00:00:00+0100 ]]> </ date >
</ resource >
</ note >
คุณต้องใช้ SerializerInterface
ที่อธิบายสองวิธีในการทำให้ ลิงก์ เป็นอนุกรมและความสัมพันธ์ แบบฝัง
คลาส HateoasBuilder
ใช้เพื่อกำหนดค่า Hateoas ได้อย่างง่ายดายด้วย API ที่ทรงพลังและคล่องแคล่ว
use Hateoas HateoasBuilder ;
$ hateoas = HateoasBuilder:: create ()
-> setCacheDir ( ' /path/to/cache/dir ' )
-> setDebug ( $ trueOrFalse )
-> setDefaultXmlSerializer ()
. . .
-> build ();
วิธีการทั้งหมดด้านล่างจะส่งคืนตัวสร้างปัจจุบัน เพื่อให้คุณสามารถโยงพวกมันได้
setXmlSerializer(SerializerInterface $xmlSerializer)
: ตั้งค่า XML serializer ที่จะใช้ ค่าเริ่มต้นคือ: XmlSerializer
;setDefaultXmlSerializer()
: ตั้งค่า XML serializer เริ่มต้น ( XmlSerializer
) setJsonSerializer(SerializerInterface $jsonSerializer)
: ตั้งค่า JSON serializer ที่จะใช้ ค่าเริ่มต้นคือ: JsonHalSerializer
;setDefaultJsonSerializer()
: ตั้งค่าเริ่มต้น JSON serializer ( JsonHalSerializer
) setUrlGenerator($name = null, UrlGeneratorInterface $urlGenerator)
: เพิ่มตัวสร้าง URL ที่มีชื่อใหม่ หาก $name
เป็น null
ตัวสร้าง URL จะเป็นค่าเริ่มต้น setExpressionContextVariable($name, $value)
: เพิ่มตัวแปรบริบทนิพจน์ใหม่setExpressionLanguage(ExpressionLanguage $expressionLanguage)
; includeInterfaceMetadata($include)
: ว่าจะรวมข้อมูลเมตาจากอินเทอร์เฟซหรือไม่setMetadataDirs(array $namespacePrefixToDirMap)
: ตั้งค่าแมปของคำนำหน้าเนมสเปซให้กับไดเร็กทอรี วิธีการนี้จะแทนที่ไดเร็กทอรีที่กำหนดไว้ก่อนหน้านี้addMetadataDir($dir, $namespacePrefix = '')
: เพิ่มไดเร็กทอรีที่ serializer จะค้นหาข้อมูลเมตาของคลาสaddMetadataDirs(array $namespacePrefixToDirMap)
: เพิ่มแมปของคำนำหน้าเนมสเปซให้กับไดเร็กทอรีreplaceMetadataDir($dir, $namespacePrefix = '')
: คล้ายกับ addMetadataDir()
แต่แทนที่รายการที่มีอยู่โปรดอ่านเอกสาร Serializer อย่างเป็นทางการสำหรับรายละเอียดเพิ่มเติม
setDebug($debug)
: เปิดใช้งานหรือปิดใช้งานโหมดดีบัก;setCacheDir($dir)
: ตั้งค่าไดเร็กทอรีแคชทั้งซีเรียลไลเซอร์และไลบรารี Hateoas รวบรวมข้อมูลเมตาเกี่ยวกับออบเจ็กต์ของคุณจากแหล่งต่างๆ เช่น YML, XML หรือคำอธิบายประกอบ เพื่อให้กระบวนการนี้มีประสิทธิภาพมากที่สุดเท่าที่จะเป็นไปได้ ขอแนะนำให้คุณอนุญาตให้ไลบรารี Hateoas แคชข้อมูลนี้ หากต้องการทำเช่นนั้น ให้กำหนดค่าไดเรกทอรีแคช:
$ builder = Hateoas HateoasBuilder:: create ();
$ hateoas = $ builder
-> setCacheDir ( $ someWritableDir )
-> build ();
Hateoas รองรับแหล่งข้อมูลเมตาหลายแหล่ง ตามค่าเริ่มต้น จะใช้คำอธิบายประกอบหลักคำสอน (PHP < 8.1) หรือแอตทริบิวต์ PHP ดั้งเดิม (PHP >= 8.1) แต่คุณอาจจัดเก็บข้อมูลเมตาในไฟล์ XML หรือ YAML ได้เช่นกัน สำหรับอย่างหลัง จำเป็นต้องกำหนดค่าไดเร็กทอรีข้อมูลเมตาซึ่งมีไฟล์เหล่านั้นอยู่:
$ hateoas = Hateoas HateoasBuilder:: create ()
-> addMetadataDir ( $ someDir )
-> build ();
Hateoas คาดหวังว่าไฟล์ข้อมูลเมตาจะได้รับการตั้งชื่อเหมือนชื่อคลาสแบบเต็มโดยที่ ทั้งหมดจะถูกแทนที่ด้วย
.
- หากคลาสของคุณชื่อ VendorPackageFoo
ไฟล์ข้อมูลเมตาจะต้องอยู่ที่ $someDir/Vendor.Package.Foo.(xml|yml)
Hateoas อนุญาตให้เฟรมเวิร์กเพิ่มความสัมพันธ์ให้กับคลาสแบบไดนามิกโดยจัดให้มีจุดส่วนขยายที่ระดับการกำหนดค่า คุณลักษณะนี้จะมีประโยชน์สำหรับผู้ที่ต้องการสร้างเลเยอร์ใหม่ที่ด้านบนของ Hateoas หรือเพื่อเพิ่มความสัมพันธ์ "ทั่วโลก" แทนที่จะคัดลอกการกำหนดค่าเดียวกันในแต่ละคลาส
เพื่อใช้ประโยชน์จากกลไกนี้ ต้องใช้อินเทอร์เฟซ ConfigurationExtensionInterface
:
use Hateoas Configuration Metadata ConfigurationExtensionInterface ;
use Hateoas Configuration Metadata ClassMetadataInterface ;
use Hateoas Configuration Relation ;
class AcmeFooConfigurationExtension implements ConfigurationExtensionInterface
{
/ * *
* {@ inheritDoc }
* /
public function decorate ( ClassMetadataInterface $ classMetadata ): void
{
if ( 0 === strpos ( ' AcmeFooModel ' , $ classMetadata -> getName ())) {
// Add a "root" relation to all classes in the `AcmeFooModel` namespace
$ classMetadata -> addRelation (
new Relation (
' root ' ,
' / '
)
);
}
}
}
คุณสามารถเข้าถึงความสัมพันธ์ที่มีอยู่ซึ่งโหลดจาก Annotations, XML หรือ YAML ด้วย $classMetadata->getRelations()
หาก $classMetadata
มีความสัมพันธ์ หรือหากคุณเพิ่มความสัมพันธ์เข้าไป ความสัมพันธ์นั้นจะถูกแคช ดังนั้น หากคุณอ่านไฟล์การกำหนดค่า (คำอธิบายประกอบ, XML หรือ YAML) อย่าลืมอ้างอิงไฟล์เหล่านั้นในข้อมูลเมตาของชั้นเรียน:
$ classMetadata -> fileResources [] = $ file ;
<? xml version = " 1.0 " encoding = " UTF-8 " ?>
< serializer >
< class name = " AcmeDemoRepresentationUser " h : providers = " Class::getRelations expr(sevice('foo').getMyAdditionalRelations()) " xmlns : h = " https://github.com/willdurand/Hateoas " >
< h : relation rel = " self " >
< h : href uri = " http://acme.com/foo/1 " />
</ h : relation >
< h : relation rel = " friends " >
< h : href route = " user_friends " generator = " my_custom_generator " >
< h : parameter name = " id " value = " expr(object.getId()) " />
< h : parameter name = " page " value = " 1 " />
</ h : ref >
< h : embedded xml-element-name = " users " >
< h : content >expr(object.getFriends())</ h : content >
< h : exclusion ... />
</ h : embedded >
< h : exclusion groups = " Default, user_full " since-version = " 1.0 " until-version = " 2.2 " exclude-if = " expr(object.getFriends() === null) " />
</ h : relation >
</ class >
</ serializer >
ดูไฟล์ hateoas.xsd
สำหรับรายละเอียดเพิ่มเติม
AcmeDemoRepresentationUser :
relations :
-
rel : self
href : http://acme.com/foo/1
-
rel : friends
href :
route : user_friends
parameters :
id : expr(object.getId())
page : 1
generator : my_custom_generator
absolute : false
embedded :
content : expr(object.getFriends())
xmlElementName : users
exclusion : ...
exclusion :
groups : [Default, user_full]
since_version : 1.0
until_version : 2.2
exclude_if : expr(object.getFriends() === null)
relation_providers : [ "Class::getRelations", "expr(sevice('foo').getMyAdditionalRelations())" ]
คำอธิบายประกอบนี้สามารถกำหนดบนชั้นเรียนได้
use Hateoas Configuration Annotation as Hateoas ;
/ * *
* @ Hateoas Relation (
* name = "self" ,
* href = "http://hello" ,
* embedded = "expr(object.getHello())" ,
* attributes = { "foo" = "bar" },
* exclusion = ...,
* )
* /
use Hateoas Configuration Annotation as Hateoas ;
#[ Hateoas Relation(
name: ' self ' ,
href: ' http://hello ' ,
embedded: ' expr(object.getHello()) ' ,
attributes: [ ' foo ' => ' bar ' ],
exclusion: ' ... ' ,
)]
คุณสมบัติ | ที่จำเป็น | เนื้อหา | ภาษาการแสดงออก |
---|---|---|---|
ชื่อ | ใช่ | เชือก | เลขที่ |
href | หากไม่ได้ตั้งค่าแบบฝังไว้ | สตริง / @Route | ใช่ |
ฝังตัว | หากไม่ได้ตั้งค่า href | สตริง / @Embedded | ใช่ |
คุณลักษณะ | เลขที่ | อาร์เรย์ | ใช่กับค่านิยม |
การยกเว้น | เลขที่ | @การยกเว้น | ไม่มี |
สิ่งสำคัญ: attributes
จะใช้เฉพาะกับ ความสัมพันธ์ของลิงก์ เท่านั้น (เช่น รวมกับคุณสมบัติ href
ไม่ใช่กับคุณสมบัติ embedded
)
use Hateoas Configuration Annotation as Hateoas ;
/ * *
* @ Hateoas Relation (
* name = "self" ,
* href = @ Hateoas Route (
* "user_get" ,
* parameters = { "id" = "expr(object.getId())" },
* absolute = true ,
* generator = "my_custom_generator"
* )
* )
* /
use Hateoas Configuration Annotation as Hateoas ;
#[ Hateoas Relation(
name: ' self ' ,
href: new Hateoas Route (
' user_get ' ,
parameters: [ ' id ' = ' expr (object. getId ())'],
absolute: true ,
generator: ' my_custom_generator ' ,
),
)]
คำอธิบายประกอบนี้สามารถกำหนดได้ในคุณสมบัติ href ของคำอธิบายประกอบ @Relation ซึ่งจะช่วยให้คุณสามารถสร้าง URL ของคุณได้ หากคุณได้กำหนดค่าไว้
คุณสมบัติ | ที่จำเป็น | เนื้อหา | ภาษาการแสดงออก |
---|---|---|---|
ชื่อ | ใช่ | เชือก | เลขที่ |
พารามิเตอร์ | ค่าเริ่มต้นเป็นอาร์เรย์ () | อาร์เรย์ / สตริง | ใช่ (ค่าสตริง + อาร์เรย์) |
แน่นอน | ค่าเริ่มต้นเป็นเท็จ | บูลีน / สตริง | ใช่ |
เครื่องกำเนิดไฟฟ้า | เลขที่ | สตริง / โมฆะ | เลขที่ |
use Hateoas Configuration Annotation as Hateoas ;
/ * *
* @ Hateoas Relation (
* name = "friends" ,
* embedded = @ Hateoas Embedded (
* "expr(object.getFriends())" ,
* exclusion = ...,
* xmlElementName = "users"
* )
* )
* /
use Hateoas Configuration Annotation as Hateoas ;
#[ Hateoas Relation(
name: ' friends ' ,
embedded: new Hateoas Embedded (
' expr(object.getFriends()) ' ,
exclusion: ' ... ' ,
xmlElementName: ' users ' ,
),
)]
คำอธิบายประกอบนี้สามารถกำหนดได้ในคุณสมบัติ แบบฝัง ของคำอธิบายประกอบ @Relation ซึ่งจะมีประโยชน์หากคุณต้องการกำหนดค่าตัวเลือก exclusion
หรือ xmlElementName
สำหรับทรัพยากรที่ฝังตัว
คุณสมบัติ | ที่จำเป็น | เนื้อหา | ภาษาการแสดงออก |
---|---|---|---|
เนื้อหา | ใช่ | สตริง / อาร์เรย์ | ใช่ (สตริง) |
การยกเว้น | ค่าเริ่มต้นเป็นอาร์เรย์ () | @การยกเว้น | ไม่มี |
xmlElementName | ค่าเริ่มต้นเป็นอาร์เรย์ () | เชือก | เลขที่ |
คำอธิบายประกอบนี้สามารถกำหนดได้ในคุณสมบัติ การแยก ของทั้งคำอธิบายประกอบ @Relation และ @Embedded
คุณสมบัติ | ที่จำเป็น | เนื้อหา | ภาษาการแสดงออก |
---|---|---|---|
กลุ่ม | เลขที่ | อาร์เรย์ | เลขที่ |
ตั้งแต่เวอร์ชัน | เลขที่ | เชือก | เลขที่ |
จนกระทั่งเวอร์ชัน | เลขที่ | เชือก | เลขที่ |
ความลึกสูงสุด | เลขที่ | จำนวนเต็ม | เลขที่ |
ไม่รวมถ้า | เลขที่ | สตริง / บูลีน | ใช่ |
ค่าทั้งหมดยกเว้น excludeIf
ทำหน้าที่ในลักษณะเดียวกับเมื่อใช้โดยตรงบนคุณสมบัติปกติด้วยซีเรียลไลเซอร์
excludeIf
คาดหวังบูลีนและมีประโยชน์เมื่อนิพจน์อื่นอาจล้มเหลวในบางกรณี ในตัวอย่างนี้ หากเมธอด getManager
เป็น null
คุณควรแยกออกเพื่อป้องกันไม่ให้การสร้าง URL ล้มเหลว:
use Hateoas Configuration Annotation as Hateoas ;
/ * *
* @ Hateoas Relation (
* "manager" ,
* href = @ Hateoas Route (
* "user_get" ,
* parameters = { "id" = "expr(object.getManager().getId())" }
* ),
* exclusion = @ Hateoas Exclusion ( excludeIf = "expr(null === object.getManager())" )
* )
* /
class User
{
public function getId () {}
/ * *
* @ return User | null
* /
public function getManager () {}
}
use Hateoas Configuration Annotation as Hateoas ;
#[ Hateoas Relation(
name: ' manager ' ,
href: new Hateoas Route (
' user_get ' ,
parameters: [ ' id ' => ' expr(object.getManager().getId()) ' ],
),
exclusion: new Hateoas Exclusion (excludeIf: ' expr(null === object.getManager()) ' )
)]
class User
{
public function getId () {}
public function getManager (): ? User {}
}
คำอธิบายประกอบนี้สามารถกำหนดบนชั้นเรียนได้ มันมีประโยชน์ถ้าคุณต้องการทำให้ความสัมพันธ์พหุสัมพันธ์เป็นอนุกรม (ลิงก์) เป็นตัวอย่าง:
{
"_links": {
"relation_name": [
{"href": "link1"},
{"href": "link2"},
{"href": "link3"}
]
}
}
คุณสมบัติ | ที่จำเป็น | เนื้อหา | ภาษาการแสดงออก |
---|---|---|---|
ชื่อ | ใช่ | เชือก | ใช่ |
อาจเป็น "ชื่อ":
my_func
MyClass::getExtraRelations
expr(service('user.rel_provider').getExtraRelations())
ที่นี่และตัวอย่างการใช้ภาษานิพจน์:
use Hateoas Configuration Annotation as Hateoas ;
/ * *
* @ Hateoas RelationProvider ( "expr(service('user.rel_provider').getExtraRelations())" )
* /
class User
{
...
}
use Hateoas Configuration Annotation as Hateoas ;
#[ Hateoas RelationProvider( " expr(service('user.rel_provider').getExtraRelations()) " )]
class User
{
...
}
นี่คือคลาส UserRelPrvider
:
use Hateoas Configuration Relation ;
use Hateoas Configuration Route ;
class UserRelPrvider
{
private $ evaluator ;
public function __construct ( CompilableExpressionEvaluatorInterface $ evaluator )
{
$ this -> evaluator = $ evaluator ;
}
/ * *
* @ return Relation []
* /
public function getExtraRelations (): array
{
// You need to return the relations
return array (
new Relation (
' self ' ,
new Route (
' foo_get ' ,
[ ' id ' => $ this -> evaluator -> parse ( ' object.getId() ' , [ ' object ' ])]
)
)
);
}
}
$this->evaluator
ที่ใช้ CompilableExpressionEvaluatorInterface
ใช้เพื่อแยกวิเคราะห์ภาษานิพจน์ในรูปแบบที่สามารถแคชและบันทึกเพื่อใช้ในภายหลัง หากคุณไม่ต้องการภาษานิพจน์ในความสัมพันธ์ของคุณ ก็ไม่จำเป็นต้องใช้บริการนี้
บริการ user.rel_provider
ถูกกำหนดเป็น:
user.rel_provider :
class : UserRelPrvider
arguments :
- ' @jms_serializer.expression_evaluator '
ในกรณีนี้ jms_serializer.expression_evaluator
เป็นบริการที่ใช้ CompilableExpressionEvaluatorInterface
ส่วนนี้อ้างอิงถึงส่วนภายในของ Hateoas ซึ่งจัดทำเอกสารเกี่ยวกับส่วนที่ซ่อนอยู่ของไลบรารีนี้ สิ่งนี้อาจไม่เกี่ยวข้องกับผู้ใช้ปลายทางเสมอไป แต่น่าสนใจสำหรับนักพัฒนาหรือผู้ที่สนใจเรียนรู้วิธีการทำงานของสิ่งต่าง ๆ ภายใต้ประทุน
willdurand/hateoas
เป็นไปตามการกำหนดเวอร์ชันเชิงความหมาย
ตั้งแต่เดือนตุลาคม 2013 เวอร์ชัน 1.x
และ 0.x
จะไม่ได้รับการสนับสนุนอย่างเป็นทางการอีกต่อไป (โปรดทราบว่า 1.x
ไม่เคยเปิดตัว)
เวอร์ชัน 3.x
เป็นเวอร์ชันเสถียรหลักในปัจจุบัน
เวอร์ชัน 2.x
ได้รับการดูแลเฉพาะสำหรับการแก้ไขข้อบกพร่องด้านความปลอดภัยและสำหรับปัญหาหลักที่อาจเกิดขึ้นเท่านั้น
ดูไฟล์ที่มีส่วนร่วม
ติดตั้งการพึ่งพา Composer dev
:
php composer.phar install --dev
จากนั้นรันชุดทดสอบโดยใช้ PHPUnit:
bin/phpunit
Hateoas ได้รับการเผยแพร่ภายใต้ใบอนุญาต MIT ดูรายละเอียดในไฟล์ LICENSE ที่ให้มา