PHP Ionic Angular HTML5 AJAX Javascript CSS MySQL jQuery Forum


เริ่มต้นการใช้งาน Flex Message ผ่าน LINE Messaging API ตอนที่ 9

06 April 2019 By Ninenik Narkdee
line bot sdk bot messaging api flex message

คำสั่ง การ กำหนด รูปแบบ ตัวอย่าง เทคนิค ลูกเล่น การประยุกต์ การใช้งาน เกี่ยวกับ line bot sdk bot messaging api flex message



เนื้อหาในตอนต่อไปนี้ เราจะมาดูเกี่ยวกับการใช้งาน Flex Message ซึ่งเป็นรูปแบบ
หนึ่งของข้อความที่ Bot สามารถโต้ตอบกับผู้ใช้ โดยมีความสามารถในการจัดรูปแบบ
ของข้อความได้มากขึ้นกว่าเดิม
    ทบทวนรูปแบบของข้อความที่สามารถใช้งานผ่าน Messaging API ได้ที่บทความตามลิ้งค์ด้านล่าง
    การใช้งาน Template Message ใน LINE Messaging API ตอนที่ 3 http://niik.in/836
    https://www.ninenik.com/content.php?arti_id=836 via @ninenik
 

ตัวอย่างหน้าตาข้อความแบบ Flex Message

 
'
 
 
ในบทความนี้ เรายังใช้งาน Line bot sdk สำหรับ PHP ในการจัดการข้อความกับ LINE Messaging API
และยิ่งเมื่อเราต้องการเพิ่มความสามารถหรือคุณสมบัติของ bot มากขึ้น โค้ดหรือคำสั่งต่างๆ ก็จะเพิ่มขึ้น
ตามไปด้วย สำหรับใน Flex Message ก็เหมือนกัน เนื่องจาก Flex Message เป็นการสร้างรูปแบบข้อความ
ตามที่เรากำหนด โดยสามารถเลือกองค์ประกอบที่ต้องการมารวมกัน ยิ่งรูปแบบข้อความที่เราต้องการมีความ
ซับซ้อนมากเท่าใด ความยากและรูปแบบของโค้ดก็จะยิ่งเพิ่มไปด้วย ด้วยเหตุนี้ ในเนื้อหาจึงขอเป็นการประยุกต์
การใช้งาน โดยมีการกำหนดรูปแบบใหม่ที่มีการปรับแต่ง ให้สะดวก และใช้งานง่าย โดยใช้รูปแบบ XML โดยติดตาม
รายละเอียดได้ตามลำดับ
 
 

โครงสร้างข้อมูลของ Flex Message

    รูปแบบโครงสร้างข้อมูลที่ใช้ในการสร้าง Flex Message จะเป็นรูปแบบ JSON ซึ่งเป็นรูปแบบเดียวกับข้อความ
ประเภทอื่นๆ โดยมีค่าและคุณสมบัติ ตามรูปแบบที่ Line กำหนด     การใช้ Library ในภาษาต่างๆ เช่น
Line bot sdk สำหรับ PHP ก็เป็นเพียงรูปแบบคำสั่งสำหรับทำการสร้างโครงสร้างของ JSON  เมื่อได้รูปแบบข้อความ
แล้ว ก็ทำการส่งค่าไปยังระบบของ Line เพื่อกำหนดเป็นข้อความส่งต่อไปยังผู้ใช้อีกที
    โครงสร้าง JSON ของ Flex Message ดูเพิ่มเติมได้ที่ 
    https://developers.line.biz/en/reference/messaging-api/#flex-message
 

    ตัวอย่างโครงสร้าง JSON ข้อความ Flex Message

{  
  "type": "flex",
  "altText": "this is a flex message",
  "contents": {
    "type": "bubble",
    "body": {
      "type": "box",
      "layout": "vertical",
      "contents": [
        {
          "type": "text",
          "text": "hello"
        },
        {
          "type": "text",
          "text": "world"
        }
      ]
    }
  }
}
 

    การส่งข้อมูลผ่าน Messaging API


curl -v -X POST https://api.line.me/v2/bot/message/push \
-H 'Content-Type:application/json' \
-H 'Authorization: Bearer {channel access token}' \
-d '{
  "to": "U4af4980629...",
  "messages": [
    {
      "type": "flex",
      "altText": "This is a Flex Message",
      "contents": {
        "type": "bubble",
        "body": {
          "type": "box",
          "layout": "horizontal",
          "contents": [
            {
              "type": "text",
              "text": "Hello,"
            },
            {
              "type": "text",
              "text": "World!"
            }
          ]
        }
      }
    }
  ]
}'
 

    กานส่งข้อมูลผ่าน Messaging API ด้วย Line bot sdk

$textReplyMessage = new BubbleContainerBuilder(
	"ltr",NULL,NULL,
	new BoxComponentBuilder(
		"vertical",
		array(
			new TextComponentBuilder("hello"),
			new TextComponentBuilder("world")
		)
	)
);
$replyData = new FlexMessageBuilder("This is a Flex Message",$textReplyMessage);    
 

องค์ประกอบของ Flex Message

 


 
    Flex Message ประกอบด้วยโครงสร้าง 3 ส่วน คือ container , block และ component หรือเข้าใจโดยง่ายคือ
container อยู่นอกสุด และมี block ซ้อนด้านใน ซึ่งในแต่ละ block ก็จะมี component อยู่อีกที  โครงสร้างแบบ tree
ก็จะเป็นในลักษณะ ดังนี้
 
|-- container
       |--- block
               |--- component
 
Container
    เป็นส่วนนอกสุด หรือ top-level ของ Flex Message แบ่งออกเป็น 2 ประเภท ได้แก่
  •     Bubble สำหรับกำหนด single bubble  (รูปตัวอย่างด้านบนคือ 1 bubble)
  •     Carousel สำหรับกำหนด Multiple bubble (มี bubble หลายอันเรียงกันในแนวนอน ไม่เกิน 10)
 
Block
    เป็นส่วนองค์ประกอบสำหรับสร้าง bubble แบ่งออกเป็น 4 ประเภท ได้แก่
  •     Header สำหรับแสดงหัวเรื่องของข้อความ หรือ ส่วนข้อมูลนำเรื่อง
  •     Hero สำหรับแสดงรูปภาพของเนื้อหา
  •     Body สำหรับแสดงส่่วนของเนื้อหาหลัก
  •     Footer สำหรับแสดงรายละเอียดย่อย หรือ ส่วนข้อมูลปิดท้าย
 
Component
    เป็นส่วนองค์ประกอบสำหรับสร้าง block แบ่งออกเป็น 8 ประเภท แยกย่อยเป็น
สองส่วนตามลักษณะของ component นั้นๆ 
    ส่วนที่ 1 ส่วนกำหนดเนื้อหาและรายละเอียดของข้อมูล
  •     Button สำหรับสร้างปุ่ม และสามารถกำหนด action ให้ทำงานมีกดปุ่มนนั้นๆ ได้
  •     Icon สำหรับสร้างรูปไอคอน
  •     Image สำหรับสร้างรูปภาพ
  •     Text สำหรับแสดงข้อความ สามารถจัดรูปแบบได้
    ส่วนที่ 2 ส่วนกำหนดการปรับแต่งเลเอาท์ของข้อความ
  •     Box สำหรับกำหนดส่วนของเลเอาท์ที่มี component ย่อยด้านในอีกที สามารถซ้อนหลายขั้นได้
  •     Filler สำหรับกำหนดพื้นที่ว่างเพื่อเติมเต็มจุดที่ต้องการ โดยมีความสูง / ความกว้าง อย่างใดอย่างหนึ่ง
  •     Separator สำหรับสร้างเส้นคั่น
  •     Spacer สำหรับกำหนดพื้นที่ว่างก่อนหรือหลัง box component ที่ต้องการ

 

การใช้งาน Line bot sdk เพื่อสร้าง Flex Message

    เราได้รู้จักองค์ประกอบคร่าวๆ ของแต่ละส่วนของ Flex Message ไปแล้ว ต่อไปเราจะมาดูวิธ๊การใช้งาน
Line bot sdk เพื่อสร้าง และจัดการ Flex Message โดยจะไล่ไปตามลำดับของแต่ละตัว พร้อมตัวอย่าง
สำหรับการกำหนดในรูปแบบ JSON สามารถดูได้ที่เว็บไซต์ Line Developers ได้เลย
    https://developers.line.biz/en/docs/messaging-api/flex-message-elements/
 
    ในตัวอย่างเราจะมีรูปแบบการกำหนดโดยใช้รูปแบบ XML เป็นตัวอย่างไปพร้อมด้วย
 

การสร้าง Bubble

รูปแบบ PHP
/**
 * BubbleContainerBuilder constructor.
 *
 * @param ContainerDirection|null $direction
 * @param BoxComponentBuilder|null $headerComponentBuilder
 * @param ImageComponentBuilder|null $heroComponentBuilder
 * @param BoxComponentBuilder|null $bodyComponentBuilder
 * @param BoxComponentBuilder|null $footerComponentBuilder
 * @param BubbleStylesBuilder|null $stylesBuilder
 */
 // ส่วนประกอบของ Bubble ประกอบด้วย parameter ต่างๆ ดังนี้
/*public function __construct(
	$direction = null, // กำหนด NULL หรือ "ltr" หรือ "rtl"
	$headerComponentBuilder = null, // box component ของ header block
	$heroComponentBuilder = null, // image component ของ hero block
	$bodyComponentBuilder = null,  // box component ของ body block
	$footerComponentBuilder = null,  // box component ของ footer block
	$stylesBuilder = null // style ของแต่ละ block
)*/

$textReplyMessage = new BubbleContainerBuilder(
	"ltr",  // กำหนด NULL หรือ "ltr" หรือ "rtl"
	new BoxComponentBuilder(
		"vertical",
		array(
			new TextComponentBuilder("This is Header")
		)
	),
	new ImageComponentBuilder(
		"https://www.ninenik.com/images/ninenik_page_logo.png",NULL,NULL,NULL,NULL,"full","20:13","cover"),
	new BoxComponentBuilder(
		"vertical",
		array(
			new TextComponentBuilder("This is Body")
		)
	),
	new BoxComponentBuilder(
		"vertical",
		array(
			new TextComponentBuilder("This is Footer")
		)
	),
	new BubbleStylesBuilder( // style ทั้งหมดของ bubble
		new BlockStyleBuilder("#FFC90E"),  // style สำหรับ header block
		new BlockStyleBuilder("#EFE4B0"), // style สำหรับ hero block
		new BlockStyleBuilder("#B5E61D"), // style สำหรับ body block
		new BlockStyleBuilder("#FFF200") // style สำหรับ footer block
	)
);
$replyData = new FlexMessageBuilder("Flex",$textReplyMessage);        
รูปแบบ XML
<noncarousel>
	<bubble direction="ltr">
		<header backgroundColor="#FFC90E">
			<box layout="vertical">
				<text>This is Header</text>
			</box>
		</header>
		<hero backgroundColor="#EFE4B0">
			<image url="https://www.ninenik.com/images/ninenik_page_logo.png"
			 	size="full" aspectRatio="20:13" aspectMode="cover" />
		</hero>
		<body backgroundColor="#B5E61D">
			<box layout="vertical">
				<text>This is Body</text>
			</box>
		</body>		
		<footer backgroundColor="#FFF200">
			<box layout="vertical">
				<text>This is Footer</text>
			</box>
		</footer>
	</bubble>
</noncarousel>	
รูปผลลัพธ์

 



 

การสร้าง Carousel

รูปแบบ PHP
/**
 * CarouselContainerBuilder  constructor.
 *
 * @param BubbleContainerBuilder[] $containerBuilders
 */
/*public function __construct($containerBuilders)
{
	$this->containerBuilders = $containerBuilders;
}
	*/
	
$textReplyMessage = new CarouselContainerBuilder(
	array(
		new BubbleContainerBuilder(
			"ltr",  // กำหนด NULL หรือ "ltr" หรือ "rtl"
			NULL,NULL,
			new BoxComponentBuilder(
				"horizontal",
				array(
					new TextComponentBuilder("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed 
					do eiusmod tempor incididunt ut labore et dolore magna aliqua.",NULL,NULL,NULL,NULL,NULL,true)
				)
			),
			new BoxComponentBuilder(
				"horizontal",
				array(
					new ButtonComponentBuilder(
						new UriTemplateActionBuilder("GO","http://niik.in"),
						NULL,NULL,NULL,"primary"
					)
				)
			)
		), // end bubble 1
		new BubbleContainerBuilder(
			"ltr",  // กำหนด NULL หรือ "ltr" หรือ "rtl"
			NULL,NULL,
			new BoxComponentBuilder(
				"horizontal",
				array(
					new TextComponentBuilder("Hello, World!",NULL,NULL,NULL,NULL,NULL,true)
				)
			),
			new BoxComponentBuilder(
				"horizontal",
				array(
					new ButtonComponentBuilder(
						new UriTemplateActionBuilder("GO","http://niik.in"),
						NULL,NULL,NULL,"primary"
					)
				)
			)
		) // end bubble 2		
	)
);
$replyData = new FlexMessageBuilder("Flex",$textReplyMessage);    
 
รูปแบบ XML
<carousel>
	<bubble direction="ltr">
		<body>
			<box layout="horizontal">
				<text wrap="true">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed 
				do eiusmod tempor incididunt ut labore et dolore magna aliqua.</text>
			</box>
		</body>		
		<footer>
			<box layout="horizontal">
				<button style="primary" action="u(http://niik.in)">
				Go
				</button>
			</box>
		</footer>
	</bubble>
	<bubble direction="ltr">
		<body>
			<box layout="horizontal">
				<text wrap="true">Hello, World!</text>
			</box>
		</body>		
		<footer>
			<box layout="horizontal">
				<button style="primary" action="u(http://niik.in)">
				Go
				</button>
			</box>
		</footer>
	</bubble>	
</carousel>	
 
รูปผลลัพธ์
 
 



 

การสร้าง Box Component

    box component จะอยู่ภายใน block ดูส่วนของ box component ส่วนที่ highlight
รูปแบบ PHP
/**
 * BoxComponentBuilder constructor.
 *
 * @param ComponentLayout|string $layout
 * @param ComponentBuilder[] $componentBuilders
 * @param int|null $flex
 * @param ComponentSpacing|string|null $spacing
 * @param ComponentMargin|null $margin
 * @param TemplateActionBuilder|null $actionBuilder
 */
/**
public function __construct(
	$layout,
	$componentBuilders,
	$flex = null,
	$spacing = null,
	$margin = null,
	$actionBuilder = null
)
*/
	
$textReplyMessage = new BubbleContainerBuilder(
			"ltr",  // กำหนด NULL หรือ "ltr" หรือ "rtl"
			NULL,NULL,
			new BoxComponentBuilder(
				"horizontal",
				array(
					new TextComponentBuilder("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed 
					do eiusmod tempor incididunt ut labore et dolore magna aliqua.",NULL,NULL,NULL,NULL,NULL,true)
				)
			),
			new BoxComponentBuilder(
				"horizontal",
				array(
					new ButtonComponentBuilder(
						new UriTemplateActionBuilder("GO","http://niik.in"),
						NULL,NULL,NULL,"primary"
					)
				)
			)
		);

$replyData = new FlexMessageBuilder("Flex",$textReplyMessage);    
 
รูปแบบ XML
<noncarousel>
	<bubble direction="ltr">
		<body>
			<box layout="horizontal">
				<text wrap="true">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed 
				do eiusmod tempor incididunt ut labore et dolore magna aliqua.</text>
			</box>
		</body>		
		<footer>
			<box layout="horizontal">
				<button style="primary" action="u(http://niik.in)">
				Go
				</button>
			</box>
		</footer>
	</bubble>
</noncarousel>	
 
รูปผลลัพธ์
 
 



 

การสร้าง Button Component

รูปแบบ PHP
/**
 * ButtonComponentBuilder constructor.
 *
 * @param TemplateActionBuilder $actionBuilder
 * @param int|null $flex
 * @param ComponentMargin|null $margin
 * @param ComponentButtonHeight|null $height
 * @param ComponentButtonStyle|null $style
 * @param string|null $color
 * @param ComponentGravity|null $gravity
 */
/**  
    public function __construct(
        $actionBuilder,
        $flex = null,
        $margin = null,
        $height = null,
        $style = null,
        $color = null,
        $gravity = null
    )
*/

$textReplyMessage = new BubbleContainerBuilder(
			"ltr",  // กำหนด NULL หรือ "ltr" หรือ "rtl"
			NULL,NULL,
			new BoxComponentBuilder(
				"vertical",
				array(
					new ButtonComponentBuilder(
						new UriTemplateActionBuilder("Primary style button","http://niik.in"),
						NULL,NULL,NULL,"primary"
					),
					new ButtonComponentBuilder(
						new UriTemplateActionBuilder("Secondary  style button","http://niik.in"),
						NULL,NULL,NULL,"secondary"
					),			
					new ButtonComponentBuilder(
						new UriTemplateActionBuilder("Link  style button","http://niik.in"),
						NULL,NULL,NULL,"link"
					),									
				),
				0,"md"
			)
		);		

$replyData = new FlexMessageBuilder("Flex",$textReplyMessage);       
 
รูปแบบ XML
<noncarousel>
	<bubble direction="ltr">
		<body>
			<box layout="vertical" spacing="md">
				<button style="primary" action="u(http://niik.in)">
				Primary style button
				</button>
				<button style="secondary" action="u(http://niik.in)">
				Secondary style button
				</button>
				<button style="link" action="u(http://niik.in)">
				Link style button
				</button>								
			</box>
		</body>		
	</bubble>
</noncarousel>	
 
รูปผลลัพธ์
 
 
 


 

การสร้าง Filler Component

รูปแบบ PHP
$textReplyMessage = new BubbleContainerBuilder(
			"ltr",  // กำหนด NULL หรือ "ltr" หรือ "rtl"
			NULL,NULL,
			new BoxComponentBuilder(
				"horizontal",
				array(
					new ImageComponentBuilder("https://www.ninenik.com/images/ninenik_page_logo.png"),
					new FillerComponentBuilder(),
					new ImageComponentBuilder("https://www.ninenik.com/images/ninenik_page_logo.png")																											
				)
			)
		);		

$replyData = new FlexMessageBuilder("Flex",$textReplyMessage);       	
 
รูปแบบ XML
<noncarousel>
	<bubble direction="ltr">
		<body>
			<box layout="horizontal">
				<image url="https://www.ninenik.com/images/ninenik_page_logo.png" />		
				<filler />
				<image url="https://www.ninenik.com/images/ninenik_page_logo.png" />		
			</box>
		</body>		
	</bubble>
</noncarousel>	
 
รูปผลลัพธ์
 
 
 
 
 
 

การสร้าง Icon Component

รูปแบบ PHP
/**
 * IconComponentBuilder constructor.
 *
 * @param string $url
 * @param ComponentMargin|null $margin
 * @param ComponentIconSize|null $size
 * @param ComponentIconAspectRatio|null $aspectRatio
 */
   /**	 
	public function __construct(
		$url, 
		$margin = null, 
		$size = null, 
		$aspectRatio = null
	)
*/
$textReplyMessage = new BubbleContainerBuilder(
			"ltr",  // กำหนด NULL หรือ "ltr" หรือ "rtl"
			NULL,NULL,
			new BoxComponentBuilder(
				"vertical",
				array(
					new BoxComponentBuilder(
						"baseline",
						array(
							new IconComponentBuilder("https://www.ninenik.com/images/ninenik_page_logo.png",NULL,"md"),
							new TextComponentBuilder("The quick brown fox jumps over the lazy dog",NULL,NULL,"md")							
						)
					),		
					new BoxComponentBuilder(
						"baseline",
						array(
							new IconComponentBuilder("https://www.ninenik.com/images/ninenik_page_logo.png",NULL,"lg"),
							new TextComponentBuilder("The quick brown fox jumps over the lazy dog",NULL,NULL,"lg")							
						)
					),
					new BoxComponentBuilder(
						"baseline",
						array(
							new IconComponentBuilder("https://www.ninenik.com/images/ninenik_page_logo.png",NULL,"xl"),
							new TextComponentBuilder("The quick brown fox jumps over the lazy dog",NULL,NULL,"xl")							
						)
					),
					new BoxComponentBuilder(
						"baseline",
						array(
							new IconComponentBuilder("https://www.ninenik.com/images/ninenik_page_logo.png",NULL,"xxl"),
							new TextComponentBuilder("The quick brown fox jumps over the lazy dog",NULL,NULL,"xxl")							
						)
					),
					new BoxComponentBuilder(
						"baseline",
						array(
							new IconComponentBuilder("https://www.ninenik.com/images/ninenik_page_logo.png",NULL,"3xl"),
							new TextComponentBuilder("The quick brown fox jumps over the lazy dog",NULL,NULL,"3xl")							
						)
					)																														
				)
			)
		);		

$replyData = new FlexMessageBuilder("Flex",$textReplyMessage);        
 
รูปแบบ XML
<noncarousel>
	<bubble direction="ltr">
		<body>
			<box layout="vertical">
				<box layout="baseline">
					<icon url="https://www.ninenik.com/images/ninenik_page_logo.png" size="md" />
					<text size="md">The quick brown fox jumps over the lazy dog</text>
				</box>			
				<box layout="baseline">
					<icon url="https://www.ninenik.com/images/ninenik_page_logo.png" size="lg" />
					<text size="lg">The quick brown fox jumps over the lazy dog</text>
				</box>		
				<box layout="baseline">
					<icon url="https://www.ninenik.com/images/ninenik_page_logo.png" size="xl" />
					<text size="xl">The quick brown fox jumps over the lazy dog</text>
				</box>		
				<box layout="baseline">
					<icon url="https://www.ninenik.com/images/ninenik_page_logo.png" size="xxl" />
					<text size="xxl">The quick brown fox jumps over the lazy dog</text>
				</box>		
				<box layout="baseline">
					<icon url="https://www.ninenik.com/images/ninenik_page_logo.png" size="3xl" />
					<text size="3xl">The quick brown fox jumps over the lazy dog</text>
				</box>																					
			</box>
		</body>		
	</bubble>
</noncarousel>	
 
รูปผลลัพธ์
 
 
 
 
 
 

การสร้าง Image Component

รูปแบบ PHP
/**
 * ImageComponentBuilder constructor.
 *
 * @param string $url
 * @param int|null $flex
 * @param ComponentMargin|null $margin
 * @param ComponentAlign|null $align
 * @param ComponentGravity|null $gravity
 * @param ComponentImageSize|null $size
 * @param ComponentImageAspectRatio|null $aspectRatio
 * @param ComponentImageAspectMode|null $aspectMode
 * @param string|null $backgroundColor
 * @param TemplateActionBuilder|null $actionBuilder
 */
/* 
    public function __construct(
        $url,
        $flex = null,
        $margin = null,
        $align = null,
        $gravity = null,
        $size = null,
        $aspectRatio = null,
        $aspectMode = null,
        $backgroundColor = null,
        $actionBuilder = null
    ) 
	*/
$textReplyMessage = new BubbleContainerBuilder(
			"ltr",  // กำหนด NULL หรือ "ltr" หรือ "rtl"
			NULL,NULL,
			new BoxComponentBuilder(
				"horizontal",
				array(
					new ImageComponentBuilder("https://www.ninenik.com/images/ninenik_page_logo.png",NULL,NULL,NULL,NULL,"md")																									
				)
			)
		);		

$replyData = new FlexMessageBuilder("Flex",$textReplyMessage);   
 
รูปแบบ XML
<noncarousel>
	<bubble direction="ltr">
		<body>
			<box layout="horizontal">
				<image url="https://www.ninenik.com/images/ninenik_page_logo.png" size="md" />			
			</box>
		</body>		
	</bubble>
</noncarousel>	
 
รูปผลลัพธ์
 

 
 
การกำหนดขนาดของรูป
    หากไม่ได้กำหนด size ให้กับรูปภาพ    ค่าเริ่มต้นของ size property ของ Image Component จะเท่ากับ md 
ค่า size คือค่าความกว้างที่สูงสุดของ Component โดยสามารถกำหนดค่า ขนาดจากน้อยไปมากตามค่าต่างๆ ดังต่อไปนี้
    ค่า size ที่สามารถกำหนดได้ ได้แก่ xxs, xs, sm, md, lg, xl, xxl, 3xl, 4xl, 5xl, หรือ full
 
การกำหนด Aspect ratio 
    คือการกำหนด อัตราส่วนพื้นที่แสดงรูป ส่วนมากจะกำหนดเมื่อต้องการแสดงรูปแบบเต็มพื้นที่ หรือรูปขนาดใหญ่ เช่น
ใช้ร่วมกับการกำหนด size เป็น full
   aspectRatio เป็นอัตราส่วนความกว้าง กับความสูง ในรูปแบบ {width}:{height} ยกตัวอย่างรูปภาพขนาด 4:3 , 16:9
โดยปกติค่า aspectRatio ถ้าไม่กำหนด จะมีค่าเท่ากับ 1:1 เป็นค่าเริ่มต้น ก็คือพื้นที่สี่เหลี่ยมจัสดุรัส ซึ่งถ้ารูปเป็นรูปสี่เหลียม
จัสดุรัส ก็จะแสดงรูปนั้นเต็มพื้นที่ แต่ถ้าเป็นรูปแนวนอน ความกว้างมากกว่าความสูง เมื่อแสดงรูปตรงกลาง พื้นที่ของรูปใน
แนวตั้งจะมีช่องว่างพื้นหลังเกิดขึ้น เช่นเดียวกันกับกรณี ถ้าเป็นรูปแนวตั้ง ความสูงมากกว่าความกว้าง เมื่อแสดงรูปตรงกลาง
พื้นที่รูปแนวนอนก็จะมีช่องว่างพื้นหลังเกิดขึ้นเช่นกัน ดังนั้นกรณีเป็นแนวนอน เราอาจจะใช้ค่าความกว้างก้บค่าความสูงของรูปนั้น
เป็นอัตราส่วนเลยก็ได้ เช่น สมมติว่ารูปขนาดเท่ากับ 800 x 500  ก็กำหนดเป็น "800:500"  
    เราสามารถกำหนดค่าได้ตั้ง 1 ถึง 100000 แต่อย่างไรก็ตาม เราไม่สามารถกำหนดค่าความสูง มากกว่า 3 เท่าของความกว้างได้
เช่น 1:4 หรือ 200:650 ค่าในลักษณะนี้ จะกำหนดไม่ได้
 
การกำหนด Aspect Mode
   คือการกำหนดค่า aspectMode property ให้กับรูปภาพ ประกอบด้วยค่า fit และ cover ซึ่งกรณีที่ไม่ได้กำหนดค่า 
หรือค่าเริ่มต้นจะมีค่าเป็น fit คือแสดงให้เห็นรูปทั้งหมดในพื้นที่ ซึ่งถ้าเป็นรูปแนวตั้งหรือแนวนอน กรณี aspectRatio เป็น 1:1 
ก็จะเกิดช่องว่างพื้นหลัง ตามที่กล่าวไปแล้ว  ส่วนอีกรูปแบบคือ cover จะเป็นลักษณะเหมือนเอารูปไปใช้เป็นพื้นหลัง รูป
จะแสดงคลุมพืนที่ แต่บางส่วนของรูปอาจจะหายไป หากพื้นที่แสดงรูปมีขนาดเล็กกว่ารูปหรือมีสัดส่วนที่น้อยกว่าขนาดของรูป
ตัวอย่างเช่น ถ้ารูปกว้างและสูงเท่ากับ 500x500 แล้วเรากำหนด aspectRatio เป็น 4:3 นั้นหมายความว่า ความสูงของรูปจะหายไป
ดังรูปตัวอย่างด้านล่าง
 

 
 

 
 

การสร้าง Separator Component

รูปแบบ PHP
/**
 * SeparatorComponentBuilder constructor.
 *
 * @param ComponentMargin|null $margin
 * @param string|null $color
 */
/* 
    public function __construct(
		$margin = null, 
		$color = null
	)
	*/
	
$textReplyMessage = new BubbleContainerBuilder(
			"ltr",  // กำหนด NULL หรือ "ltr" หรือ "rtl"
			NULL,NULL,
			new BoxComponentBuilder(
				"vertical",
				array(
					new BoxComponentBuilder(
						"horizontal",
						array(
							new TextComponentBuilder("orange"),
							new SeparatorComponentBuilder(),
							new TextComponentBuilder("apple")							
						),
						0,"md"
					),
					new SeparatorComponentBuilder(),	
					new BoxComponentBuilder(
						"horizontal",
						array(
							new TextComponentBuilder("grape"),
							new SeparatorComponentBuilder(),
							new TextComponentBuilder("lemon")							
						),
						0,"md"
					)																										
				),
				0,"md"
			)
		);

$replyData = new FlexMessageBuilder("Flex",$textReplyMessage);       
 
รูปแบบ XML
<noncarousel>
	<bubble direction="ltr">
		<body>
			<box layout="vertical" spacing="md">
				<box layout="horizontal" spacing="md">
					<text>orange</text>
					<separator />
					<text>apple</text>
				</box>
				<separator />
				<box layout="horizontal" spacing="md">
					<text>grape</text>
					<separator />
					<text>lemon</text>
				</box>	
			</box>
		</body>		
	</bubble>
</noncarousel>	
 
รูปผลลัพธ์
 
 
 
 
 

การสร้าง Spacer Component

รูปแบบ PHP
/**
 * SpacerComponentBuilder constructor.
 *
 * @param ComponentSpaceSize|string $size
 */
/*
	public function __construct(
		$size
	)
*/	
	
$textReplyMessage = new BubbleContainerBuilder(
			"ltr",  // กำหนด NULL หรือ "ltr" หรือ "rtl"
			NULL,NULL,
			new BoxComponentBuilder(
				"vertical",
				array(
					new ImageComponentBuilder("https://www.ninenik.com/images/ninenik_page_logo.png",NULL,NULL,NULL,NULL,"full")																							
				)
			),
			new BoxComponentBuilder(
				"vertical",
				array(
					new SpacerComponentBuilder("xl"),
					new ButtonComponentBuilder(
						new UriTemplateActionBuilder("Tap me","http://niik.in"),
						NULL,NULL,NULL,"primary","#0000ff"
					)
				)
			)			
		);		

$replyData = new FlexMessageBuilder("Flex",$textReplyMessage);      
รูปแบบ XML
<noncarousel>
	<bubble direction="ltr">
		<body>
			<box layout="vertical">
				<image url="https://www.ninenik.com/images/ninenik_page_logo.png" size="full" />
			</box>
		</body>	
		<footer>
			<box layout="vertical">
				<spacer size="xl" />
				<button style="primary" color="#0000ff" action="u(http://niik.in)">Tap me</button>
			</box>
		</footer>	
	</bubble>
</noncarousel>	
 
รูปผลลัพธ์
 
 
 
 
 
 

การสร้าง Text Component

รูปแบบ PHP
/**
 * TextComponentBuilder constructor.
 *
 * @param string $text
 * @param int|null $flex
 * @param ComponentMargin|null $margin
 * @param ComponentFontSize|null $size
 * @param ComponentAlign|null $align
 * @param ComponentGravity|null $gravity
 * @param boolean|null $wrap
 * @param int|null $maxLines
 * @param ComponentFontWeight|null $weight
 * @param string|null $color
 * @param TemplateActionBuilder|null $actionBuilder
 */
 /**	 
    public function __construct(
        $text,
        $flex = null,
        $margin = null,
        $size = null,
        $align = null,
        $gravity = null,
        $wrap = null,
        $maxLines = null,
        $weight = null,
        $color = null,
        $actionBuilder = null
    )
*/	
	
$textReplyMessage = new BubbleContainerBuilder(
			"ltr",  // กำหนด NULL หรือ "ltr" หรือ "rtl"
			NULL,NULL,
			new BoxComponentBuilder(
				"vertical",
				array(
					new TextComponentBuilder("Closing the distance",NULL,NULL,"md","center",NULL,NULL,NULL,NULL,"#ff0000"),		
					new TextComponentBuilder("Closing the distance",NULL,NULL,"lg","center",NULL,NULL,NULL,NULL,"#00ff00"),
					new TextComponentBuilder("Closing the distance",NULL,NULL,"xl","center",NULL,NULL,NULL,"bold","#0000ff")																	
				)
			)			
		);		

$replyData = new FlexMessageBuilder("Flex",$textReplyMessage);        
 
รูปแบบ XML
<noncarousel>
	<bubble direction="ltr">
		<body>
			<box layout="vertical">
				<text size="md" align="center" color="#ff0000">Closing the distance</text>
				<text size="lg" align="center" color="#00ff00">Closing the distance</text>
				<text size="xl" align="center" color="#0000ff" weight="bold">Closing the distance</text>
			</box>
		</body>	
	</bubble>
</noncarousel>	
 
รูปผลลัพธ์
 

 
 


 

ทำความเข้าใจการใช้งาน Class ของ ส่วนต่างๆ

    รูปแบบการใช้งานแบบ PHP ข้างต้น สังเกตว่า เราได้นำรูปแบบ constructor หรือโครงสร้างของ class
ต่างๆ ว่าประกอบด้วย parameter อะไรบ้าง ค่าไหนเป็นค่าที่จำเป็นต้องระบุ ลำดับของ parameter เหล่านี้
เป็นต้น  ที่ยกส่วนของ constructor มาประกอบ เพื่อเป็นแนวทางในการใช้งาน 
    อย่างสมมติเช่น เราต้องการสร้างข้อความ
<?php

/**
 * TextComponentBuilder constructor.
 *
 * @param string $text
 * @param int|null $flex
 * @param ComponentMargin|null $margin
 * @param ComponentFontSize|null $size
 * @param ComponentAlign|null $align
 * @param ComponentGravity|null $gravity
 * @param boolean|null $wrap
 * @param int|null $maxLines
 * @param ComponentFontWeight|null $weight
 * @param string|null $color
 * @param TemplateActionBuilder|null $actionBuilder
 */
 /**	 
    public function __construct(
        $text,
        $flex = null,
        $margin = null,
        $size = null,
        $align = null,
        $gravity = null,
        $wrap = null,
        $maxLines = null,
        $weight = null,
        $color = null,
        $actionBuilder = null
    )
*/
    class ของข้อความคือ TextComponentBuilder การสร้าง Text Component ก็จะเริ่มต้นด้วย
 
    new TextComponentBuilder()
    ต่อไปเราก็ดูว่า Class นี้ต้องการ parameter กี่ตัว ตำไหนจำเป็นต้องระบุ จาก constructor ด้านบน 
จะเห็นว่า text มี parameter ที่สามารถกำหนดได้ทั้งหมด 11 ตัว โดยตัวที่ 2 - 11 มีการกำหนดค่าเริ่มต้น
เป็น null นั่นหมายความว่า ค่าเหล่านี้เป็น option คือไม่กำหนดก็ได้ แต่ถ้าต้องการข้ามลำดับของ parameter
ตัวใด เราก็ต้องกำหนดค่าเป็น null
    สมมติเราต้องการกำหนดข้อความว่า "Hello World"
    ก็จะได้เป็น
 
    new TextComponentBuilder("Hello World")
    คำว่า Hello world เป็น parameter ตัวแรก ที่เราต้องกำหนดเสมอ เพราะใน constructor ไม่ได้กำหนดค่า
เริ่มต้นเหมือนตัวอื่น หากเราไม่ได้กำหนดค่าอื่นๆ เพิ่มเติม ค่าเหล่านั้นจะเป็นค่า null ซึ่งเป็นค่าเริ่มต้น
 
    สมมติเราต้องการกำหนด size ให้กับข้อความ ซึ่ง size เป็น parameter ตัวที่ 4 
    ก็จะได้เป็น
 
    new TextComponentBuilder("Hello World",NULL,NULL,"xl")
    สำหรับตัวอื่นๆ ก็ใช้หลักการหรือแนวทางเดียวกัน
 
    บางตัว อาจจะไม่มี parameter อย่างเช่น Filler Component เวลาสร้างเราก็เรียกใช้แบบนี้ได้เลย
 
    new FillerComponentBuilder()
    สำหรับรูปแบบ XML ที่แสดงควบคู่ไปนั้น เป็นแนวทางการประยุกต์ ที่ผู้เขียนต้องการลดการทำงานหรือ
อำนวยความสะดวกในการสร้าง Flex Message รูปแบบ XML ข้างต้น จะถูกแปลงอัตโนมัติ ซึ่งจะขออธิบาย
เพิ่มเติม พร้อมกับวิธีการใช้งาน ในตอนหน้า 


 
 

การกำหนด Flex Message Layout

    จากรูปแบบโครงสร้างของ Flex Message เราทราบไปแล้วว่า Bubble หนึ่งจะมีด้วยกัน 4 Block คือ
Header, Hero , Body และ Footer โดยเวลาวางโครงเราต้องวางเรียงตามลำดับข้างต้น คือ จากบนลงล่าง
โดยเราจะแสดงหรือกำหนดทั้ง 4 Block พร้อมกันก็ได้ หรือจะเลือกแสดงเฉพาะบาง Block ตามรูปแบบ
ของข้อมูลก็ได้ อย่างสมมติเช่น เราต้องการแสดงรูปภาพหลัก กับปุ่ม ก็อาจจะใช้ Hero block สำหรับกำหนด
รูปภาพ และใช้ Footer block สำหรับกำหนดปุ่ม หรืออีกแบบ เราอาจจะใช้แค่ Body block แล้วซ้อน อันเดียว
แล้วแสดงทั้งรูปและปุ่มใน block เดียวก็ได้เช่นกัน
    ใน Block ทั้ง 4 ข้างต้น จะมี Hero block ที่มี child เป็น Image Component ไม่สามารถเป็นอย่างอื่นได้
ส่วน Header , Body และ Footer จะมี child เป็น Box Component ได้เพียง 1 อันเท่านั้น สมมติอธิบายในรูป
แบบ XML 
 
<body>
    <box></box>
    <box></box>
</body>
จะเป็นลักษณะข้างต้นไม่ได้ ที่ได้คือ
 
<body>
    <box></box>
</body>
แต่ Box component สามารถมี box child ก็อันก็ได้ จะได้เป็น
 
<body>
    <box>
        <box>
        </box>
        <box>
            <box>
            </box>
        </box>
    </box>
</body>
ในการจัดวางองค์ประกอบ Child element ต่างๆ ที่อยูใน Box Component ของ Flex Message จะถูกจัดเรียง
โดยเป็นไปตามคำสั่งหรือรูปแบบที่ใช้งานของ Box Component และ Child element นั้นๆ
    เนื้อหาในหัวข้อนี้ เราจะมาดูวิธีการปรับแต่งรูปแบบ รวมถึงการกำหนดขนาดขององค์ประกอบต่างๆ ใน 
Flex Message ดังนี้
 

ประเภท Layout ของ Box Component

    Box Component ทุกตัว ต้องมีการกำหนด Layout เสมอ โดยประเภทของ Layout ได้แก่
  •     horizontal   การจัดเรียงแนวนอน โดย component ต่างๆ จะต่อเรียงกันจากทางซ้ายไปขวาในแนวนอน
  •     vertical   การจัดเรียงแนวตั้ง โดย coponent ต่างๆ จะต่อเรียงกันจากบนลงล่างในแนวตั้ง
  •     baseline การจัดเรียงในแนวนอน เช่นเดียวกับ horizontal layout
 
    Component ที่สามารถกำหนดใน Baseline Box หรือ Box Component ที่กำหนด Layout เป็น
baseline ได้แก่ : Filler, Icon, Spacer และ Text components
    Component ที่สามารถกำหนดใน Box Component ที่กำหนด Layout เป็น horizontal หรือ vertical ได้แก่
Box, Button, Filler, Image, Separator, Spacer และ Text components
 
 
คุณลักษณะของ Baseline Box
    Baseline box เป็น Box Component ในแนวนอน ที่ Child หรือ Component ด้านในถูกจัดตำแหน่งในแนวตั้ง
อยู่ในแนวเดียวกับข้อความ Text Component  สำหรับข้อความที่มีขนาดแตกต่างกัน ก็จะจัดให้อยู่ในแนวเดียวกัน
ดูรูปด้านล่างประกอบ
    จำไว้ว่า เฉพาะ Icon Component เท่านั้น ที่สามารถกำหนดไว้ใน Baseline Box ได้ โดยแนวของ Icon จะอยู่
ชิดกับขอบด้านล่างของรูปไอคอน 
 
 
 
ความกว้างและความสูงของ Component
    ค่า Flex ของ Component ใดๆ จะหมายถึงความกว้างของ Component นั้นกรณีอยู่ใน horicontal box
และจะหมายถึงความสูงของ Component นั้นกรณีอยู่ใน vertical box
    ขออธิบาย Flex แยกออกเป็น 2 กรณีตามรูปแบบของ Layout
 
    กรณีเป็น Component ที่อยู่ใน Box แนวนอน (horizontal box)
    ค่า flex จะหมายถึงความกว้าง โดยถ้าไม่ได้กำหนดค่า ค่าเริ่มต้นจะเท่ากับ 1 ให้เข้าใจแบบนี้คือ
    สมมติมี Text Component อยู่ 3 รายการใน Box แนวนอน และไม่ได้กำหนด Flex property 
Text Component แต่ละตัวจะมี Flex เท่ากับ 1 ซึ่งเป็นค่าเริ่มต้น การจะดูว่าแต่ละ Component นั้น
กว้างคิดเป็น กี่เปอร์เซ็นต์จาก 100 หาได้จากสูตร 
 
(ค่า Flex ของ Component * 100) / ค่า Flex รวม 
ก็จะเท่ากับ (1*100)/3 เท่ากับ 33.33333333333333%
 
    ดังนั้นความกว้างของแต่ละ Component จะเท่ากันที่ประมาณ 33.33%
 
    สมมติใน horizontal box ของเรามี Component เป็น Text 2 ตัวติดกันตามรูปด้านล่าง 
 
 

 
 
    โดยเรากำหนด Flex ให้กับ ตัวแรกและตัวที่สองเป็น 2 และ 3 ตามลำดับ เราก็จะได้ความกว้างของ
Flex ที่เท่ากับ 2 เท่ากับ (2*100)/5 เท่ากับ 40% และได้ความกว้างของ Flex ที่เท่ากับ 3 เท่ากับ
(3*100)/5 เท่ากับ 60% 
 
    เราสามารถกำหนดความกว้างของ Coponent ใดๆ ให้เท่ากับความกว้างของเนื้อหาของ Component นั้นๆ ได้ 
โดยกำหนด Flex ให้เท่ากับ 0   ซึ่งเมื่อเรามีการกำหนด Component ใดๆเป็น 0 แล้ว ความกว้างของ Component นั้น
จะถูกนำไปลบออกจาก 100 เพื่อเป็นพื้นที่ที่เหลือสำหรับ Component อื่นๆ ทำให้สูตรการคำนวณสำหรับ Component
อื่น จะเปลี่ยนจากคูณ 100 เป็นค่าที่เหลือแทน 
    ยกตัวอย่าง สมมติว่ามี Text Component 3 อัน ตัวแรกเรากำหนด Flex เป็น 0 ตัวที่ 2 และ 3 กำหนด Flex เป็น 2 
และ 3 ตามลำดับ ถ้าหากว่าตัวแรก กว้างไปแล้ว 50% ตามเเนื้อหาที่กว้างของ Text ดังนั้นจะเหลือพื้นที่สำหรับตัวที่ 2 และ 3 
เท่ากับ 100 - 50 เท่ากับ 50 จะได้ความกว้างของ Text ที่สองเท่ากับ (2*50)/5 เท่ากับ 20% และความกว้างของ Text
ตัวที่สามเท่ากับ (3*50)/5 เท่ากับ 30%
 
    หากมีการกำหนด Flex เท่ากับ 0 ให้กับ Component ที่มีขนาดความกว้างของเนื้อหา Component นั้นเท่า 100% แล้ว
    จะมีผลให้ตัว Component ที่เหลือหลุดออกไปเฟรมไปหรือก็คือ ไม่แสดงนั่นเอง เพราะไม่มีพื้นที่เหลือเพียงพอ
 
 
    กรณีเป็น Component ที่อยู่ใน Box แนวตั้ง (vertical box)
    ค่า flex จะหมายถึงความสูง โดยถ้าไม่ได้กำหนดค่า ค่าเริ่มต้นจะเท่ากับ 0 หรือก็คือมีความสูง เท่ากับความสูงของ 
Component นั้นๆ
    ดูรูปด้านล่างประกอบคำอธิบาย
 
 


 
 
    สังเกต Text Component สองตัว ที่อยู่ฝั่งขวา ซึ่งมีการกำหนด Layout แนวตั้ง เหมือนกันทั้งสอง Bubble 
    Text Component ทั้งสองจะเรียงต่อกันจากบนลงล่าง    ใน Bubble แรก Text Component ไม่ได้มีการกำหนด 
    Flex หรือกำหนด Flex เท่ากับ 0 ทำให้ความสูงของแต่ละ Component เท่ากับความสูงของ text นั้นเอง  
    ดังนั้น เพื่อให้ สามารถจัดส่วนของ Component ทั้งสองให้สวยงาม เป็นสัดส่วน
    เราจึงสามารถใช้ Flex มากำหนดได้ ดังตัวอย่างใน Bubble ตัวที่สอง Text Component ทั้งสองถูกำหนดเป็นเท่ากับ 1
    จะได้ความสูงแต่ละ Component เท่ากับ 50% หรือก็คือแบ่างเป็นสัดส่วนบนล่างสูงเท่าๆ กัน วิธีการคำนวณ
    ใช้รูปแบบเดียวกับกรณีแนวนอน  
 
(ค่า Flex ของ Component * 100) / ค่า Flex รวม 
    Component ที่รองรับการกำหนด Flex ประกอบด้วย Box , Button , Image และ Text Component
    สำหรับ Filler Component จะมีค่า Flex เท่ากับ 1
 
 
 
การจัดตำแหน่งของ Component
    ถ้า Component ต่างๆ อยู่ภายใน Box Component ที่กำหนด Layout เป็น horizontal หรือ vertical เราสามารถกำหนดตำแหน่ง
ของแต่ละ component ด้านในได้ โดยหลักการดังนี้คือ
    ถ้าอยู่ใน Box แนวตั้ง เราสามารถกำหนด ตำแหน่งในแนวนอนได้ โดยใช้ align เป็น start , center หรือ end
 

 
 
    ถ้าอยู่ใน Box แนวนอน เราสามารถกำหนด ตำแหน่งในแนวตั้งได้ โดยใช้ gravity เป็น top , center หรือ bottom
 
 

 

 
การกำหนดช่องว่างระหว่าง Component
    การใช้งาน Spacing property
    การกำหนด Spacing ให้กับ Box Component จะหมายถึงการกำหนดค่าช่องว่างค่าน้อยที่สุดระหว่าง Component ที่อยู่ด้านใน
 
 

 
 
    spacing จะเป็น property ที่กำหนดใน Box Component เท่านั้น 
    ค่าของ spacing ได้แก่ none, xs, sm, md, lg, xl, หรือ xxl. ค่าเริ่มต้น หรือเมื่อได้กำหนด จะเท่ากับ none
 
    การใช้งาน Margin property
    เราสามารถกำหนดค่า Margin เพื่อกำหนดช่องว่างที่ต้องการระหว่าง Component ได้ การใช้งาน Margin จะเป็นมีผลต่อ Component
สูงกว่า การกำหนดด้วย Spacing ของ Parent Box กล่าวคือ สมมติ เรากำหนด ให้ Box Component ตัว Parent มี spacing เท่ากับ xs
ทำให้ Image Component ด้านในทั้งสาม มีช่องว่างห่างเท่าๆ กัน ตามรูป
 
 

 
 
    แต่พอเรากำหนด margin ให้กับ Image Component ตัวที่ 3 ทำให้พื้นที่ช่องว่าง ระหว่างตัวที่ 2 กับ 3 ก็เพิ่มขนาดเข้ามาตามค่าที่เรากำหนด
 
 

 
 
    margin จะเป็น property ที่กำหนดให้กับ Box , Button , Icon , Image , Separator และ Text Component
    ค่าของ margin ได้แก่ none, xs, sm, md, lg, xl, หรือ xxl ค่าเริ่มต้น จะยึดตาม ค่า spacing ของ Box Component ที่เป็น Parent 
    ค่า margin จะไม่มีผลกับตัว Component แรกที่อยู่ใน Box
 
 
สำหรับเนื้อหาตอนนี้ เราได้รู้จักกับ Flex Message เบื้องต้น รวมถึงทำความเข้าใจเกี่ยวกับแนวทางการจัด Layout
ไปบ้างแล้ว นอกจากนั้น ยังได้เห็นตัวอย่างบางส่วนการประยุกต์ ในรูปแบบการใช้งาน XML ที่ทำให้การสร้าง Flex Message 
ง่ายขึ้น เนื้อหาตอนต่อไป จะเป็นรูปแบบการประยุกต์การสร้าง Flex Message ด้วย XML และเนื้อหาเพิ่มเติม รอติดตาม


อย่าลืมกด Like กด Share เป็นกำลังใจ ในการสร้างบทความใหม่ๆ น่ะครับ



อ่านต่อที่บทความ





บริการเว็บ server web hosting
บริการเว็บ server web hosting




เนื้อหาที่เกี่ยวข้อง



Tags:: line bot sdk messaging api flex message bot




เนื้อหาพิเศษ เฉพาะสำหรับสมาชิก

กรุณาล็อกอิน เพื่ออ่านเนื้อหาบทความ

ยังไม่เป็นสมาชิก

สมาชิกล็อกอิน



หริอ ล็อกอิน ด้วย Facebook




URL สำหรับอ้างอิง