การสร้าง และใช้งาน Rich Menu ผ่าน LINE Messaging API ตอนที่ 8

31 March 2019 By Ninenik Narkdee
rich menu line bot line

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



เนื้อหาในตอนต่อไปนี้ เราจะมาดูเกี่ยวกับการใช้งาน Rich Menu
    Rich Menu เป็นเมนูที่เราสามารถจัดรูปแบบเองได้ จะแสดงในหน้าสนทนา ตัวต่อตัว
ระหว่างผู้ใช้กับ bot เพื่อกำหนดตัวเลือกให้ผู้ใช้งานตอบโต้กับ bot  คล้ายๆ กับปุ่ม navigator
เราสามารถปรับแต่งเมนูให้ทำงานรองรับ action ต่างๆ ได้
 
ตัวอย่างหน้าตา Rich Menu
 

 
 

Rich Menu จะประกอบไปด้วยส่วนที่เป็นรูปภาพ และส่วนที่เป็นแถบเมนู

    - ส่วนที่เป็นรูปภาพ เราสามารถกำหนดบริเวณหรือพื้นที่ ที่ผู้ใช้สามารถที่จะกดเลือกตามต้องการได้ 
โดยเมื่อกดเลือกพื้นที่หรือจุดที่กำหนดไว้แล้ว ก็ให้ไปทำงานตาม action ที่ระบุ
    - ส่วนของแถบเมนู เป็นส่วนที่ผู้ใช้สามารถที่ใช้เปิด หรือปิด Rich Menu สามารถแก้ไขข้อความ
ที่แสดงตามต้องการได้ แต่ปกติ จะใช้คำว่า "เมนู" หรือ "Menu"
 

รูปแบบและลำดับความสำคัญการแสดงของ Rich Menu

    - Rich Menu ที่กำหนดโดย Messaging API ที่แสดงต่อผู้ใช้แต่ละคน จะมีระดับความสำคัญเท่ากับ 1 
หมายถึง Rich Menu ที่เชื่อมกับผู้ใช้ใดๆ จะถูกแสดงก่อน Rich Menu เริ่มต้น
    - Rich Menu เริ่มต้น หรือ Rich Menu ที่ผู้ใช้ทุกคนที่เพิ่ม bot เป็นเพื่อนแล้ว ที่กำหนดผ่าน Messaging
API จะมีระดับความสำคัญเท่ากับ 2 หมายถึง เมื่อมีการกำหนด Rich Menu ใดๆ เป็นเมนูเริ่มต้น ผู้ใช้ทุกคน
ที่เป็นเพื่อนกับ bot จะเห็นเมนูนี้
    - Rich Menu เริ่มต้น หรือ Rich Menu ที่ผู้ใช้ทุกคนที่เพิ่ม bot เป็นเพื่อนแล้ว ที่กำหนดผ่น LINE@ Manager
จะมีระดับความสำคัญเท่ากับ 3 หมายถึง เมื่อมีการกำหนด Rich Menu ใดๆ เป็นเมนูเริ่มต้น ผู้ใช้ทุกคน
ที่เป็นเพื่อนกับ bot จะเห็นเมนูนี้
 

เงื่อนไขเมื่อมีการกำหนดค่าหรือปรับแต่ง Rich Menu

    เมื่อมีการปรับแต่ง หรือกำหนดค่าให้กับ Rich Menu แล้ว Rich Menu จะมีผลต่อการเปลี่ยนแปลงที่เกิดขึ้น
ในเวลาที่แตกต่างกันขึ้นกับรูปแบบของ Rich Menu ตามเงื่อนไขดังนี้
    - Rich Menu กำหนดโดย Messaging API ที่เชื่อมกับผู้ใช้ จะมีผลทัน นั่นคือ เมื่อมีการเปลี่ยนแปลง 
Rich Menu ที่เชื่อมกับผู้ใช้อยู่ Rich Menu นั้นๆ ก็จะอัพเดทและแสดงทันที อย่างไรก็ตาม ถ้า Rich Menu นั้น
ถูกลบออก โดยไม่ได้ทำการยกเลิกการเชื่อมกับผู้ใช้    Rich Menu นั้นจะหายไป เมื่อผู้ใช้ออกจากหน้าสนทนา
ไปแล้วเปิดเข้ามาใหม่
    - Rich Menu ที่เป็นเมนูหลัก กำหนดโดย Messaging API จะมีผล เมื่อผู้ใช้ออกจากห้องสนทนาไปแล้วเปิดกลับ
เข้ามาใหม่ ไม่เกิดขึ้นในทันทีทันใด หรือนานเป็นนาที ดังนั้นผู้ใช้ต้องรอสักครู่
    - Rich Menu ที่เป็นเมนูหลัก ที่กำหนดผ่าน LINE@ Manager จะมีผล เมื่อผู้ใช้ออกจากห้องสนทนาไปแล้ว
เปิดกลับเข้ามาใหม่ 
 
 

การกำหนด Rich Menu ผ่าน Messaging API

    เราสามารถกำหนด Rich Menu สำหรับเมนูหลัก และแบบสำหรับเชื่อมโยงเฉพาะกับผู้ใช้ ผ่านการใช้งาน 
Messaging API ได้ โดย Rich Menu ที่กำหนดโดย Messaging API จะรองรับ postback และ datetime picker action  เพิ่มเข้ามา ต่างจากที่กำหนดใน LINE@ Manager ที่รองรับเฉพาะ Message และ URL action
    เราสามารถกำหนดบริเวณ พื้นที่ หรือจุดใดๆใน Rich Menu เพื่อให้ทำงาน action ที่กำหนดเมื่อแตะเลือกได้
 

ลำดับขั้นตอนการสร้าง Rich Menu ผ่าน Messaging API

  •     เตรียมรูปภาพ
  •     สร้าง Rich Menu
  •     อัพโหลดรูปสำหรับ Rich Menu

การกำหนด Rich Menu ใดๆ เป็นเมนูหลัก หรือเมนูที่เชื่อมกับผู้ใช้แต่ละคน

  •     กำหนดเป็น เมนูหลัก
  •     เชื่อมโยงกับผู้ใช้ขณะนั้น
 

    การเตรียมรูปสำหร้บใช้เป็น Rich Menu

    สำหรับรูปที่ใช้ในการสร้าง Rich Menu นั้น จะสามารถกำหนดจุดที่จะทำงาน action ได้สูงสุดไม่เกิน 20 จุด 
โดย รูปที่จะนำมาใช้ ต้องเป็นไปตามรูปแบบดังนี้
    - เป็นไฟล์รูปภาพนามสกุล JPEG หรือ PNG
    - มีขนาดความกว้างความสูง 2500x1686 หรือ 2500x843 pixels (ความสูงครึ่งหนึ่ง)
    - ขนาดของไฟล์สูงสุดไม่เกิน 1 MB
 

    การสร้าง Rich Menu

    ขึ้นตอนในการสร้าง Rich Menu จะเป็นไปดังนี้
    - สร้าง Rich Menu Object โดยมีการกำหนดค่าต่างๆ เช่น ขนาด ชื่อ ข้อความแสดงเมนู พื้นที่บริเวณที่
จะให้สามารถกดเลือกได้ การแสดงเมนูเสมอหรือไม่ เหล่านี้เป็นต้น
    - ส่งข้อมูล Rich Menu ที่ได้สร้างไปยัง url ที่ Line กำหนดไว้ หากทำการสร้างเมนูสำเร็จ จะมีการคืนค่า
เป็น Rich Menu ID กลับมา
 
    เราสามารถสร้าง Rich Menu ได้สูงสุดถึง 1000 ต่อ 1 bot 
 
    สำหรับใครที่ยังไม่เข้าใจการกำหนดบริเวณหรือพื้นที่ในรูปภาพ เพื่อใช้ในการกำหนด action สามารถทบทวน
เนื้อหาเกี่ยวกับ Imagemapได้ที่บทความ
    การใช้งาน Template Message ใน LINE Messaging API ตอนที่ 3 http://niik.in/836
    https://www.ninenik.com/content.php?arti_id=836 via @ninenik
 
    ในการสร้าง Rich Menu ผ่าน Messaging API เราจะใช้งาน Line bot sdk หลักๆ คือ รับคำสั่งข้อความ
จากเรา แล้วเข้าไปทำคำสั่งตามเงื่อนไข และแจ้งสถานะการทำงานกลับมา (* เราจะมีแนวทางการประยุกต์เพิ่มให้)
    เราจะใช้รูปแบบโค้ดต่อจากตอนที่แล้ว http://niik.in/897
    โดยไฟล์ bot.php กับ bot_action.php จะเพิ่มโค้ดการใช้งาน class เข้าไป
 
use LINE\LINEBot\RichMenuBuilder;
use LINE\LINEBot\RichMenuBuilder\RichMenuSizeBuilder;
use LINE\LINEBot\RichMenuBuilder\RichMenuAreaBuilder;
use LINE\LINEBot\RichMenuBuilder\RichMenuAreaBoundsBuilder;
 
    เนื่องจากการใช้งาน Rich Menu มีรูปแบบคำสั่งต่างๆ รวมทั้งการจัดการค่อนข้างมาก จะขอยกตัวอย่างเฉพาะ
ในขั้นตอนการสร้าง อย่างง่ายเพื่อทำความเข้าใจ ส่วนรายละเอียดแบบเต็มให้ดูในโค้ดการประยุกต์ในตอนท้ายๆ
    นี่คือรูปที่เราจะใช้เป็นตัวอย่าง ในการสร้าง Rich Menu
 
 
    รูปนี้จะแบ่งออกเป็นสองส่วน เป็นด้านซ้านและขวา A และ B ตามรูป โดยบริเวณ A เราจะใส่ Message action
เมื่อผู้ใช้กดเลือกให้ส่งข้อความไปใน chat ส่วนบริเวณ B เราจะใช้ URI action เป็นลิ้งค์ เมื่อผู้ใช้กดเลือก ก็จะเปิด
หน้าลิ้งค์นั้นขึ้นมาใน LINE โค้ดในส่วนของการสร้าง จะเป็นดังนี้
 
case (preg_match('/^create-/',$userMessage) ? true : false): // เมื่อพิมพ์คำว่า create- เข้ามา
	$respRichMenu = $bot->createRichMenu(
		new RichMenuBuilder(
			new RichMenuSizeBuilder(1686,2500), // ขนาด rich menu ปกติจะไม่เปลี่ยน แปลง
			true, // เปิดให้แสดง * จะไม่แสดงทันที 
			"Rich Menu 1", // ชื่อ rich menu
			"เมนู", // ข้อความที่จะแสดงที่แถบเมนู
			array( // array ของ action แต่ละบริเวณ
				new RichMenuAreaBuilder( // action ที่ 1
					new RichMenuAreaBoundsBuilder(0,0,1250,1686),// พื้นที่ A (x,y,width,height)
					new MessageTemplateActionBuilder('m','Area A') // เปลี่ยนเฉพาะตัวที่ 2 ตามต้องการ 'Area A'
				),
				new RichMenuAreaBuilder( // action ที่ 2
					new RichMenuAreaBoundsBuilder(1250,0,1250,1686), // พื้นที่ B (x,y,width,height)
					new UriTemplateActionBuilder('u','http://niik.in') // เปลี่ยนเฉพาะตัวที่ 2 ตามต้องการ 'http://niik.in'
				),																					
			)
		)
	);			
	// ให้ bot แจ้งกลับเกี่ยวกับ สถานะการสร้าง
	$textReplyMessage = " การสร้าง Rich Menu ".$respRichMenu->getRawBody();
	$replyData = new TextMessageBuilder($textReplyMessage);         											
	break;
 
    กรณีจะใช้เป็น postback หรือ datetime picker action ก็สามารถใช้เป็น 
 
new PostbackTemplateActionBuilder('p','action=dosomething&data=1')
    หรือ
 
new DatetimePickerTemplateActionBuilder('d','action=reservation&room=1','datetime')
 
    เมื่อเราสร้าง Rich Menu สำเร็จ ก็จะได้ค่า Rich Menu ID กลับมาใช้งาน สมมติได้ค่ากลับมาเป็น
 
การสร้าง Rich Menu {"richMenuId":"richmenu-c5057563053bcf79f62d644fc787830a"}
 
    หลังจากนั้น เราต้องทำการอัพโหลดรูปไปใช้กับ Rich Menu ที่เราได้สร้าง ในการอัพโหลดรูป เราต้อง
อัพไฟล์รูปภาพ Rice Menu เราไปไว้ใน path เดียวกันกับไฟล์ bot.php ผ่านโปรแกรม FTP เสียก่อน 
สมมติไฟล์เราชื่อ rich-menu-01.png เราจะได้คำสั่งในการอัพโหลดรูปไปใช้กับ Rich Menu ดังนี้
 
case (preg_match('/^uploadpic-/',$userMessage) ? true : false): // เมื่อพิมพ์คำว่า uploadpic- เข้ามา	
	$richmenuID = "richmenu-c5057563053bcf79f62d644fc787830a";  // ค่า rich menu id ที่เราได้จากการสร้าง
	$respRichMenu = $bot->uploadRichMenuImage($richmenuID,"rich-menu-01.png","image/png");
	$textReplyMessage = " อัดโหลดรูป Rich Menu ".$respRichMenu->getRawBody();
	$replyData = new TextMessageBuilder($textReplyMessage);         											
	break;	
 
    หลังจากอัพโหลดรูปให้กับ Rich Menu แล้ว ถ้าสำเร็จจะไม่คืนค่าใดๆ กลับมา 
    เมื่อเราสร้าง และอัพโหลดรูปให้กับ Rich Menu เรียบร้อยแล้ว Rich Menu นั้น จะไม่แสดงจนกว่าเราจะ
กำหนดให้เป็นเมนูหลัก ซึ่งเมนูหลักก็คือ เมนูที่ผู้ใช้ทุกคนที่เป็นเพื่อนกับ bot จะเห็นเมนูนี้ในหน้าห้องสนทนา
เราจะใช้คำสั่งต่อไปนี้
 
case (preg_match('/^setdefault-/',$userMessage) ? true : false): // เมื่อพิมพ์คำว่า setdefault- เข้ามา	
	$richmenuID = "richmenu-c5057563053bcf79f62d644fc787830a";  // ค่า rich menu id ที่เราได้จากการสร้าง
	$respRichMenu = $httpClient->post("https://api.line.me/v2/bot/user/all/richmenu/".$richmenuID,array());
	$textReplyMessage = " กำหนด Default Rich Menu ".$respRichMenu->getRawBody();
	$replyData = new TextMessageBuilder($textReplyMessage);         											
	break;	
 
     เมื่อกำหนดเมนูหลักให้กับ Rich Menu แล้ว ถ้าสำเร็จจะไม่คืนค่าใดๆ กลับมา รอสักครู่ ออกจากห้องสนนากับ
bot แล้วเปิดเข้าไปใหม่ เมนูก็จะแสดงในห้องสนทนา แนวทางหลักๆ ก็จะประมาณนี้ เราสามารถทำคำสั่งอื่นๆ
เพื่มเติม เช่น ยกเลิกการแสดงเมนูหลัก ลบ Rich Menu เชื่อม Rich Menu กับผู้ใช้รายบุคคล เป็นต้น เหล่านี้
สามารถดูเพิ่มเติมได้ที่ https://developers.line.biz/en/docs/messaging-api/using-rich-menus/
    หรือดูจากแนวทางการประยุกต์ด้านล่าง

 

สร้างระบบจัดการ Rich Menu ผ่าน Bot

    จากรูปแบบการใช้งาน Rich Menu ผ่าน Messaging API ข้างต้น จะเห็นว่า ถึงแม้ตัว API จะรองรับการปรับแต่ง
มากมาย แต่การใช้งาน ก็จำเป็นต้องมีความเข้าใจ และมีการกำหนดสิ่งต่างๆ มากมายผ่านการเขียนโค้ด ดังนั้น 
จึงขอประยุกต์ ให้สามารถสรัาง Rich Menu ได้ง่ายขึ้น ผ่านการสั่งงานไปยัง bot โดยมีรูปแบบและแนวทางดังนี้
    รูปแบบ pattern เราจะใช้รูปแบบเดียวกับ Line มี 7 layout ดังรูปด้านล่าง
 
 
    จะใช้เลข 1 ถึง 7 แทนรูปแบบที่ต้องการ ให้ดาวน์โหลดไฟล์รูปภาพ pattern ตามลิ้งค์ด้านล่าง
    http://niik.in/download/rich-menu.rar
 
    เมื่อแตกไฟล์จะพบโฟลเดอร์ rich-menu และด้านในมีไฟล์ pattern กับไฟล์ตัวอย่างที่จะใช้สำหรับกำหนด
Rich Menu รูปแบบชื่อไฟล์ จะเป็น 
  •     rich-menu-01.png  สำหรับไฟล์ที่จะใช้เป็น Rich Menu
  •     rich-menu-pattern-01.png สำหรับไฟล์ pattern layout
    
    แต่ละไฟล์จะแยกด้วยตัวเลข 01-07 โดยไฟล์ pattern เราไม่ต้องแก้ไข
ส่วนไฟล์ rich-menu-0(x).png จะเป็นไฟล์ที่เราไว้อัพโหลดเพื่อใช้งาน Rich Menu 
สมมติ เราต้องการ Rich Menu รูปแบบที่ 1 เราก็สร้างไฟล์ให้ได้ pattern เดียวกับไฟล์ 
rich-menu-pattern-01.png แล้วอัพโหลดขึ้นไปทับไฟล์ rich-menu-01.png 
ถ้าเราต้องการ Rich Menu รูปแบบที่ 1 อีกหนึ่งตัว เราก็ใช้เป็นชื่อ rich-menu-01-2.png จะได้รูปแบบ
กรณีใช้รูปแบบเดียวกันหลายๆ รูปเป็นดังนี้
 
    rich-menu-01.png 
    rich-menu-01-2.png 
    rich-menu-01-3.png 
    .....
    .....    
    rich-menu-01-x.png 
 
ดังนั้น ก่อนที่เราจะไปในขั้นตอนการสร้าง Rich Menu เราต้องเตรียมรูปให้พร้อมก่อน แล้วอัพโหลดไปยังโฟลเดอร์
เดียวกับ bot  สมมติไฟล์ webhook หรือไฟล์ bot.php เราอยู่ในโฟลเดอร์ linebot โครงสร้างโฟลเดอร์ก็จะเป็น
 
> linebot
    > rich-menu 
        > ไฟล์รูป Rich menu และไฟล์ pattern
    bot.php
    bot_action.php
 
    คำสั่งและรูปแบบการสร้าง Rich Menu
    ต่อไปมาดูรูปแบบคำสั่งที่เราจะใช้สร้าง Rich Menu ผ่านหน้า Chat กับ Bot
 
    คำสั่งในการสร้าง Rich Menu
cr-x>y>z
 
  •     x คือรูปแบบ
  •     y คือลำดับ ID ค่าควรจะเริ่มจาก 1 ให้สอดคล้องกับรูปที่กำหนดด้านบน
  •     z คือ รูปแบบ action ที่ต้องการ
 
    รูปแบบ action
  •     p(data) สำหรับกำหนด postback action
  •     m(data) สำหรับกำหนด message action
  •     u(data) สำหรับกำหนด uri action หรือ url
  •     d(data) สำหรับกำหนด datetime picker action
  •     c() สำหรับกำหนด เพื่อถ่ายรูป
  •     cs() สำหรับกำหนด ให้เลือกรูป 1 รูปจากคลังภาพ
  •     cm() สำหรับกำหนด ให้เลือกรูปได้หลายรูปจากคลังภาพ
  •     l() สำหรับกำหนด เลือกตำแหน่งในแผนที่ (*ตัว L พิมพ์เล็ก)
  •     () สำหรับกำหนดเป็นค่าว่าง ไม่มี action
 
    การกำหนดจำนวนของ action ต้องกำหนด จำนวนให้เท่ากับ จำนวนพื้นที่ของแต่ละ pattern นั้นๆ
    โดยแต่ละ pattern มีจุด action แตกต่างกันไปดังนี้
  •      pattern 1 มี 6
  •      pattern 2 มี 4
  •      pattern 3 มี 4
  •      pattern 4 มี 3
  •      pattern 5 มี 2
  •      pattern 6 มี 2
  •      pattern 7 มี 1
     สามารถดูแต่ละตำแหน่งจากรูป pattern เรียงตามลำดับตัวอักษรจากซ้ายไปขวา และบนลงล่าง
     ตามตัวอย่างรูป pattern 4 ด้านล่าง
 
 


 
 
    สมมติเราจะสร้าง Rich Menu รูปแบบที่ 4 และไม่มี action ใดๆ เลย จะได้เป็น
 
cr-4>1>()()()
 
    สมมติ รูปแบบที่ 4 ตำแหน่งที่ 2 (B) และ 3 (C) เป็น ข้อความ และ ลิ้งค์ จะได้เป็น
 
cr-4>1>()m(ข้อความ)u(http://niik.in)
 
    จะเห็นว่า ตำแหน่งที่ 1 เราไม่มี action แต่เราต้องกำหนด () เพื่อให้ครบตามจำนวน
  
 
    คำสั่งในการเรียกดู Rich Menu ที่เราสร้าง
    คำสั่งนี้จะใช้เรียกดู Rich Menu ที่เราได้สร้างสำเร็จ หากไม่มีรายการใดๆ ก็จะไม่แสดง โดยเราใช้วิธี
แสดงรายการแบบใช้ CarouselTemplateBuilder และมีเมนูจัดการด้านในของแต่ละ Rich Menu
 
gr-  
ประกอบด้วยเมนู 
  • กำหนด / ยกเลิก เป็น Default
  • แสดงรายการ Default
  • อัพโหลดรูป Rich Menu
 
 gr2-
ประกอบด้วยเมนู 
  • รายละเอียด Rich Menu
  • ลบ Rich Menu 
  • อัพโหลดรูป Rich Menu 
 
    ลำดับการสร้าง Rich Menu และให้แสดงเป็นเป็นเมนูหลัก จะมีขั้นตอนดังนี้
 
    1. สร้าง Rich Menu
cr-4>1>()m(ข้อความ)u(http://niik.in)
 
    2. แสดง Rich Menu ที่สร้าง 
 gr-
 
    3. เมื่อ Rich Menu แสดง กดเลือก "อัพโหลดรูป" Rich Menu ที่ต้องการ
    4. กดเลือก "กำหนดเป็น Default" เท่านี้เมนู ก็จะแสดงในหน้าสนทนา
    หากต้องการลบ Rich Menu ใดๆ ให้แสดงเมนูผ่านคำสั่ง gr2-
 
    ทำความเข้าใจกับการทำงานของคำสั่งการสร้าง Rich Menu
 cr-4>1>()m(ข้อความ)u(http://niik.in)
    ส่วนของการจัดการจะถูกแยกการทำงานออกเป็น 3 ส่วน
    สองส่วนแรก
    cr-4 จะเป็นการใช้รูปแบบ pattern ที่ 4
    เลข 1 เป็นเมนูลำดับที่ 1
    สองค่านี้จะถูกนำไปใช้ในการกำหนดชื่อเมนู เรากำหนดให้ชื่อเมนูอยู่ในรูปแบบ
    "Rich Menu 4-1" ค่าเหล่านี้จะไปสอดคล้องกับชื่อไฟล์รูปที่เราอัพโหลดไว้
    ไฟล์รูปที่จะถูกอัพโหลดไปยังเมนูนี้คือ rich-menu-04.png
    ถ้าเราใช้เป็น cr-4>2
    ไฟล์รูปที่จะถูกอัพโหลดไปยังเมนูนี้คือ rich-menu-04-2.png  
    ดังนั้นเราจะต้องมีโฟล์ rich-menu-04-2.png ในโฟลเดอร์ rich-menu ก่อนด้วย ตามที่ได้กล่าวมาแล้ว
 
    ส่วนที่สาม ()m(ข้อความ)u(http://niik.in) จะเห็นว่ามีวงเล็บทั้งหมด 3 ตัว ทั้งนี้เพราะ
    pattern ที่ 4 มีด้วยกัน 3 จุด action แต่เราเลือกให้ทำงานเฉพราะจุดที่ 2 และ 3 โดยจุดแรกไม่ให้มี
    action ซึ่งเรากำหนดเป็น () ส่วนจุดที่สองกำหนด action เป็น message คำว่า "ข้อความ" คือคำที่
    จะถูกส่งไปยัง bot เมื่อแตะที่บริเวณตำแหน่งที่สอง สำหรับตำแหน่งที่ 3 จะเป็น uri หรือ url ที่เมื่อแตะ
    แล้วก็จะลิ้งค์ไปยังลิ้งค์นั้นๆ ที่กำหนด
 

    การเชื่อม Rich Menu กับผู้ใช้

    เราสามารถใช้ส่วนของการกำหนด action สร้างการเชื่อมโยง Rich Menu ให้กับผู้ใช้ ลักษณะคือ เมื่อเชื่อม
ผู้ใช้ขณะนั้นเข้ากับอีกเมนู เมนูของผู้ใช้จะเปลี่ยนไปเป็นเมนูใหม่ ไม่ใช่เมนูหลัก แต่เราก็สามารถกำหนดให้ผู้ใช้
กลับมาเมนูหลักโดยการกำหนด action ในเมนูของสมาชิกได้ การเชื่อม Rich Menu จะเชื่อมได้ 1 Rich Menu
ต่อหนึ่งผู้ใช้เท่านั้น 
    วิธีการเชื่อม Rich Menu และวิธีการยกเลิก
    เราจะใช้วิธีกำหนดผ่าน postback action แต่ก่อนอื่น เราต้องมี Rich Menu อย่างน้อย 2 อัน
อันหนึ่งเป็นเมนูหลัก และอีกอันเป็นเมนูสำหรับผู้ใช้  ผู้ใช้ทุกคนจะเห็นเมนูหลัก และเมื่อคลิกที่จุดที่เรา
ทำ action ไว้ ก็จะให้เชื่อมไปยังเมนูที่ 2 ดังนั้นเราต้องทราบ Rich Menu ID ของเมนูที่ 2 
เช่นกันในเมนูที่ 2 เมื่อผู้ใช้เชื่อมกับ Rich Menu แล้ว เราต้องมีปุ่มให้ผู้ใช้ยกเลิกการเชื่อม หรือก็คือกลับมา
เมนูหลัก
    ตัวอย่าง เราจะสร้างเมนู 2 อัน โดยต้องสร้างเมนูสำหรับผู้ใช้ก่อน ในที่นี้จะใช้ pattern 1 และจะกำหนด
ปุ่มสุดท้ายมุมล่างขวา เป็นปุ่ม back จะได้คำสั่งเป็น
 
 

 
 
 cr-1>1>()()()()()p(action=back_richmenu)
 
เมือ่สร้างแล้ว เราจะได้ {"richMenuId":"richmenu-f72e9b0233b786f7ba0297e722605e03"}
 
ต่อไปเราจะสร้างเมนูหลักใช้ pattern 4 เป็นจุดที่จะทำการเชื่อมโยงเมนูแรกกับผู้ใช้
 
 

 
 
cr-4>1>()()p(action=more_richmenu&richmenuid=richmenu-f72e9b0233b786f7ba0297e722605e03)
 
จากนั้นใช้คำสั่ง gr- เพื่อแสดง Rich Menu ทั้งสอง เมื่อรายการ Rich Menu แสดงให้ทำการกดเลือก
อัพโหลดรูปให้กับเมนูทั้งสอง เสร็จแล้วให้กดกำหนดเมนู pattern 4 เป็น เมนูหลักหรือ Default
 
รอสักครู่ จากนั้นออกจากห้องสนทนา แล้วเข้าไปใหม่ จะพบเมนูหลักตามรูป 
 
 

 
 
เมื่อเรากดไปที่ตำแหน่ง C จุดที่เรากำหนด postback action เอาไว้ ก็จะเป็นการเชื่อมผู้ใช้ คือเราเข้าไปในเมนู
ที่กำหนด หน้าเมนู ก็จะเปลี่ยนเป็นเมนู pattern 1 
 
 

 
 
เมนูนี้จะคงอยู่จนกว่าผู้ใช้จะกด ปุ่มที่ตำแหน่ง F ซึ่งเรากำหนด
ให้ยกเลิกการเชื่อม เมื่อยกเลิกการเชื่อม Rich Menu ก็จะกลับมาแสดง เมนูหลักอีกครั้ง
 
จะเห็นวิธีการสร้าง Rich Menu ด้วยวิธีที่ทำขึ้น จะทำให้เราสามารถจัดการ Rich Menu ได้อย่างง่ายดาย หรือถ้า
ต้องการปรับแต่งเพิ่มเติม ก็สามารถเข้าไปแก้ไขโค้ดได้ตามต้องการ แต่เท่านี้ก็ถือว่ารองรับได้มากพอสมควร
 
ด้านล่างนี้เป็นโค้ดของตัวจัดการ Rich Menu ผ่าน Bot
 
ไฟล์ bot.php
<?php
// กรณีต้องการตรวจสอบการแจ้ง error ให้เปิด 3 บรรทัดล่างนี้ให้ทำงาน กรณีไม่ ให้ comment ปิดไป
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

// include composer autoload
require_once '../vendor/autoload.php';

// การตั้งเกี่ยวกับ bot
require_once 'bot_settings.php';

// กรณีมีการเชื่อมต่อกับฐานข้อมูล
//require_once("dbconnect.php");

///////////// ส่วนของการเรียกใช้งาน class ผ่าน namespace
use LINE\LINEBot;
use LINE\LINEBot\HTTPClient;
use LINE\LINEBot\HTTPClient\CurlHTTPClient;
use LINE\LINEBot\Event;
use LINE\LINEBot\Event\BaseEvent;
use LINE\LINEBot\Event\MessageEvent;
use LINE\LINEBot\Event\AccountLinkEvent;
use LINE\LINEBot\Event\MemberJoinEvent; 
use LINE\LINEBot\MessageBuilder;
use LINE\LINEBot\MessageBuilder\TextMessageBuilder;
use LINE\LINEBot\MessageBuilder\StickerMessageBuilder;
use LINE\LINEBot\MessageBuilder\ImageMessageBuilder;
use LINE\LINEBot\MessageBuilder\LocationMessageBuilder;
use LINE\LINEBot\MessageBuilder\AudioMessageBuilder;
use LINE\LINEBot\MessageBuilder\VideoMessageBuilder;
use LINE\LINEBot\ImagemapActionBuilder;
use LINE\LINEBot\ImagemapActionBuilder\AreaBuilder;
use LINE\LINEBot\ImagemapActionBuilder\ImagemapMessageActionBuilder ;
use LINE\LINEBot\ImagemapActionBuilder\ImagemapUriActionBuilder;
use LINE\LINEBot\MessageBuilder\Imagemap\BaseSizeBuilder;
use LINE\LINEBot\MessageBuilder\ImagemapMessageBuilder;
use LINE\LINEBot\MessageBuilder\MultiMessageBuilder;
use LINE\LINEBot\TemplateActionBuilder;
use LINE\LINEBot\TemplateActionBuilder\DatetimePickerTemplateActionBuilder;
use LINE\LINEBot\TemplateActionBuilder\MessageTemplateActionBuilder;
use LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder;
use LINE\LINEBot\TemplateActionBuilder\UriTemplateActionBuilder;
use LINE\LINEBot\MessageBuilder\TemplateBuilder;
use LINE\LINEBot\MessageBuilder\TemplateMessageBuilder;
use LINE\LINEBot\MessageBuilder\TemplateBuilder\ButtonTemplateBuilder;
use LINE\LINEBot\MessageBuilder\TemplateBuilder\CarouselTemplateBuilder;
use LINE\LINEBot\MessageBuilder\TemplateBuilder\CarouselColumnTemplateBuilder;
use LINE\LINEBot\MessageBuilder\TemplateBuilder\ConfirmTemplateBuilder;
use LINE\LINEBot\MessageBuilder\TemplateBuilder\ImageCarouselTemplateBuilder;
use LINE\LINEBot\MessageBuilder\TemplateBuilder\ImageCarouselColumnTemplateBuilder;
use LINE\LINEBot\QuickReplyBuilder;
use LINE\LINEBot\QuickReplyBuilder\QuickReplyMessageBuilder;
use LINE\LINEBot\QuickReplyBuilder\ButtonBuilder\QuickReplyButtonBuilder;
use LINE\LINEBot\TemplateActionBuilder\CameraRollTemplateActionBuilder;
use LINE\LINEBot\TemplateActionBuilder\CameraTemplateActionBuilder;
use LINE\LINEBot\TemplateActionBuilder\LocationTemplateActionBuilder;
use LINE\LINEBot\RichMenuBuilder;
use LINE\LINEBot\RichMenuBuilder\RichMenuSizeBuilder;
use LINE\LINEBot\RichMenuBuilder\RichMenuAreaBuilder;
use LINE\LINEBot\RichMenuBuilder\RichMenuAreaBoundsBuilder;


$httpClient = new CurlHTTPClient(LINE_MESSAGE_ACCESS_TOKEN);
$bot = new LINEBot($httpClient, array('channelSecret' => LINE_MESSAGE_CHANNEL_SECRET));
 
// คำสั่งรอรับการส่งค่ามาของ LINE Messaging API
$content = file_get_contents('php://input');
 
// กำหนดค่า signature สำหรับตรวจสอบข้อมูลที่ส่งมาว่าเป็นข้อมูลจาก LINE
$hash = hash_hmac('sha256', $content, LINE_MESSAGE_CHANNEL_SECRET, true);
$signature = base64_encode($hash);
 
// แปลงค่าข้อมูลที่ได้รับจาก LINE เป็น array ของ Event Object
$events = $bot->parseEventRequest($content, $signature);
$eventObj = $events[0]; // Event Object ของ array แรก
 
// ดึงค่าประเภทของ Event มาไว้ในตัวแปร มีทั้งหมด 7 event
$eventType = $eventObj->getType();
 
// สร้างตัวแปร ไว้เก็บ sourceId ของแต่ละประเภท
$userId = NULL;
$groupId = NULL;
$roomId = NULL;
// สร้างตัวแปรเก็บ source id และ source type
$sourceId = NULL;
$sourceType = NULL;
// สร้างตัวแปร replyToken และ replyData สำหรับกรณีใช้ตอบกลับข้อความ
$replyToken = NULL;
$replyData = NULL;
// สร้างตัวแปร ไว้เก็บค่าว่าเป้น Event ประเภทไหน
$eventMessage = NULL;
$eventPostback = NULL;
$eventJoin = NULL;
$eventLeave = NULL;
$eventFollow = NULL;
$eventUnfollow = NULL;
$eventBeacon = NULL;
$eventAccountLink = NULL;
$eventMemberJoined = NULL;
$eventMemberLeft = NULL;
// เงื่อนไขการกำหนดประเภท Event 
switch($eventType){
    case 'message': $eventMessage = true; break;    
    case 'postback': $eventPostback = true; break;  
    case 'join': $eventJoin = true; break;  
    case 'leave': $eventLeave = true; break;    
    case 'follow': $eventFollow = true; break;  
    case 'unfollow': $eventUnfollow = true; break;  
    case 'beacon': $eventBeacon = true; break;     
    case 'accountLink': $eventAccountLink = true; break;       
    case 'memberJoined': $eventMemberJoined = true; break;       
    case 'memberLeft': $eventMemberLeft = true; break;       				                     
}
// สร้างตัวแปรเก็บค่า userId กรณีเป็น Event ที่เกิดขึ้นใน USER
if($eventObj->isUserEvent()){
    $userId = $eventObj->getUserId();  
	$sourceType = "USER";
}
// สร้างตัวแปรเก็บค่า groupId กรณีเป็น Event ที่เกิดขึ้นใน GROUP
if($eventObj->isGroupEvent()){
    $groupId = $eventObj->getGroupId();  
	$userId = $eventObj->getUserId();  
	$sourceType = "GROUP";
}
// สร้างตัวแปรเก็บค่า roomId กรณีเป็น Event ที่เกิดขึ้นใน ROOM
if($eventObj->isRoomEvent()){
    $roomId = $eventObj->getRoomId();        
	$userId = $eventObj->getUserId();      
	$sourceType = "ROOM";
}
// เก็บค่า sourceId ปกติจะเป็นค่าเดียวกันกับ userId หรือ roomId หรือ groupId ขึ้นกับว่าเป็น event แบบใด
$sourceId = $eventObj->getEventSourceId();
// ดึงค่า replyToken มาไว้ใช้งาน ทุกๆ Event ที่ไม่ใช่ Leave และ Unfollow Event และ  MemberLeft
// replyToken ไว้สำหรับส่งข้อความจอบกลับ 
if(is_null($eventLeave) && is_null($eventUnfollow) && is_null($eventMemberLeft)){
    $replyToken = $eventObj->getReplyToken();    
}

////////////////////////////  ส่วนของการทำงาน
include_once("bot_action.php");
//////////////////////////

$response = $bot->replyMessage($replyToken,$replyData);
if ($response->isSucceeded()) {
	echo 'Succeeded!';
	return;
}
// Failed
echo $response->getHTTPStatus() . ' ' . $response->getRawBody();
?>
 
ไฟล์ bot_action.php
<?php
///////////// ส่วนของการเรียกใช้งาน class ผ่าน namespace
use LINE\LINEBot;
use LINE\LINEBot\HTTPClient;
use LINE\LINEBot\HTTPClient\CurlHTTPClient;
use LINE\LINEBot\Event;
use LINE\LINEBot\Event\BaseEvent;
use LINE\LINEBot\Event\MessageEvent;
use LINE\LINEBot\Event\AccountLinkEvent;
use LINE\LINEBot\Event\MemberJoinEvent; 
use LINE\LINEBot\MessageBuilder;
use LINE\LINEBot\MessageBuilder\TextMessageBuilder;
use LINE\LINEBot\MessageBuilder\StickerMessageBuilder;
use LINE\LINEBot\MessageBuilder\ImageMessageBuilder;
use LINE\LINEBot\MessageBuilder\LocationMessageBuilder;
use LINE\LINEBot\MessageBuilder\AudioMessageBuilder;
use LINE\LINEBot\MessageBuilder\VideoMessageBuilder;
use LINE\LINEBot\ImagemapActionBuilder;
use LINE\LINEBot\ImagemapActionBuilder\AreaBuilder;
use LINE\LINEBot\ImagemapActionBuilder\ImagemapMessageActionBuilder ;
use LINE\LINEBot\ImagemapActionBuilder\ImagemapUriActionBuilder;
use LINE\LINEBot\MessageBuilder\Imagemap\BaseSizeBuilder;
use LINE\LINEBot\MessageBuilder\ImagemapMessageBuilder;
use LINE\LINEBot\MessageBuilder\MultiMessageBuilder;
use LINE\LINEBot\TemplateActionBuilder;
use LINE\LINEBot\TemplateActionBuilder\DatetimePickerTemplateActionBuilder;
use LINE\LINEBot\TemplateActionBuilder\MessageTemplateActionBuilder;
use LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder;
use LINE\LINEBot\TemplateActionBuilder\UriTemplateActionBuilder;
use LINE\LINEBot\MessageBuilder\TemplateBuilder;
use LINE\LINEBot\MessageBuilder\TemplateMessageBuilder;
use LINE\LINEBot\MessageBuilder\TemplateBuilder\ButtonTemplateBuilder;
use LINE\LINEBot\MessageBuilder\TemplateBuilder\CarouselTemplateBuilder;
use LINE\LINEBot\MessageBuilder\TemplateBuilder\CarouselColumnTemplateBuilder;
use LINE\LINEBot\MessageBuilder\TemplateBuilder\ConfirmTemplateBuilder;
use LINE\LINEBot\MessageBuilder\TemplateBuilder\ImageCarouselTemplateBuilder;
use LINE\LINEBot\MessageBuilder\TemplateBuilder\ImageCarouselColumnTemplateBuilder;
use LINE\LINEBot\QuickReplyBuilder;
use LINE\LINEBot\QuickReplyBuilder\QuickReplyMessageBuilder;
use LINE\LINEBot\QuickReplyBuilder\ButtonBuilder\QuickReplyButtonBuilder;
use LINE\LINEBot\TemplateActionBuilder\CameraRollTemplateActionBuilder;
use LINE\LINEBot\TemplateActionBuilder\CameraTemplateActionBuilder;
use LINE\LINEBot\TemplateActionBuilder\LocationTemplateActionBuilder;
use LINE\LINEBot\RichMenuBuilder;
use LINE\LINEBot\RichMenuBuilder\RichMenuSizeBuilder;
use LINE\LINEBot\RichMenuBuilder\RichMenuAreaBuilder;
use LINE\LINEBot\RichMenuBuilder\RichMenuAreaBoundsBuilder;


// ส่วนของการทำงาน
if(!is_null($events)){

	// ถ้า bot ถูก invite เพื่อเข้า Join Event ให้ bot ส่งข้อความใน GROUP ว่าเข้าร่วม GROUP แล้ว
	if(!is_null($eventJoin)){
		$textReplyMessage = "ขอเข้าร่วมด้วยน่ะ $sourceType ID:: ".$sourceId;
		$replyData = new TextMessageBuilder($textReplyMessage);                 
	}
	
	// ถ้า bot ออกจาก สนทนา จะไม่สามารถส่งข้อความกลับได้ เนื่องจากไม่มี replyToken
	if(!is_null($eventLeave)){

	}	
	
	// ถ้า bot ถูกเพื่มเป้นเพื่อน หรือถูกติดตาม หรือ ยกเลิกการ บล็อก
	if(!is_null($eventFollow)){
        $textReplyMessage = "ขอบคุณที่เป็นเพื่อน และติดตามเรา";        
        $replyData = new TextMessageBuilder($textReplyMessage);     			
	}
	
	// ถ้า bot ถูกบล็อก หรือเลิกติดตาม จะไม่สามารถส่งข้อความกลับได้ เนื่องจากไม่มี replyToken
	if(!is_null($eventUnfollow)){

	}		
	
	// ถ้ามีสมาชิกคนอื่น เข้ามาร่วมใน room หรือ group 
	// room คือ สมมติเราคุยกับ คนหนึ่งอยู่ แล้วเชิญคนอื่นๆ เข้ามาสนทนาด้วย จะกลายเป็นห้องใหม่
	// group คือ กลุ่มที่เราสร้างไว้ มีชื่อกลุ่ม แล้วเราเชิญคนอื่นเข้ามาในกลุ่ม เพิ่มร่วมสนทนาด้วย
	if(!is_null($eventMemberJoined)){
			$arr_joinedMember = $eventObj->getEventBody();
			$joinedMember = $arr_joinedMember['joined']['members'][0];
			if(!is_null($groupId) || !is_null($roomId)){
				if($eventObj->isGroupEvent()){
					foreach($joinedMember as $k_user=>$v_user){
						if($k_user=="userId"){
							$joined_userId = $v_user;
						}
					}						
					$response = $bot->getGroupMemberProfile($groupId, $joined_userId);
				}
				if($eventObj->isRoomEvent()){
					foreach($joinedMember as $k_user=>$v_user){
						if($k_user=="userId"){
							$joined_userId = $v_user;
						}
					}					
					$response = $bot->getRoomMemberProfile($roomId, $joined_userId);    
				}
			}else{
				$response = $bot->getProfile($userId);
			}
			if ($response->isSucceeded()) {
				$userData = $response->getJSONDecodedBody(); // return array     
				// $userData['userId']
				// $userData['displayName']
				// $userData['pictureUrl']
				// $userData['statusMessage']
				$textReplyMessage = 'สวัสดีครับ คุณ '.$userData['displayName'];     
			}else{
				$textReplyMessage = 'สวัสดีครับ ยินดีต้อนรับ';
			}
//        $textReplyMessage = "ยินดีต้อนรับกลับมาอีกครั้ง ".json_encode($joinedMember);
        $replyData = new TextMessageBuilder($textReplyMessage);     				
	}
	
	// ถ้ามีสมาชิกคนอื่น ออกจากก room หรือ group จะไม่สามารถส่งข้อความกลับได้ เนื่องจากไม่มี replyToken
	if(!is_null($eventMemberLeft)){
	
	}	

	// ถ้ามีกาาเชื่อมกับบัญชี LINE กับระบบสมาชิกของเว็บไซต์เรา
	if(!is_null($eventAccountLink)){
		// หลักๆ ส่วนนี้ใช้สำรหบัเพิ่มความภัยในการเชื่อมบัญตี LINE กับระบบสมาชิกของเว็บไซต์เรา 
        $textReplyMessage = "AccountLink ทำงาน ".$replyToken." Nonce: ".$eventObj->getNonce();
        $replyData = new TextMessageBuilder($textReplyMessage);   	  					
	}
			
    // ถ้าเป็น Postback Event
    if(!is_null($eventPostback)){
        $dataPostback = NULL;
        $paramPostback = NULL;
        // แปลงข้อมูลจาก Postback Data เป็น array
        parse_str($eventObj->getPostbackData(),$dataPostback);
        // ดึงค่า params กรณีมีค่า params
        $paramPostback = $eventObj->getPostbackParams();
		
		$moreResult = "";
		// ส่วนทำงานสำหรับเชื่อม Rich Menu ไปยังผู้ใช้นั้นๆ
		if(isset($dataPostback['action']) && $dataPostback['action']=="more_richmenu"){
			$respRichMenu = $bot->linkRichMenu($userId,$dataPostback['richmenuid']);
			$moreResult = $respRichMenu->getRawBody();
			$result = json_decode($respRichMenu->getRawBody(),TRUE);	
		}		
		// ส่วนทำงานสำหรับยกเลิกการเชื่อมกับ Rich Menu ของ ผู้ใช้
		if(isset($dataPostback['action']) && $dataPostback['action']=="back_richmenu"){
			$respRichMenu = $bot->unlinkRichMenu($userId);
			$moreResult = $respRichMenu->getRawBody();
			$result = json_decode($respRichMenu->getRawBody(),TRUE);	
		}				
		// ส่วนทำงานสำหรับลบ Rich Menu
		if(isset($dataPostback['action']) && $dataPostback['action']=="delete_richmenu"){
			$respRichMenu = $bot->deleteRichMenu($dataPostback['richMenuId']);
			$moreResult = $respRichMenu->getRawBody();
			$result = json_decode($respRichMenu->getRawBody(),TRUE);	
		}
		// ส่วนทำงานสำหรับดูข้อมูลของ Rich Menu นั้นๆ
		if(isset($dataPostback['action']) && $dataPostback['action']=="get_richmenu"){
			$respRichMenu = $bot->getRichMenu($dataPostback['richMenuId']);
			$moreResult = $respRichMenu->getRawBody();
			$result = json_decode($respRichMenu->getRawBody(),TRUE);	
		}
		// ส่วนทำงานสำหรับกำหนดเป็น เมนูหลัก
		if(isset($dataPostback['action']) && $dataPostback['action']=="s_default_richmenu"){
			$respRichMenu = $httpClient->post("https://api.line.me/v2/bot/user/all/richmenu/".$dataPostback['richMenuId'],array());
			$moreResult = $respRichMenu->getRawBody();
			$result = json_decode($respRichMenu->getRawBody(),TRUE);	
		}	
		// ส่วนทำงานสำหรับยกเลิกเมนูหลัก	
		if(isset($dataPostback['action']) && $dataPostback['action']=="c_default_richmenu"){
			$respRichMenu = $httpClient->delete("https://api.line.me/v2/bot/user/all/richmenu");
			$moreResult = $respRichMenu->getRawBody();
			$result = json_decode($respRichMenu->getRawBody(),TRUE);	
		}			
		// ส่วนทำงานดึงข้อมูลเมนูหลัก หรือ Rich Menu ที่เป็นเมนูหลัก ถ้ามี
		if(isset($dataPostback['action']) && $dataPostback['action']=="g_default_richmenu"){
			$respRichMenu = $httpClient->get("https://api.line.me/v2/bot/user/all/richmenu");
			$moreResult = $respRichMenu->getRawBody();
			$result = json_decode($respRichMenu->getRawBody(),TRUE);	
		}		
		// ส่วนทำงานอัพโหลดรูปให้กับ Rich Menu	
		if(isset($dataPostback['action']) && $dataPostback['action']=="upload_richmenu"){
			$richMenuImg = str_replace('Rich Menu ','',$dataPostback['richMenuName']);
			if(!file_exists("rich-menu/rich-menu-0".$richMenuImg.".png")){
				$richMenuImg = substr(str_replace('Rich Menu ','',$dataPostback['richMenuName']),0,1);
			}
			$respRichMenu = $bot->uploadRichMenuImage($dataPostback['richMenuId'],"rich-menu/rich-menu-0".$richMenuImg.".png","image/png");
			$moreResult = $respRichMenu->getRawBody();
			$result = json_decode($respRichMenu->getRawBody(),TRUE);	
		}					
		
        // ทดสอบแสดงข้อความที่เกิดจาก Postaback Event
        $textReplyMessage = "ข้อความจาก Postback Event Data : DataPostback = ";        
        $textReplyMessage.= json_encode($dataPostback);
        $textReplyMessage.= " ParamPostback = ".json_encode($paramPostback);
		$textReplyMessage.= " RsponseMore = ".$moreResult;
        $replyData = new TextMessageBuilder($textReplyMessage);     
    }
    // ถ้าเป้น Message Event 
    if(!is_null($eventMessage)){
		
		// สร้างตัวแปรเก็ยค่าประเภทของ Message จากทั้งหมด 7 ประเภท
		$typeMessage = $eventObj->getMessageType();  
		//  text | image | sticker | location | audio | video | file  
		// เก็บค่า id ของข้อความ
		$idMessage = $eventObj->getMessageId();  		
		// ถ้าเป็นข้อความ
		if($typeMessage=='text'){
			$userMessage = $eventObj->getText(); // เก็บค่าข้อความที่ผู้ใช้พิมพ์
		}
		// ถ้าเป็น image
		if($typeMessage=='image'){

		}				
		// ถ้าเป็น audio

		if($typeMessage=='audio'){

		}		
		// ถ้าเป็น video
		if($typeMessage=='video'){

		}	
		// ถ้าเป็น file
		if($typeMessage=='file'){
			$FileName = $eventObj->getFileName();
			$FileSize = $eventObj->getFileSize();
		}				
		// ถ้าเป็น image หรือ audio หรือ video หรือ file และต้องการบันทึกไฟล์
		if(preg_match('/image|audio|video|file/',$typeMessage)){			
			$responseMedia = $bot->getMessageContent($idMessage);
			if ($responseMedia->isSucceeded()) {
				// คำสั่ง getRawBody() ในกรณีนี้ จะได้ข้อมูลส่งกลับมาเป็น binary 
				// เราสามารถเอาข้อมูลไปบันทึกเป็นไฟล์ได้
				$dataBinary = $responseMedia->getRawBody(); // return binary
				// ดึงข้อมูลประเภทของไฟล์ จาก header
				$fileType = $responseMedia->getHeader('Content-Type');    
				switch ($fileType){
					case (preg_match('/^application/',$fileType) ? true : false):
//						$fileNameSave = $FileName; // ถ้าต้องการบันทึกเป็นชื่อไฟล์เดิม
						$arr_ext = explode(".",$FileName);
						$ext = array_pop($arr_ext);
						$fileNameSave = time().".".$ext;       						
						break;					
					case (preg_match('/^image/',$fileType) ? true : false):
						list($typeFile,$ext) = explode("/",$fileType);
						$ext = ($ext=='jpeg' || $ext=='jpg')?"jpg":$ext;
						$fileNameSave = time().".".$ext;
						break;
					case (preg_match('/^audio/',$fileType) ? true : false):
						list($typeFile,$ext) = explode("/",$fileType);
						$fileNameSave = time().".".$ext;                        
						break;
					case (preg_match('/^video/',$fileType) ? true : false):
						list($typeFile,$ext) = explode("/",$fileType);
						$fileNameSave = time().".".$ext;                                
						break;                                                      
				}
				$botDataFolder = 'botdata/'; // โฟลเดอร์หลักที่จะบันทึกไฟล์
				$botDataUserFolder = $botDataFolder.$userId; // มีโฟลเดอร์ด้านในเป็น userId อีกขั้น
				if(!file_exists($botDataUserFolder)) { // ตรวจสอบถ้ายังไม่มีให้สร้างโฟลเดอร์ userId
					mkdir($botDataUserFolder, 0777, true);
				}   
				// กำหนด path ของไฟล์ที่จะบันทึก
				$fileFullSavePath = $botDataUserFolder.'/'.$fileNameSave;
//				file_put_contents($fileFullSavePath,$dataBinary); // เอา comment ออก ถ้าต้องการทำการบันทึกไฟล์
				$textReplyMessage = "บันทึกไฟล์เรียบร้อยแล้ว $fileNameSave";
				$replyData = new TextMessageBuilder($textReplyMessage);
//				$failMessage = json_encode($fileType);				
//				$failMessage = json_encode($responseMedia->getHeaders());
				$replyData = new TextMessageBuilder($failMessage);  					
			}else{
				$failMessage = json_encode($idMessage.' '.$responseMedia->getHTTPStatus() . ' ' . $responseMedia->getRawBody());
				$replyData = new TextMessageBuilder($failMessage);  		
			}
		}
		// ถ้าเป็น sticker
		if($typeMessage=='sticker'){
			$packageId = $eventObj->getPackageId();
			$stickerId = $eventObj->getStickerId();
		}
		// ถ้าเป็น location
		if($typeMessage=='location'){
			$locationTitle = $eventObj->getTitle();
			$locationAddress = $eventObj->getAddress();
			$locationLatitude = $eventObj->getLatitude();
			$locationLongitude = $eventObj->getLongitude();
		}       
		
		
        switch ($typeMessage){ // กำหนดเงื่อนไขการทำงานจาก ประเภทของ message
            case 'text':  // ถ้าเป็นข้อความ
                $userMessage = strtolower($userMessage); // แปลงเป็นตัวเล็ก สำหรับทดสอบ
                switch ($userMessage) {
						case (preg_match('/^cr-/',$userMessage) ? true : false):
							$paramRichMenu = explode(">",$userMessage);
							if(!isset($paramRichMenu) || !is_array($paramRichMenu) || count($paramRichMenu)<3){
								exit;
							}
							$patternSet = $paramRichMenu[0];
							$numberID = $paramRichMenu[1];
							$actionSet = $paramRichMenu[2];
							$actionArr_prepare = array();
							if(isset($actionSet)){
								$actionArr_prepare = explode(")",$actionSet);
								array_pop($actionArr_prepare);
							}
							$imgTypePattern = str_replace("cr-","",$patternSet);
							$areaBound_arr = array(
								"a"=>array(0,0,833,843),
								"b"=>array(833,0,833,843),
								"c"=>array(1666,0,834,843),
								"d"=>array(0,843,833,843),
								"e"=>array(833,843,833,843),
								"f"=>array(1666,843,834,843),
								"g"=>array(0,0,1250,843),
								"h"=>array(1250,0,1250,843),
								"i"=>array(0,843,1250,843),
								"j"=>array(1250,843,1250,843),
								"k"=>array(0,0,2500,843),
								"l"=>array(0,0,1666,1686),
								"m"=>array(0,843,2500,843),
								"n"=>array(0,0,1250,1686),
								"o"=>array(1250,0,1250,1686),
								"p"=>array(0,0,2500,1686)
							);
							$imgTypePatternArea_arr = array(
								"1"=>array("a","b","c","d","e","f"),
								"2"=>array("g","h","i","j"),
								"3"=>array("k","d","e","f"),
								"4"=>array("l","c","f"),
								"5"=>array("k","m"),
								"6"=>array("n","o"),
								"7"=>array("p")
							);
							
							function makeFRM($imgType){
								global $areaBound_arr,$imgTypePatternArea_arr,$actionSet,$actionArr_prepare;
								$dataArr = array();
								$Area_arr = $imgTypePatternArea_arr[$imgType];
								for($i=1;$i<=count($imgTypePatternArea_arr[$imgType]);$i++){									
									if(preg_match('/^p\(/',$actionArr_prepare[$i-1])){
										list($ac,$data) = explode("(",$actionArr_prepare[$i-1]);
										$actionVal = new PostbackTemplateActionBuilder('p',$data);
									}elseif(preg_match('/^m\(/',$actionArr_prepare[$i-1])){
										list($ac,$data) = explode("(",$actionArr_prepare[$i-1]);
										$actionVal = new MessageTemplateActionBuilder('m',$data);									
									}elseif(preg_match('/^u\(/',$actionArr_prepare[$i-1])){
										list($ac,$data) = explode("(",$actionArr_prepare[$i-1]);
										$actionVal = new UriTemplateActionBuilder('u',$data);	
									}elseif(preg_match('/^c\(/',$actionArr_prepare[$i-1])){
										list($ac,$data) = explode("(",$actionArr_prepare[$i-1]);
										$actionVal = new UriTemplateActionBuilder('u',"line://nv/camera/");		
									}elseif(preg_match('/^cs\(/',$actionArr_prepare[$i-1])){
										list($ac,$data) = explode("(",$actionArr_prepare[$i-1]);
										$actionVal = new UriTemplateActionBuilder('u',"line://nv/cameraRoll/single/");	
									}elseif(preg_match('/^cm\(/',$actionArr_prepare[$i-1])){
										list($ac,$data) = explode("(",$actionArr_prepare[$i-1]);
										$actionVal = new UriTemplateActionBuilder('u',"line://nv/cameraRoll/multi/");														
									}elseif(preg_match('/^l\(/',$actionArr_prepare[$i-1])){
										list($ac,$data) = explode("(",$actionArr_prepare[$i-1]);
										$actionVal = new UriTemplateActionBuilder('u',"line://nv/location");	                                        
									}elseif(preg_match('/^d\(/',$actionArr_prepare[$i-1])){
										list($ac,$data) = explode("(",$actionArr_prepare[$i-1]);
										$actionVal = new DatetimePickerTemplateActionBuilder('d',$data,'datetime');
									}elseif(preg_match('/^n\(/',$actionArr_prepare[$i-1])){
										$actionVal = NULL;
										continue;
									}else{
										$actionVal = NULL;
										continue;
									}
									$patternLetter = $Area_arr[$i-1];
									array_push($dataArr,
											new RichMenuAreaBuilder(
												new RichMenuAreaBoundsBuilder(...$areaBound_arr[$patternLetter]),$actionVal
											)					
									);
								}
								return $dataArr;						
							}
//							$arrayRichMenu = makeFRM();
							// $sizeBuilder, $selected, $name, $chatBarText, $areaBuilders // 1686, 843.  // 2500
							// ($x, $y, $width, $height)
							$_idRichMenu = $imgTypePattern."-".$numberID;
							$respRichMenu = $bot->createRichMenu(
								new RichMenuBuilder(
									new RichMenuSizeBuilder(1686,2500),true,"Rich Menu $_idRichMenu",
									"เมนู",
									makeFRM($imgTypePattern)
								)
							);
							// ทำอื่นๆ 
							$textReplyMessage = " การสร้าง Rich Menu ".$respRichMenu->getRawBody()." Res = ".json_encode($dataArr);
							$replyData = new TextMessageBuilder($textReplyMessage);         							
							break;								
						case "gr-": // ส่วนจัดการ Rich Menu ส่วนที่ 1
							/// หา Rich Menu ที่เป็นเมนูหลัก หรือ Default ถ้ามี
							$respRichMenu = $httpClient->get("https://api.line.me/v2/bot/user/all/richmenu");
							$result = json_decode($respRichMenu->getRawBody(),TRUE);		
							$defaultRichMenu = (isset($result['richMenuId']))?$result['richMenuId']:NULL;
	
							// รายการ Rich Menu ทั้งหมด
							$respRichMenu = $bot->getRichMenuList();
							$result = json_decode($respRichMenu->getRawBody(),TRUE);									
							// สร้างตัวแปร สำหรับเก็บ rich menu แต่ละรายการไว้ในแต่ละคอลัมน์
							$columnTemplate = array();
							foreach($result['richmenus'] as $itemRichMenu){
								$_txtShow = ($itemRichMenu['richMenuId']==$defaultRichMenu)?"ยกเลิก":"กำหนดเป็น";
								$_action = ($itemRichMenu['richMenuId']==$defaultRichMenu)?"c_default_richmenu":"s_default_richmenu";
								$imgRichLayout = substr(str_replace('Rich Menu ','',$itemRichMenu['name']),0,1);
								array_push($columnTemplate,	
									new CarouselColumnTemplateBuilder(
											$itemRichMenu['name'], // ชื่อ rich menu
											'เลือกการจัดการ',
											'[เปลี่ยนส่วนนี้เป็น path url ของเรา]rich-menu/rich-menu-pattern-0'.$imgRichLayout.'.png', // ไม่แสดงรูป มีมี url รูป
											// ตัวอย่าง 'https://www.mywebsite.com/linebot/rich-menu/rich-menu-pattern-0'.$imgRichLayout.'.png', 
											array(									
												new PostbackTemplateActionBuilder(
													$_txtShow.' Default', // ข้อความแสดงในปุ่ม
													http_build_query(array(
														'action'=>$_action,			
														'richMenuName'=>$itemRichMenu['name'],					 
														'richMenuId'=>$itemRichMenu['richMenuId']
													)), // ข้อมูลที่จะส่งไปใน webhook ผ่าน postback event
													'กำหนด Default Rich Menu'  // ข้อความที่จะแสดงฝั่งผู้ใช้ เมื่อคลิกเลือก
												),      	
												new PostbackTemplateActionBuilder(
													'แสดงที่ Default', // ข้อความแสดงในปุ่ม
													http_build_query(array(
														'action'=>'g_default_richmenu',		
														'richMenuName'=>$itemRichMenu['name'],			 
														'richMenuId'=>$itemRichMenu['richMenuId']
													)), // ข้อมูลที่จะส่งไปใน webhook ผ่าน postback event
													'แสดง Default Rich Menu'  // ข้อความที่จะแสดงฝั่งผู้ใช้ เมื่อคลิกเลือก
												),     																						
												new PostbackTemplateActionBuilder(
													'อัพโหลดรูป Rich Menu นี้', // ข้อความแสดงในปุ่ม
													http_build_query(array(
														'action'=>'upload_richmenu',			
														'richMenuName'=>$itemRichMenu['name'],					 
														'richMenuId'=>$itemRichMenu['richMenuId']
													)), // ข้อมูลที่จะส่งไปใน webhook ผ่าน postback event
													'อัพโหลดรูป Rich Menu'  // ข้อความที่จะแสดงฝั่งผู้ใช้ เมื่อคลิกเลือก
												) 						
											)		
									)	// end CarouselColumnTemplateBuilder			
								); // end array push function
							}	// end foreach						
							
							// ใช้ Carousel Template วนลูปแสดงรายการ rich menu ที่ได้สร้างไว้
							$replyData = new TemplateMessageBuilder('Carousel',
								new CarouselTemplateBuilder(
									$columnTemplate
								)
							);											
							break;  	
						case "gr2-": // ส่วนจัดการ Rich Menu ส่วนที่ 2
							$respRichMenu = $bot->getRichMenuList();
							$result = json_decode($respRichMenu->getRawBody(),TRUE);	
								
							// สร้างตัวแปร สำหรับเก็บ rich menu แต่ละรายการไว้ในแต่ละคอลัมน์
							$columnTemplate = array();
							foreach($result['richmenus'] as $itemRichMenu){
								$imgRichLayout = substr(str_replace('Rich Menu ','',$itemRichMenu['name']),0,1);								
								array_push($columnTemplate,	
									new CarouselColumnTemplateBuilder(
											$itemRichMenu['name'], // ชื่อ rich menu
											'เลือกการจัดการ',
											'[เปลี่ยนส่วนนี้เป็น path url ของเรา]rich-menu/rich-menu-pattern-0'.$imgRichLayout.'.png', // ไม่แสดงรูป มีมี url รูป
											// ตัวอย่าง 'https://www.mywebsite.com/linebot/rich-menu/rich-menu-pattern-0'.$imgRichLayout.'.png', 
											array(
												new PostbackTemplateActionBuilder(
													'รายละเอียด Rich Menu', // ข้อความแสดงในปุ่ม
													http_build_query(array(
														'action'=>'get_richmenu',		
														'richMenuName'=>$itemRichMenu['name'],						 
														'richMenuId'=>$itemRichMenu['richMenuId']
													)), // ข้อมูลที่จะส่งไปใน webhook ผ่าน postback event
													'ข้อมูล Rich Menu'  // ข้อความที่จะแสดงฝั่งผู้ใช้ เมื่อคลิกเลือก
												),      																														
												new PostbackTemplateActionBuilder(
													'ลบ Rich Menu นี้', // ข้อความแสดงในปุ่ม
													http_build_query(array(
														'action'=>'delete_richmenu',			
														'richMenuName'=>$itemRichMenu['name'],					 
														'richMenuId'=>$itemRichMenu['richMenuId']
													)), // ข้อมูลที่จะส่งไปใน webhook ผ่าน postback event
													'ลบ Rich Menu'  // ข้อความที่จะแสดงฝั่งผู้ใช้ เมื่อคลิกเลือก
												),      		
												new PostbackTemplateActionBuilder(
													'อัพโหลดรูป Rich Menu นี้', // ข้อความแสดงในปุ่ม
													http_build_query(array(
														'action'=>'upload_richmenu',			
														'richMenuName'=>$itemRichMenu['name'],					 
														'richMenuId'=>$itemRichMenu['richMenuId']
													)), // ข้อมูลที่จะส่งไปใน webhook ผ่าน postback event
													'อัพโหลดรูป Rich Menu'  // ข้อความที่จะแสดงฝั่งผู้ใช้ เมื่อคลิกเลือก
												) 						
											)		
									)	// end CarouselColumnTemplateBuilder			
								); // end array push function
							}	// end foreach						
							
							// ใช้ Carousel Template วนลูปแสดงรายการ rich menu ที่ได้สร้างไว้
							$replyData = new TemplateMessageBuilder('Carousel',
								new CarouselTemplateBuilder(
									$columnTemplate
								)
							);											
							break;  															
						case "ot":
							// ทำอื่นๆ 
							break;
						case "l": // เงื่อนไขทดสอบถ้ามีใครพิมพ์ L ใน GROUP / ROOM แล้วให้ bot ออกจาก GROUP / ROOM
								$sourceId = $eventObj->getEventSourceId();
								if($eventObj->isGroupEvent()){
									$bot->leaveGroup($sourceId);
								}
								if($eventObj->isRoomEvent()){
									$bot->leaveRoom($sourceId);  
								}                                                                                         
							break;							
						case "qr":
							$postback = new PostbackTemplateActionBuilder(
                                'Postback', // ข้อความแสดงในปุ่ม
                                http_build_query(array(
                                    'action'=>'buy',
                                    'item'=>100
                                )), // ข้อมูลที่จะส่งไปใน webhook ผ่าน postback event
		                         'Buy'  // ข้อความที่จะแสดงฝั่งผู้ใช้ เมื่อคลิกเลือก
                            );
							$txtMsg = new MessageTemplateActionBuilder(
                                'ข้อความภาษาไทย',// ข้อความแสดงในปุ่ม
                                'thai' // ข้อความที่จะแสดงฝั่งผู้ใช้ เมื่อคลิกเลือก
                            );
							$datetimePicker = new DatetimePickerTemplateActionBuilder(
								'Datetime Picker', // ข้อความแสดงในปุ่ม
								http_build_query(array(
									'action'=>'reservation',
									'person'=>5
								)), // ข้อมูลที่จะส่งไปใน webhook ผ่าน postback event
								'datetime', // date | time | datetime รูปแบบข้อมูลที่จะส่ง ในที่นี้ใช้ datatime
								substr_replace(date("Y-m-d H:i"),'T',10,1), // วันที่ เวลา ค่าเริ่มต้นที่ถูกเลือก
								substr_replace(date("Y-m-d H:i",strtotime("+5 day")),'T',10,1), //วันที่ เวลา มากสุดที่เลือกได้
								substr_replace(date("Y-m-d H:i"),'T',10,1) //วันที่ เวลา น้อยสุดที่เลือกได้
							);
							
							$quickReply = new QuickReplyMessageBuilder(
								array(
									new QuickReplyButtonBuilder(new LocationTemplateActionBuilder('เลือกตำแหน่ง')),
									new QuickReplyButtonBuilder(new CameraTemplateActionBuilder('ถ่ายรูป')),
									new QuickReplyButtonBuilder(new CameraRollTemplateActionBuilder('เลือกรูปภาพ')),
									new QuickReplyButtonBuilder($postback),
									new QuickReplyButtonBuilder($datetimePicker),
									new QuickReplyButtonBuilder(
										$txtMsg,
										"https://www.ninenik.com/images/ninenik_page_logo.png"
									),
								)
							);
							$textReplyMessage = "ส่งพร้อม quick reply ";
							$replyData = new TextMessageBuilder($textReplyMessage,$quickReply);     						
							break;   												                       
                    default:
                        $textReplyMessage = " คุณไม่ได้พิมพ์ ค่า ตามที่กำหนด";
                        $replyData = new TextMessageBuilder($textReplyMessage);         
                        break;                                      
                }
                break;                                                  
            default:
				if(!is_null($replyData)){
					
				}else{
					// กรณีทดสอบเงื่อนไขอื่นๆ ผู้ใช้ไม่ได้ส่งเป็นข้อความ
					$textReplyMessage = 'สวัสดีครับ คุณ '.$typeMessage;         
					$replyData = new TextMessageBuilder($textReplyMessage);         
				}
                break;  
        }
    }
}
?>
 
 
หวังว่าจะเป็นแนวทาง หรือนำไปใช้ประโยชน์ต่อไปได้ไม่นากก็น้อย
 
ดูตัวอย่างได้จาก Demo Video ด้านล่าง







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



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









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



Tags:: line rich menu line bot




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

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

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

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



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




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











เว็บไซต์ของเราให้บริการเนื้อหาบทความสำหรับนักพัฒนา โดยพึ่งพารายได้เล็กน้อยจากการแสดงโฆษณา โปรดสนับสนุนเว็บไซต์ของเราด้วยการปิดการใช้งานตัวปิดกั้นโฆษณา (Disable Ads Blocker) ขอบคุณครับ