ต่อจากตอนที่แล้ว เราได้รู้จักกับ Flex Message ว่ามีองค์ประกอบ
อะไรบ้าง รวมถึงการสร้างข้อความ Flex Message ด้วย Line bot sdk
แยกตามแต่ละ Component ได้รู้จักกับแนวทางการสร้าง Flex Message
Layout สามารถทบทวนเนื้อหาได้ที่บทความ
เริ่มต้นการใช้งาน Flex Message ผ่าน LINE Messaging API ตอนที่ 9 http://niik.in/899
https://www.ninenik.com/content.php?arti_id=899 via @ninenik
ในตอนต่อไปนี้ เราจะมาเข้าสู่รายละเอียดทั้งหมดของการใช้งาน Flex Message
ผ่าน Line bot sdk และมาทำความรู้จักกับแนวทางการประยุกต์การสร้าง Flex Message
ด้วยรูปแบบ XML
Class ที่จำเป็นในการใช้งาน Flex Message
ให้เราเพิ่ม class เหล่านี้เข้าไปในไฟล์ bot.php และ bot_action.php
use LINE\LINEBot\Constant\Flex\ComponentIconSize; use LINE\LINEBot\Constant\Flex\ComponentImageSize; use LINE\LINEBot\Constant\Flex\ComponentImageAspectRatio; use LINE\LINEBot\Constant\Flex\ComponentImageAspectMode; use LINE\LINEBot\Constant\Flex\ComponentFontSize; use LINE\LINEBot\Constant\Flex\ComponentFontWeight; use LINE\LINEBot\Constant\Flex\ComponentMargin; use LINE\LINEBot\Constant\Flex\ComponentSpacing; use LINE\LINEBot\Constant\Flex\ComponentButtonStyle; use LINE\LINEBot\Constant\Flex\ComponentButtonHeight; use LINE\LINEBot\Constant\Flex\ComponentSpaceSize; use LINE\LINEBot\Constant\Flex\ComponentGravity; use LINE\LINEBot\MessageBuilder\FlexMessageBuilder; use LINE\LINEBot\MessageBuilder\Flex\BubbleStylesBuilder; use LINE\LINEBot\MessageBuilder\Flex\BlockStyleBuilder; use LINE\LINEBot\MessageBuilder\Flex\ContainerBuilder\BubbleContainerBuilder; use LINE\LINEBot\MessageBuilder\Flex\ContainerBuilder\CarouselContainerBuilder; use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\BoxComponentBuilder; use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\ButtonComponentBuilder; use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\IconComponentBuilder; use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\ImageComponentBuilder; use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\SpacerComponentBuilder; use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\FillerComponentBuilder; use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\SeparatorComponentBuilder; use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\TextComponentBuilder;
ต่อไปให้เราสร้างไฟล์ชื่อ flex_gen.php ไฟล์นี้เป็นไฟล์ที่รวมฟังก์ชั่น ที่ผู้เขียนสร้างขึ้นมาประยุกต์
สำหรับแปลง Flex Message ในรูปแบบ XML โดยจะใช้คำสั่ง createFlex()
ไฟล์ flex_gen.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; use LINE\LINEBot\Constant\Flex\ComponentIconSize; use LINE\LINEBot\Constant\Flex\ComponentImageSize; use LINE\LINEBot\Constant\Flex\ComponentImageAspectRatio; use LINE\LINEBot\Constant\Flex\ComponentImageAspectMode; use LINE\LINEBot\Constant\Flex\ComponentFontSize; use LINE\LINEBot\Constant\Flex\ComponentFontWeight; use LINE\LINEBot\Constant\Flex\ComponentMargin; use LINE\LINEBot\Constant\Flex\ComponentSpacing; use LINE\LINEBot\Constant\Flex\ComponentButtonStyle; use LINE\LINEBot\Constant\Flex\ComponentButtonHeight; use LINE\LINEBot\Constant\Flex\ComponentSpaceSize; use LINE\LINEBot\Constant\Flex\ComponentGravity; use LINE\LINEBot\MessageBuilder\FlexMessageBuilder; use LINE\LINEBot\MessageBuilder\Flex\BubbleStylesBuilder; use LINE\LINEBot\MessageBuilder\Flex\BlockStyleBuilder; use LINE\LINEBot\MessageBuilder\Flex\ContainerBuilder\BubbleContainerBuilder; use LINE\LINEBot\MessageBuilder\Flex\ContainerBuilder\CarouselContainerBuilder; use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\BoxComponentBuilder; use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\ButtonComponentBuilder; use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\IconComponentBuilder; use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\ImageComponentBuilder; use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\SpacerComponentBuilder; use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\FillerComponentBuilder; use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\SeparatorComponentBuilder; use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\TextComponentBuilder; $is_carousel = NULL; $is_bubble = NULL; $is_singleBubble = NULL; $count_container = 0; $count_bubble = 0; $name_container = NULL; $bubble_direction = array(); $block_header = array(); $block_hero = array(); $block_body = array(); $block_footer = array(); $block_header_style = array(); $block_hero_style = array(); $block_body_style = array(); $block_footer_style = array(); $box_header = array(); $box_hero = array(); $box_body = array(); $box_footer = array(); function bubbleContainerAttr($xmlObj){ $bubbleContainer = $xmlObj; $bubbleContainerAttr = NULL; foreach($bubbleContainer->attributes() as $key=>$val){ if($key=="direction"){$bubbleContainerAttr[0]=implode("",(array)$val[0]);} } return $bubbleContainerAttr; } function blockStyleAttr($xmlObj){ $blockStyle = $xmlObj; $blockStyleAttr = array(null,null,null); foreach($blockStyle->attributes() as $key=>$val){ if($key=="backgroundColor"){$blockStyleAttr[0]=implode("",(array)$val[0]);} if($key=="separator"){$blockStyleAttr[1]=(boolean)implode("",(array)$val[0]);} if($key=="separatorColor"){$blockStyleAttr[2]=implode("",(array)$val[0]);} } if(count($blockStyle->attributes())>0){ return $blockStyleAttr; }else{ return NULL; } } function textComponentArr($xmlObj){ $textComponent = $xmlObj; $textComponentAttr = array(trim((string)$textComponent),null,null,null,null,null,null,null,null,null,null); foreach($textComponent->attributes() as $key=>$val){ if($key=="flex"){$textComponentAttr[1]=(int)implode("",(array)$val[0]);} if($key=="margin"){$textComponentAttr[2]=implode("",(array)$val[0]);} if($key=="size"){$textComponentAttr[3]=implode("",(array)$val[0]);} if($key=="align"){$textComponentAttr[4]=implode("",(array)$val[0]);} if($key=="gravity"){$textComponentAttr[5]=implode("",(array)$val[0]);} if($key=="wrap"){$textComponentAttr[6]=(boolean)implode("",(array)$val[0]);} if($key=="maxLines"){$textComponentAttr[7]=(int)implode("",(array)$val[0]);} if($key=="weight"){$textComponentAttr[8]=implode("",(array)$val[0]);} if($key=="color"){$textComponentAttr[9]=implode("",(array)$val[0]);} if($key=="action"){ $textButton = "u"; $strAction = str_replace(")","",implode("",(array)$val[0])); switch($strAction){ case (preg_match('/^p\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new PostbackTemplateActionBuilder($textButton,$data); break; case (preg_match('/^m\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new MessageTemplateActionBuilder($textButton,$data); break; case (preg_match('/^u\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new UriTemplateActionBuilder($textButton,$data); break; case (preg_match('/^c\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new UriTemplateActionBuilder($textButton,"line://nv/camera/"); break; case (preg_match('/^cs\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new UriTemplateActionBuilder($textButton,"line://nv/cameraRoll/single/"); break; case (preg_match('/^cm\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new UriTemplateActionBuilder($textButton,"line://nv/cameraRoll/multi/"); break; case (preg_match('/^l\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new UriTemplateActionBuilder($textButton,"line://nv/location"); break; case (preg_match('/^d\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new DatetimePickerTemplateActionBuilder($textButton,$data,'datetime'); break; default: $actionVal = new PostbackTemplateActionBuilder($textButton,""); break; } $textComponentAttr[10] = $actionVal; } } return $textComponentAttr; } function boxComponentArr($xmlObj,$arrComponent = array()){ $boxComponent = $xmlObj; $boxComponentAttr = array(null,$arrComponent,null,null,null,null); foreach($boxComponent->attributes() as $key=>$val){ if($key=="layout"){$boxComponentAttr[0]=implode("",(array)$val[0]);} if($key=="flex"){$boxComponentAttr[2]=(int)implode("",(array)$val[0]);} if($key=="spacing"){$boxComponentAttr[3]=implode("",(array)$val[0]);} if($key=="margin"){$boxComponentAttr[4]=implode("",(array)$val[0]);} if($key=="action"){ $textButton = "u"; $strAction = str_replace(")","",implode("",(array)$val[0])); switch($strAction){ case (preg_match('/^p\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new PostbackTemplateActionBuilder($textButton,$data); break; case (preg_match('/^m\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new MessageTemplateActionBuilder($textButton,$data); break; case (preg_match('/^u\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new UriTemplateActionBuilder($textButton,$data); break; case (preg_match('/^c\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new UriTemplateActionBuilder($textButton,"line://nv/camera/"); break; case (preg_match('/^cs\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new UriTemplateActionBuilder($textButton,"line://nv/cameraRoll/single/"); break; case (preg_match('/^cm\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new UriTemplateActionBuilder($textButton,"line://nv/cameraRoll/multi/"); break; case (preg_match('/^l\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new UriTemplateActionBuilder($textButton,"line://nv/location"); break; case (preg_match('/^d\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new DatetimePickerTemplateActionBuilder($textButton,$data,'datetime'); break; default: $actionVal = new PostbackTemplateActionBuilder($textButton,""); break; } $boxComponentAttr[5] = $actionVal; } } return $boxComponentAttr; } function buttonComponentArr($xmlObj){ $buttonComponent = $xmlObj; $textButton = trim((string)$buttonComponent); $buttonComponentAttr = array(new PostbackTemplateActionBuilder($textButton,"nothing"),null,null,null,null,null,null); foreach($buttonComponent->attributes() as $key=>$val){ if($key=="action"){ $strAction = str_replace(")","",implode("",(array)$val[0])); switch($strAction){ case (preg_match('/^p\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new PostbackTemplateActionBuilder($textButton,$data); break; case (preg_match('/^m\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new MessageTemplateActionBuilder($textButton,$data); break; case (preg_match('/^u\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new UriTemplateActionBuilder($textButton,$data); break; case (preg_match('/^c\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new UriTemplateActionBuilder($textButton,"line://nv/camera/"); break; case (preg_match('/^cs\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new UriTemplateActionBuilder($textButton,"line://nv/cameraRoll/single/"); break; case (preg_match('/^cm\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new UriTemplateActionBuilder($textButton,"line://nv/cameraRoll/multi/"); break; case (preg_match('/^l\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new UriTemplateActionBuilder($textButton,"line://nv/location"); break; case (preg_match('/^d\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new DatetimePickerTemplateActionBuilder($textButton,$data,'datetime'); break; default: $actionVal = new PostbackTemplateActionBuilder($textButton,"false"); break; } $buttonComponentAttr[0] = $actionVal; } if($key=="flex"){$buttonComponentAttr[1]=(int)implode("",(array)$val[0]);} if($key=="margin"){$buttonComponentAttr[2]=implode("",(array)$val[0]);} if($key=="height"){$buttonComponentAttr[3]=implode("",(array)$val[0]);} if($key=="style"){$buttonComponentAttr[4]=implode("",(array)$val[0]);} if($key=="color"){$buttonComponentAttr[5]=implode("",(array)$val[0]);} if($key=="gravity"){$buttonComponentAttr[6]=implode("",(array)$val[0]);} } return $buttonComponentAttr; } function iconComponentAttr($xmlObj){ $iconComponent = $xmlObj; $iconComponentAttr = array(null,null,null,null); foreach($iconComponent->attributes() as $key=>$val){ if($key=="url"){$iconComponentAttr[0]=implode("",(array)$val[0]);} if($key=="margin"){$iconComponentAttr[1]=implode("",(array)$val[0]);} if($key=="size"){$iconComponentAttr[2]=implode("",(array)$val[0]);} if($key=="aspectRatio"){$iconComponentAttr[3]=implode("",(array)$val[0]);} } return $iconComponentAttr; } function separatorComponentAttr($xmlObj){ $separatorComponent = $xmlObj; $separatorComponentAttr = array(); foreach($separatorComponent->attributes() as $key=>$val){ if($key=="margin"){$separatorComponentAttr[0]=implode("",(array)$val[0]);} if($key=="color"){$separatorComponentAttr[1]=implode("",(array)$val[0]);} } return $separatorComponentAttr; } function fillerComponentAttr(){ } function spacerComponentAttr($xmlObj){ $spacerComponent = $xmlObj; $spacerComponentAttr = array("md"); foreach($spacerComponent->attributes() as $key=>$val){ if($key=="size"){$spacerComponentAttr[0]=implode("",(array)$val[0]);} } return $spacerComponentAttr; } function imageComponentArr($xmlObj){ $imageComponent = $xmlObj; $imageComponentAttr = array(null,null,null,null,null,null,null,null,null); foreach($imageComponent->attributes() as $key=>$val){ if($key=="url"){$imageComponentAttr[0]=implode("",(array)$val[0]);} if($key=="flex"){$imageComponentAttr[1]=(int)implode("",(array)$val[0]);} if($key=="margin"){$imageComponentAttr[2]=implode("",(array)$val[0]);} if($key=="align"){$imageComponentAttr[3]=implode("",(array)$val[0]);} if($key=="gravity"){$imageComponentAttr[4]=implode("",(array)$val[0]);} if($key=="size"){$imageComponentAttr[5]=implode("",(array)$val[0]);} if($key=="aspectRatio"){$imageComponentAttr[6]=implode("",(array)$val[0]);} if($key=="aspectMode"){$imageComponentAttr[7]=implode("",(array)$val[0]);} if($key=="backgroundColor"){$imageComponentAttr[8]=implode("",(array)$val[0]);} if($key=="action"){ $textButton = "u"; $strAction = str_replace(")","",implode("",(array)$val[0])); switch($strAction){ case (preg_match('/^p\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new PostbackTemplateActionBuilder($textButton,$data); break; case (preg_match('/^m\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new MessageTemplateActionBuilder($textButton,$data); break; case (preg_match('/^u\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new UriTemplateActionBuilder($textButton,$data); break; case (preg_match('/^c\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new UriTemplateActionBuilder($textButton,"line://nv/camera/"); break; case (preg_match('/^cs\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new UriTemplateActionBuilder($textButton,"line://nv/cameraRoll/single/"); break; case (preg_match('/^cm\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new UriTemplateActionBuilder($textButton,"line://nv/cameraRoll/multi/"); break; case (preg_match('/^l\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new UriTemplateActionBuilder($textButton,"line://nv/location"); break; case (preg_match('/^d\(/',$strAction) ? true : false): list($ac,$data) = explode("(",$strAction); $actionVal = new DatetimePickerTemplateActionBuilder($textButton,$data,'datetime'); break; default: $actionVal = new PostbackTemplateActionBuilder($textButton,""); break; } $imageComponentAttr[9] = $actionVal; } } return $imageComponentAttr; } function listElement($xmlObj,$arr_Element = array()){ $arr_final = array(); foreach ($xmlObj->children() as $childObj) { $elName = $childObj->getName(); if($elName=="box"){ $arr_final[] = new BoxComponentBuilder(...boxComponentArr($childObj,listElement($childObj,$arr_Element))); }else{ if($elName=="text"){ $arr_final[] = new TextComponentBuilder(...textComponentArr($childObj)); // textComponentArr }elseif($elName=="button"){ $arr_final[] = new ButtonComponentBuilder(...buttonComponentArr($childObj)); // }elseif($elName=="icon"){ $arr_final[] = new IconComponentBuilder(...iconComponentAttr($childObj)); // }elseif($elName=="image"){ $arr_final[] = new ImageComponentBuilder(...imageComponentArr($childObj)); // }elseif($elName=="filler"){ $arr_final[] = new FillerComponentBuilder(); // }elseif($elName=="spacer"){ $arr_final[] = new SpacerComponentBuilder(...spacerComponentAttr($childObj)); // }elseif($elName=="separator"){ $arr_final[] = new SeparatorComponentBuilder(...separatorComponentAttr($childObj)); // }else{ $arr_final[] = array(); } } } return $arr_final; } function createFlex($xmlstr){ //$objXML = new SimpleXMLElement($xmlstr); $xmlIterator = new SimpleXMLIterator($xmlstr); $xmlIterator->rewind(); $name_container = $xmlIterator->getName(); $count_container = $xmlIterator->count(); if($name_container!="carousel"){ $is_singleBubble = true; } $arr_bubble = array(); $hasBlockStyle = false; $i = 0; for( $xmlIterator; $xmlIterator->valid(); $xmlIterator->next() ) { $bubble_direction[$i] = NULL; $bubble_direction[$i] = bubbleContainerAttr($xmlIterator->current()); $block_header[$i] = NULL; $block_hero[$i] = NULL; $block_body[$i] = NULL; $block_footer[$i] = NULL; $block_header_style[$i] = NULL; $block_hero_style[$i] = NULL; $block_body_style[$i] = NULL; $block_footer_style[$i] = NULL; foreach ($xmlIterator->current()->children() as $blockChild) { if($blockChild->getName()=="header"){ $block_header[$i]=$blockChild; $block_header_style[$i] = (!is_null(blockStyleAttr($blockChild)))?new BlockStyleBuilder(...blockStyleAttr($blockChild)):NULL; $box_header[$i] = listElement($blockChild->children()); } if($blockChild->getName()=="hero"){ $block_hero[$i]=$blockChild; $block_hero_style[$i] = (!is_null(blockStyleAttr($blockChild)))?new BlockStyleBuilder(...blockStyleAttr($blockChild)):NULL; $box_hero[$i] = listElement($blockChild->children()); } if($blockChild->getName()=="body"){ $block_body[$i]=$blockChild; $block_body_style[$i] = (!is_null(blockStyleAttr($blockChild)))?new BlockStyleBuilder(...blockStyleAttr($blockChild)):NULL; $box_body[$i] = listElement($blockChild->children()); } if($blockChild->getName()=="footer"){ $block_footer[$i]=$blockChild; $block_footer_style[$i] = (!is_null(blockStyleAttr($blockChild)))?new BlockStyleBuilder(...blockStyleAttr($blockChild)):NULL; $box_footer[$i] = listElement($blockChild->children()); } } $style_bubble[$i]=NULL; if(!is_null($block_header_style[$i]) || !is_null($block_hero_style[$i]) || !is_null($block_body_style[$i]) || !is_null($block_footer_style[$i])){ $style_bubble[$i] = new BubbleStylesBuilder( $block_header_style[$i], $block_hero_style[$i], $block_body_style[$i], $block_footer_style[$i] ); } $i++; } for($i=0;$i<$count_container;$i++){ $containDirection = (!is_null($bubble_direction[$i]))?$bubble_direction[$i][0]:"ltr"; $containHeader = (!is_null($block_header[$i]))?new BoxComponentBuilder(...boxComponentArr($block_header[$i]->children(),$box_header[$i])):NULL; $containHero = (!is_null($block_hero[$i]))?new ImageComponentBuilder(...imageComponentArr($block_hero[$i]->children(),$box_hero[$i])):NULL; $containBody = (!is_null($block_body[$i]))?new BoxComponentBuilder(...boxComponentArr($block_body[$i]->children(),$box_body[$i])):NULL; $containFooter = (!is_null($block_footer[$i]))?new BoxComponentBuilder(...boxComponentArr($block_footer[$i]->children(),$box_footer[$i])):NULL; $arr_bubble[] = new BubbleContainerBuilder( $containDirection,$containHeader,$containHero,$containBody,$containFooter,$style_bubble[$i] ); } $arr_FlexMessage = NULL; if(!is_null($is_singleBubble)){ $arr_FlexMessage = $arr_bubble[0]; }else{ $arr_FlexMessage = new CarouselContainerBuilder( $arr_bubble ); } $textReplyMessage = $arr_FlexMessage; return $textReplyMessage; }
ส่วนต่อมา กลับมาที่ไฟล์ bot_action.php ให้เราเรียกใช้ไฟล์ฟังก์ชั่น flex_gen.php เข้ามาใน
ไฟล์ bot_action.php ด้วยคำสั่ง
// ไฟล์ฟังก์ชั่นสำหรับแปลง xml เป็น flex require_once("flex_gen.php");
และไฟล์ bot_action.php ให้เราเพิ่ม เงื่อนไข การโต้ตอบกับ Bot อย่างง่ายเข้าไป เช่นสมมติเรากำหนด
ว่า เมื่อผู้ใช้พิมพ์ fl ให้ตอบกลับเป็นข้อความ Flex Message จะได้ไฟล์ bot_action.php เป็นดังนี้
ไฟล์ 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; use LINE\LINEBot\Constant\Flex\ComponentIconSize; use LINE\LINEBot\Constant\Flex\ComponentImageSize; use LINE\LINEBot\Constant\Flex\ComponentImageAspectRatio; use LINE\LINEBot\Constant\Flex\ComponentImageAspectMode; use LINE\LINEBot\Constant\Flex\ComponentFontSize; use LINE\LINEBot\Constant\Flex\ComponentFontWeight; use LINE\LINEBot\Constant\Flex\ComponentMargin; use LINE\LINEBot\Constant\Flex\ComponentSpacing; use LINE\LINEBot\Constant\Flex\ComponentButtonStyle; use LINE\LINEBot\Constant\Flex\ComponentButtonHeight; use LINE\LINEBot\Constant\Flex\ComponentSpaceSize; use LINE\LINEBot\Constant\Flex\ComponentGravity; use LINE\LINEBot\MessageBuilder\FlexMessageBuilder; use LINE\LINEBot\MessageBuilder\Flex\BubbleStylesBuilder; use LINE\LINEBot\MessageBuilder\Flex\BlockStyleBuilder; use LINE\LINEBot\MessageBuilder\Flex\ContainerBuilder\BubbleContainerBuilder; use LINE\LINEBot\MessageBuilder\Flex\ContainerBuilder\CarouselContainerBuilder; use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\BoxComponentBuilder; use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\ButtonComponentBuilder; use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\IconComponentBuilder; use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\ImageComponentBuilder; use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\SpacerComponentBuilder; use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\FillerComponentBuilder; use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\SeparatorComponentBuilder; use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\TextComponentBuilder; // ไฟล์ฟังก์ชั่นสำหรับแปลง xml เป็น flex require_once("flex_gen.php"); // ส่วนของการทำงาน 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 = ""; if(isset($dataPostback['action']) && $dataPostback['action']=="more_richmenu"){ $respRichMenu = $bot->linkRichMenu($userId,$dataPostback['richmenuid']); $moreResult = $respRichMenu->getRawBody(); $result = json_decode($respRichMenu->getRawBody(),TRUE); } if(isset($dataPostback['action']) && $dataPostback['action']=="back_richmenu"){ $respRichMenu = $bot->unlinkRichMenu($userId); $moreResult = $respRichMenu->getRawBody(); $result = json_decode($respRichMenu->getRawBody(),TRUE); } if(isset($dataPostback['action']) && $dataPostback['action']=="delete_richmenu"){ $respRichMenu = $bot->deleteRichMenu($dataPostback['richMenuId']); $moreResult = $respRichMenu->getRawBody(); $result = json_decode($respRichMenu->getRawBody(),TRUE); } 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); } 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); } 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 "fl": // ส่วนทดสอบโต้ตอบข้อควมม flex $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); break; 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-": $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; $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 'เลือกการจัดการ', 'https://www.example.com/linebot/rich-menu/rich-menu-pattern-0'.$imgRichLayout.'.png', // ไม่แสดงรูป มีมี url รูป 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-": $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 'เลือกการจัดการ', 'https://www.example.com/linebot/rich-menu/rich-menu-pattern-0'.$imgRichLayout.'.png', // ไม่แสดงรูป มีมี url รูป 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; } } } ?>
ทดสอบ ถ้าไม่มีอะไรผิดพลาด ก็จะได้ผลลัพธ์ดังนี้
ส่วนของการสร้าง Flex Message ข้างต้น เราทำการสร้าง Bubble ที่มี
Text Component ข้อความว่า hello world
$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);
สำหรับ คำว่า "This is a Flex Message" จะเป็นข้อความที่แสดงหรืออธิบายว่า Flex Message
ที่เราส่งไปนั้น เป็นเนื้อหาเกี่ยวกับอะไร ตามตัวอย่างรูปด้านบน หน้ารวมห้องสนทนา เราจะเห็นข้อความ
นี้แสดง ข้อความส่วนนี้ สามารถเปลี่ยนอะไรก็ได้ ที่เราต้องการสื่อถึงรายละเอียดของ Flex Message
สร้าง Flex Message จากรูปแบบ XML
ต่อไปเรามาดูว่า ถ้าเราจะส่งข้อความ hello world ในรูปแบบตามตัวอย่างข้างต้น แต่เขียนในรูปแบบ
XML จะสามารถทำได้แบบไหน
// Flex Message รูปแบบ XML $xmlstr = <<<XML <noncarousel> <bubble direction="ltr"> <body> <box layout="vertical"> <text>hello</text> <text>world</text> </box> </body> </bubble> </noncarousel> XML; $textReplyMessage = createFlex($xmlstr); $replyData = new FlexMessageBuilder("Flex from XML",$textReplyMessage);
ในรูปแบบ XML เราสร้าง XML string แล้วไว้ในตัวแปร $xmlstr โดยใช้รูปแบบ Heredoc syntax
เป็นการกำหนดค่าตัวแปรรูปแบบหนึ่ง
$xmlstr = <<<XML <!--รูปแบบ XML ที่ต้องการ--> XML;
สังเกตุว่า ตัวปิดของการกำหนดแบบ Herodoc (XML;) จะต้องชิดขอบด้านซ้าย โดยไม่มีช่องว่ามากั้นเสมอ
ไม่เช่นจะไม่สามารถกำหนดค่าได้
หลักการทำงาน เราส่งรูปแบบ XML เข้าไปในฟังก์ชั่น createFlex($xmlstr) เพื่อแปลงค่า
เป็น Flex Message ก่อนนำไปใช้งาน
Flex Message XML Elements
องค์ประกอบของ Flex Message ในรูปแบบ XML ประกอบไปด้วย Elements ต่างๆ
แบ่งออกได้เป็นแต่ละส่วนดังนี้
ส่วนที่ใช้ในการกำหนด Container
- <noncarousel> รูปแบบการใช้งาน <noncarousel>...</noncarousel>
- <carousel> รูปแบบการใช้งาน <carousel>...</carousel>
- <bubble> รูปแบบการใช้งาน <bubble>....</bubble>
ส่วนที่ใช้ในการกำหนด Block
- <header> รูปแบบการใช้งาน <header>...</header>
- <hero> รูปแบบการใช้งาน <hero>...</hero>
- <body> รูปแบบการใช้งาน <body>...</body>
- <footer> รูปแบบการใช้งาน <footer>...</footer>
ส่วนที่ใช้ในการกำหนด Component
- <box> รูปแบบการใช้งาน <box>...</box>
- <button> รูปแบบการใช้งาน <button>...</button>
- <filler> รูปแบบการใช้งาน <filler />
- <icon> รูปแบบการใช้งาน <icon />
- <image> รูปแบบการใช้งาน <image />
- <separator> รูปแบบการใช้งาน <separator />
- <spacer> รูปแบบการใช้งาน <spacer />
- <text> รูปแบบการใช้งาน <text>...</text>
จะใช้เป็นตัวพิมพ์เล็กทั้งหมด จะเห็นว่าจะเหมือนกันรูปแบบที่กำหนดใน JSON แต่มีเพิ่ม
มาคือ <noncarousel> สำหรับ ส่งข้อมูล Flex ที่เป็น Single Bubble
การกำหนด Property ให้กับ Flex Message Element
ใน Element แต่ละตัว ก็จะมี property ตามรูปแบบ ที่ Line กำหนด โดยในการ XML
เราจะกำหนด property ไว้ในส่วนของ Attribute และบางตัวกำหนดไว้ใน Text Node
ของ Element นั้น
สามารถดู property ต่าง ๆ เพิ่มเติมได้ที่
Property จะเป็นแบบ case-sensitive คือยึดตามรูปแบบของ Line เช่น สีพื้นหลัง
ใช้เป็น "backgroundColor" จะไม่ใช้เป็น "backgroundcolor"
ตัวอย่าง
<noncarousel> <bubble direction="ltr"> <body backgroundColor="#CCCCCC"> <box layout="vertical"> <text>hello</text> <text>world</text> </box> </body> </bubble> </noncarousel>
Element บางตัวใช้ textNode เป็นค่า text property เช่น <text> และ <button>
ตัวอย่าง
<text>hello world</text> <button action="u(http://niik.in)">Go</button>
Element บางตัว เช่น <filler> ไม่มี property ก็สามารถใช้เป็น <filler /> ได้เลย
Elements Property
ต่อไปเราจะมาดู property ต่างๆ ไล่ไปแต่ละ element โดย property ใดที่จำเป็นต้องกำหนดเสมอ
เราจะใช้ * กำหนดไว้ด้านหน้า
Container Elements
Carousel Container
<carousel> <bubble direction="ltr"> </bubble> <bubble direction="ltr"> </bubble> </carousel>
Bubble Container
<noncarousel> <bubble direction="ltr"> </bubble> </noncarousel>
สำหรับ property ของ Container จะกำหนดใน Bubble Element มี property เดียวคือ
*direction
กำหนดค่า ltr หรือ rtl เป็นการกำหนดลักษณะการอ่านของข้อความ จากซ้ายไปขวาหรือขวาไปซ้าย
ในไทยก็จะเป็นการอ่านจากซ้ายไปขวา เราก็ใช้ ltr เสมอแทนได้
Block Elements
<noncarousel> <bubble direction="ltr"> <header backgroundColor="#CCCCCC"> </header> <hero> <hero> <body separator="true" separatorColor="#FF0000"> </body> <footer> </footer> </bubble> </noncarousel>
สำหรับ Header, Hero, Body และ Footer Block จะมีด้วยกัน 3 property ได้แก่
backgroundColor
ค่าสีพื้นหลังใช้เป็นข้อความเลขฐาน 16 เช่น #CCCCCC
separator
กำหนดมีเส้นแบ่งด้านบนของ Block หรือไม่ ใช้ค่า "true" หรือ "false" ไม่มีผลกับ Block ตัวแรก
separatorColor
ค่าสีเส้นแบ่งเลขฐาน 16 เช่น #CCCCCC
Component Elements
Box Element
<box layout="vertical" flex="2"> </box>
*layout
กำหนดค่าการจัดเรียงแนวนอน "horizontal" "vertical" หรือ "baseline"
เพิ่มเติม http://niik.in/899
flex
กำหนดเป็นตัวเลข เป็นค่ากำหนดถึงสัดส่วนความกว้างหรือสูงของ element นั้นเทียบกับ parent box
เพิ่มเติม http://niik.in/899
spacing
กำหนดระยะห่างระหว่าง element ด้านใน ค่า none, xs, sm, md, lg, xl, หรือ xxl
เพิ่มเติม http://niik.in/899
margin
กำหนดระยะห่างของ element ใกล้เคียง none, xs, sm, md, lg, xl, หรือ xxl
เพิ่มเติม http://niik.in/899
action
กำหนดการทำงานให้กับ element นั้น ๆ เมื่อแตะหรือกดที่ element
รูปแบบการใช้งาน จะอธิบายในหัวข้อถัดไป ตัวอย่าง action="u(http://niik.in)" หมายถึง
ลิ้งค์ไปยัง url ที่กำหนด
Button Element
<button style="primary" action="u(http://niik.in)"> More </button>
*action
กำหนดการทำงานให้กับ element นั้น ๆ เมื่อแตะหรือกดที่ element
รูปแบบการใช้งาน จะอธิบายในหัวข้อถัดไป ตัวอย่าง action="u(http://niik.in)" หมายถึง
ลิ้งค์ไปยัง url ที่กำหนด
flex
กำหนดเป็นตัวเลข เป็นค่ากำหนดถึงสัดส่วนความกว้างหรือสูงของ element นั้นเทียบกับ parent box
เพิ่มเติม http://niik.in/899
margin
กำหนดระยะห่างของ element ใกล้เคียง none, xs, sm, md, lg, xl, หรือ xxl
เพิ่มเติม http://niik.in/899
height
กำหนดความสูงให้กับ button ค่า sm หรือ md ค่าเริ่มต้นคือ md
style
กำหนดรูปแบบของ button ค่า
- link สำหรับรูปแบบลิ้งค์คล้ายใน HTML
- primary สำหรับปุ่มพื้นหลังสีเข้ม
- secondary สำหรับปุ่มพื้นหลังสีอ่อน
ค่าเริ่มต้นเป็น link *(คำว่า ค่าเริ่มต้น หมายถึง ถ้าไม่ได้กำหนด จะใช้ค่าเริ่มต้น แทน)
color
ค่าสีใช้เป็นข้อความเลขฐาน 16 เช่น #CCCCCC
จะเป็นค่าสีของข้อความถ้ากำหนด style เป็น link และจะเป็นสีพื้นหลัง
ถ้ากำหนด style เป็น primary หรือ secondary
gravity
การจัดตำแหน่งในแนวตั้งเทียบกับ parent box
ค่า top , center หรือ bottom
เพิ่มเติม http://niik.in/899
Filler Element
<filler />
ไม่ต้องกำหนด property แต่จำไว้ว่า filler มี flex เท่ากับ 1 เสมอ และ การกำหนด spacing
ใน parent box ไม่มีผลกับ filler
Icon Element
<icon url="https://www.ninenik.com/images/ninenik_page_logo.png" />
*url
กำหนด url ของไฟล์รูปภาพที่ต้องการใช้เป็นไอคอน ต้องเรียกผ่าน https เท่านั้น
รองรับไฟล์ JPEG และ PNG ขนาดสูงสุดไม่เกิน 240x240
ขนาดไฟล์สูงสุดไม่เกิน 1 MB
margin
กำหนดระยะห่างของ element ใกล้เคียง none, xs, sm, md, lg, xl, หรือ xxl
เพิ่มเติม http://niik.in/899
size
กำหนดขนาดสูงสุดของ element นั้นๆ
ใช้ค่า xxs, xs, sm, md, lg, xl, xxl, 3xl, 4xl, หรือ 5xl ใหญ่ขึ้นตามลำดับ ค่าเริ่มต้นคือ md
aspectRatio
อัตราส่วนความกว้างต่อความสูง {width}:{height} เข่น 4:3 หรือ 16:9 ค่าเริ่มต้นเป็น 1:1
เพิ่มเติม http://niik.in/899
Icon Element จะมี flex property เท่ากับ 0 คือ มีความกว้างหรือความสูง เท่ากับขนาดของ Icon นั้นๆ
Image Element
<image url="https://www.ninenik.com/images/ninenik_page_logo.png" />
*url
กำหนด url ของไฟล์รูปภาพ ต้องเรียกผ่าน https เท่านั้น
รองรับไฟล์ JPEG และ PNG ขนาดสูงสุดไม่เกิน 1024x1024
ขนาดไฟล์สูงสุดไม่เกิน 1 MB
flex
กำหนดเป็นตัวเลข เป็นค่ากำหนดถึงสัดส่วนความกว้างหรือสูงของ element นั้นเทียบกับ parent box
เพิ่มเติม http://niik.in/899
margin
กำหนดระยะห่างของ element ใกล้เคียง none, xs, sm, md, lg, xl, หรือ xxl
เพิ่มเติม http://niik.in/899
align
การจัดตำแหน่งในแนวนอนเทียบกับ parent box
ค่า start , center หรือ end ค่าเริ่มต้น จะเป็น center
เพิ่มเติม http://niik.in/899
gravity
การจัดตำแหน่งในแนวตั้งเทียบกับ parent box
ค่า top , center หรือ bottom ค่าเริ่มต้น จะเป็น top
เพิ่มเติม http://niik.in/899
size
กำหนดขนาดสูงสุดของ element นั้นๆ
ใช้ค่า xxs, xs, sm, md, lg, xl, xxl, 3xl, 4xl, 5xl, หรือ full ขนาดจะใหญ่ขึ้นตามลำดับ
ค่าเริ่มต้นคือ md
aspectRatio
อัตราส่วนความกว้างต่อความสูง {width}:{height} เข่น 4:3 หรือ 16:9 ค่าเริ่มต้นเป็น 1:1
เพิ่มเติม http://niik.in/899
aspectMode
การกำหนดลักษณะการแสดงของรูป ค่า fit และ cover ค่าเริ่มต้นคือ fit
fit สำหรับให้แสดงให้เห็นรูปนั้นๆ ในพื้นที่ อาจจะมีช่องว่างพื้นหลังถ้ารูปนั้นมีขนาดไม่สันพันธ์กับพื้นที่
cover สำหรับให้รูปคลุมเต็มพื้นที่ ลักษณะคล้ายกับเป็นรูปพื้นหลัง บางส่วนของรูปอาจหายไป
ถ้าพื้นที่ไม่สัมพันธ์กับขนาดรูป
เพิ่มเติม http://niik.in/899
backgroundColor
สำหรับกำหนดสีพื้นหลัง กรณีรูปนั้นเป็นรูปโปร่งแสง
ค่าสีพื้นหลังใช้เป็นข้อความเลขฐาน 16 เช่น #CCCCCC
action
กำหนดการทำงานให้กับ element นั้น ๆ เมื่อแตะหรือกดที่ element
รูปแบบการใช้งาน จะอธิบายในหัวข้อถัดไป ตัวอย่าง action="u(http://niik.in)" หมายถึง
ลิ้งค์ไปยัง url ที่กำหนด
Separator Element
<separator />
margin
กำหนดระยะห่างของ element ใกล้เคียง none, xs, sm, md, lg, xl, หรือ xxl
เพิ่มเติม http://niik.in/899
color
กำหนดสีของเส้นคั่นหรือเส้นแบ่ง ค่าสีใช้เป็นข้อความเลขฐาน 16 เช่น #CCCCCC
Spacer Element
<spacer />
size
ขนาดของช่องว่าง ระหว่าง element
ใช้ค่า xs, sm, md, lg, xl, หรือ xxl ขนาดจะใหญ่ขึ้นตามลำดับ
ค่าเริ่มต้นคือ md
การกำหนด spacing property ของ parent box จะไม่มีผลกับ Spacer Element
Text Element
<text>Hello World</text>
flex
กำหนดเป็นตัวเลข เป็นค่ากำหนดถึงสัดส่วนความกว้างหรือสูงของ element นั้นเทียบกับ parent box
เพิ่มเติม http://niik.in/899
margin
กำหนดระยะห่างของ element ใกล้เคียง none, xs, sm, md, lg, xl, หรือ xxl
เพิ่มเติม http://niik.in/899
size
กำหนดขนาดของตัวอักษร
ใช้ค่า xxs, xs, sm, md, lg, xl, xxl, 3xl, 4xl, หรือ 5xl ขนาดจะใหญ่ขึ้นตามลำดับ
ค่าเริ่มต้นคือ md
align
การจัดตำแหน่งในแนวนอนเทียบกับ parent box
ค่า start , center หรือ end ค่าเริ่มต้น จะเป็น center
เพิ่มเติม http://niik.in/899
gravity
การจัดตำแหน่งในแนวตั้งเทียบกับ parent box
ค่า top , center หรือ bottom ค่าเริ่มต้น จะเป็น top
เพิ่มเติม http://niik.in/899
wrap
กำหนดให้ขึ้นบรรทัดใหม่อัตโนมัติ เพื่อให้ข้อความอยู่ในกรอบ หรือพื้นที่
ใช้ ค่า true หรือ false ค่าเริ่มต้นเป็น false กรณีใช้ค่าเป็น true เราสามารถกำหนด
การขึ้นบรรทัดใหม่โดยใช้ \n แทรกในข้อความได้
maxLines
กำหนดตัวเลข จำนวนบรรทัดของข้อความสูงสุด กรณีข้อความมีจำนวนมาก
ทำให้จำนวนบรรทัดเกินค่าที่กำหนด จะแสดงเป็น (...) ต่อท้าย
ถ้ากำหนดเป็น 0 จะหมายถึงให้แสดงข้อความทั้งหมด ค่าเริ่มต้นเท่ากับ 0
weight
กำหนดความเข้มหรือความหนาของข้อความ โดยใช้ค่า regular หรือ bold
โดยถ้าระบุเป็น bold จะเป็นตัวหนา ค่าเริ่มต้นเป็น regular หรือตัวอักษรปกติ
color
กำหนดสีของข้อความ ค่าสีใช้เป็นข้อความเลขฐาน 16 เช่น #CCCCCC
action
กำหนดการทำงานให้กับ element นั้น ๆ เมื่อแตะหรือกดที่ element
รูปแบบการใช้งาน จะอธิบายในหัวข้อถัดไป ตัวอย่าง action="u(http://niik.in)" หมายถึง
ลิ้งค์ไปยัง url ที่กำหนด
การกำหนด Action ให้กับ Element
action เป็น property หนึ่งที่ให้ผู้ใช้สามารถโต้ตอบหรือปฏิสัมพันธ์กับ Flex Message โดย Element
ที่รองรับ action property ได้แก่ Box , Button , Image และ Text Element
<button style="primary" action="u(http://niik.in)">More</button>
รูปแบบ action
p(data) สำหรับกำหนด postback action
action="p(a=1&b=2)"
m(data) สำหรับกำหนด message action
action="m(flex message)"
u(data) สำหรับกำหนด uri action หรือ url
action="u(http://niik.in)"
d(data) สำหรับกำหนด datetime picker action
action="d(reservDate=1&room=1)"
c() สำหรับกำหนด เพื่อถ่ายรูป
action="c()"
cs() สำหรับกำหนด ให้เลือกรูป 1 รูปจากคลังภาพ
action="cs()"
cm() สำหรับกำหนด ให้เลือกรูปได้หลายรูปจากคลังภาพ
action="cm()"
l() สำหรับกำหนด เลือกตำแหน่งในแผนที่ (*ตัว L พิมพ์เล็ก)
action="l()"
ทั้งหมด เป็นแนวทางการประยุกต์ การสร้าง Flex Message ในรูปแบบ XML สามารถนำไปปรับแต่ง
เพิ่มเติมได้ตามต้องการ