[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"blog-categories":3,"blog-category-html":78},[4,10,14,19,24,30,36,40,45,51,55,58,62,68,73],{"id":5,"databaseId":6,"name":7,"slug":8,"count":9},"dGVybTo1NQ==",55,"AI","ai",2,{"id":11,"databaseId":12,"name":13,"slug":13,"count":9},"dGVybTo2MQ==",61,"backend",{"id":15,"databaseId":16,"name":17,"slug":18,"count":16},"dGVybToyMA==",20,"Devops","devops",{"id":20,"databaseId":21,"name":22,"slug":22,"count":23},"dGVybToxNQ==",15,"frontend",25,{"id":25,"databaseId":26,"name":27,"slug":28,"count":29},"dGVybTo2MA==",60,"GAS","gas",1,{"id":31,"databaseId":32,"name":33,"slug":34,"count":35},"dGVybTo5",9,"HTML","html",4,{"id":37,"databaseId":38,"name":39,"slug":39,"count":29},"dGVybToyMg==",22,"mac",{"id":41,"databaseId":42,"name":43,"slug":43,"count":44},"dGVybTo2",6,"node",18,{"id":46,"databaseId":47,"name":48,"slug":49,"count":50},"dGVybTo2OQ==",69,"Nuxt","nuxt",3,{"id":52,"databaseId":53,"name":54,"slug":54,"count":50},"dGVybTo1NA==",54,"office",{"id":56,"databaseId":9,"name":57,"slug":57,"count":21},"dGVybToy","omekas",{"id":59,"databaseId":60,"name":61,"slug":61,"count":16},"dGVybToxNg==",16,"vue",{"id":63,"databaseId":64,"name":65,"slug":66,"count":67},"dGVybTo1",5,"WordPress","wordpress",13,{"id":69,"databaseId":29,"name":70,"slug":71,"count":72},"dGVybTox","無","uncategorized",null,{"id":74,"databaseId":75,"name":76,"slug":77,"count":9},"dGVybTo3MA==",70,"生活","life",[79,95,108,120],{"id":80,"slug":81,"title":82,"description":83,"content":84,"date":85,"image":86,"imageAlt":82,"author":87,"categories":90,"path":94,"minRead":9},3325,"vue初探liff的一些筆記-開發篇","[Vue]初探LIFF的一些筆記-開發篇","初探LIFF的一些筆記 最近因為chatGPT很紅因素，很多人將chatGPT與line整合一起，在玩這類專案 […]","\u003Ch1>初探LIFF的一些筆記\u003C\u002Fh1>\n\u003Cp>最近因為chatGPT很紅因素，很多人將chatGPT與line整合一起，在玩這類專案時剛好碰到了line的API服務於是認識到LIFF，今天花點時間整理關於開發LIFF遇到的狀況。\u003Cbr \u002F>\nLIFF ( LINE Front-end Framework ) 是Line推出的一種前端框架，可以將功能與Line直接整合，藉此取得使用者user資料、進行部分操作。\u003Cbr \u002F>\n用這玩意能完美的與Line bot連動，透過使用 Line Login 或 Account Link 的網站進行使用者資料串接，進而製作更全面性的整合行銷服務。\u003Cbr \u002F>\n我用Vue3進行串接開發，使用setup script。\u003C\u002Fp>\n\u003Ch2>使用LIFF\u003C\u002Fh2>\n\u003Cp>請參考\u003Ca href=\"https:\u002F\u002Fpost.billxu.net\u002Fline初探liff的一些筆記-申請篇\u002F\" title=\"liff的一些筆記-申請篇\">LIFF的一些筆記-申請篇\u003C\u002Fa>\u003C\u002Fp>\n\u003Ch2>載入\u003C\u002Fh2>\n\u003Cp>使用LIFF SDK可以直接用CDN引入\u003C\u002Fp>\n\u003Cpre>\u003Ccode>&lt;script src=&quot;https:\u002F\u002Fstatic.line-scdn.net\u002Fliff\u002Fedge\u002F2\u002Fsdk.js&quot;&gt;&lt;\u002Fscript&gt;\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>在Vue話，我是先透過npm安裝\u003C\u002Fp>\n\u003Cpre>\u003Ccode>npm install vue-router@next @line\u002Fliff\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>使用Vue3的setup script，載入SDK\u003C\u002Fp>\n\u003Cpre>\u003Ccode>&lt;script setup&gt;\nimport liff from &quot;@line\u002Fliff&quot;;\n&lt;\u002Fscript&gt;\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>後面就可以直接用囉。\u003C\u002Fp>\n\u003Ch2>初始化\u003C\u002Fh2>\n\u003Cp>啟動 LIFF 前需要先初始化(init)，在 Vue 的話就在 Mounted 實作這件事情。\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-javascript\">onMounted(async () =&gt; {\n  liff\n  .init({\n    liffId: &quot;&lt;LIFF ID&gt;&quot;, \u002F\u002F 從LIFF頁面中拿到的ID\n  })\n  .then(() =&gt; { \n  \u002F\u002F做你想要做的\n  })\n  .catch((err) =&gt; {\n    console.log(err.code, err.message);\n  });\n})\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2>登入與登出\u003C\u002Fh2>\n\u003Cp>登入後的redirectUri最好是跟LIFF頁面上設定的Callback URL相同，當然你可以依照需求轉到你要的地方。\u003Cbr \u002F>\n\u003Cimg decoding=\"async\" src=\"\u002Fapi\u002Fproxy-image?url=https%3A%2F%2Fpost.billxu.net%2Fwp-content%2Fuploads%2F2022%2F12%2F%E6%88%AA%E5%9C%96-2022-12-21-%E4%B8%8B%E5%8D%8812.17.53.png\" alt=\"\" \u002F>\u003C\u002Fp>\n\u003Cpre>\u003Ccode>if(!sysdata.isLoggedIn) {\n    liff.login({\n      redirectUri: window.location.href \u002F\u002F登入後轉址到需要的地方\n    });\n  }\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>登出就比較單純\u003C\u002Fp>\n\u003Cpre>\u003Ccode> if(sysdata.isLoggedIn) {\n    liff.logout();\n    window.location.reload(); \u002F\u002F 登出後重整一次頁面\n  }\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2>取得基本資訊\u003C\u002Fh2>\n\u003Cp>我將取得資訊跟初始化寫在一起，範例如下。\u003C\u002Fp>\n\u003Cul>\n\u003Cli>打開頁面中的使用語系（lang）\u003C\u002Fli>\n\u003Cli>LIFF SDK 的版本\u003C\u002Fli>\n\u003Cli>目前 LIFF 是否是在 LINE App 中開啟\u003C\u002Fli>\n\u003Cli>使用者有沒有登入 LINE 帳號\u003C\u002Fli>\n\u003Cli>使用者的作業系統：web、android、ios\u003C\u002Fli>\n\u003Cli>\n\u003Cp>使用者用的 LINE App 版本\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-javascript\">onMounted(async () =&gt; {\nliff\n.init({\nliffId: &quot;&quot;, \u002F\u002F 從LIFF頁面中拿到的ID\n})\n.then(() =&gt; {\nsysdata.language = liff.getLanguage(); \u002F\u002F String。引用 LIFF SDK 的頁面，頁面中的 lang 資料\nsysdata.version = liff.getVersion(); \u002F\u002F String。取得LIFF SDK 的版本\nsysdata.isInClient = liff.isInClient(); \u002F\u002F Boolean。回傳是否由 LINE App 存取\nsysdata.isLoggedIn = liff.isLoggedIn(); \u002F\u002F Boolean。檢查使用者是否登入 LINE 帳號狀態。true 時，可呼叫需要 Access Token 的 API\nsysdata.os = liff.getOS(); \u002F\u002F String。取得使用者的作業系統：ios、android、web\nsysdata.lineVersion = liff.getLineVersion(); \u002F\u002F 使用者的 LINE 版本\nconsole.log(sysdata.language,sysdata.version,sysdata.isInClient,sysdata.isLoggedIn,sysdata.os,sysdata.lineVersion);\n\n})\n.catch((err) =&gt; {\nconsole.log(err.code, err.message);\n});\n})\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>這邊要再講一下，申請完LIFF後會有個原來的Endpoint URL和LIFF上的LIFF URL，兩邊的LIFF SDK都會作用，但取得的權限不同(見下段落)，如果需要在LINE做一些操作，最好使用LIFF URL給使用者打開。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2>取得使用者資訊\u003C\u002Fh2>\n\u003Cp>取得使用者資訊使用這個api，取得後可以檢查使用者賦予的權限和一些資料，必須要使用者必須登入才能使用。\u003C\u002Fp>\n\u003Cpre>\u003Ccode>userdata.context = liff.getContext();\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>回傳有以下幾種資料\u003C\u002Fp>\n\u003Cul>\n\u003Cli>type: utou(一對一聊天)、group(群組)、room(多人聊天室)、external(外部，通常是瀏覽器)、none(除以上外)。\u003C\u002Fli>\n\u003Cli>viewType：compact、tall、full。目前視窗的尺寸，可以在LIFF中設定。\u003C\u002Fli>\n\u003Cli>userId、groupId、roomId：不同的 type 會有不同的 ID。\u003C\u002Fli>\n\u003Cli>availability.shareTargetPicker.permission：能不能使用 shareTargetPicker 功能，可以在LIFF中打開。\u003C\u002Fli>\n\u003Cli>availability.shareTargetPicker.minVer：使用 shareTargetPicker 功能的需求版本是多少。\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>這邊就要提醒一下，Endpoint URL和LIFF URL打開來得到的使用者資訊是不同的，前者type為external後者為utou(如果是bot聊天)。\u003C\u002Fp>\n\u003Ch2>取得使用者公開資料\u003C\u002Fh2>\n\u003Cp>必須要使用者必須登入才能使用。回傳資料有四個：userId、暱稱、照片的圖片位置、狀態消息。除了userId外皆屬於完全公開資訊。\u003C\u002Fp>\n\u003Cpre>\u003Ccode>liff.getProfile()\n    .then(function(profile) {\n    userdata.profile = profile;\n    console.log(userdata.profile);\n});\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>取得使用者 email\u003C\u002Fh3>\n\u003Cp>必須要使用者必須登入才能使用。也必須先在LIFF打開權限，並且使用者登入時需授權。\u003Cbr \u002F>\n\u003Cimg decoding=\"async\" src=\"\u002Fapi\u002Fproxy-image?url=https%3A%2F%2Fpost.billxu.net%2Fwp-content%2Fuploads%2F2022%2F12%2F%E6%88%AA%E5%9C%96-2022-12-21-%E4%B8%8B%E5%8D%8812.01.58.png\" alt=\"\" \u002F>\u003Cbr \u002F>\n還要打開LIFF的Scopes權限(email*)\u003Cbr \u002F>\n\u003Cimg decoding=\"async\" src=\"\u002Fapi\u002Fproxy-image?url=https%3A%2F%2Fpost.billxu.net%2Fwp-content%2Fuploads%2F2022%2F12%2F%E6%88%AA%E5%9C%96-2022-12-21-%E4%B8%8B%E5%8D%8812.05.21.png\" alt=\"\" \u002F>\u003C\u002Fp>\n\u003Cpre>\u003Ccode> const user = liff.getDecodedIDToken();\n    userdata.user = user\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>發送訊息\u003C\u002Fh3>\n\u003Cp>使用者必須登入才能使用，分為對自己和對其他人。要先打開LIFF的Scopes權限(chat_message.write)，並且使用者在登入時要授權。\u003Cbr \u002F>\n\u003Cimg decoding=\"async\" src=\"\u002Fapi\u002Fproxy-image?url=https%3A%2F%2Fpost.billxu.net%2Fwp-content%2Fuploads%2F2022%2F12%2F%E6%88%AA%E5%9C%96-2022-12-21-%E4%B8%8B%E5%8D%8812.05.21.png\" alt=\"\" \u002F>\u003C\u002Fp>\n\u003Ch3>對自己發送\u003C\u002Fh3>\n\u003Cp>只能在Line APP才能使用此功能，而且需要一對一聊天室，使用者資料的type須為utou，如果為group、room沒測試不知道能不能使用。external則不行。\u003C\u002Fp>\n\u003Cpre>\u003Ccode>const sendMessegeToSelf = () =&gt; {\n  \u002F\u002F 傳送訊息給自己\n  \u002F\u002F type 的可用值說明：https:\u002F\u002Fdevelopers.line.biz\u002Fen\u002Freference\u002Fliff\u002F#send-messages\n  liff.sendMessages([\n    {\n      type: &#039;text&#039;,\n      text: &lt;發送訊息&gt;\n    }\n  ])\n  .then(res =&gt; window.alert(res.status))\n  .catch(error =&gt; window.alert(error));\n}\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>對其他人發送\u003C\u002Fh3>\n\u003Cp>type為external也可以使用，但記得要先開啟\u003Cem>shareTargetPicker\u003C\u002Fem>。\u003Cbr \u002F>\n\u003Cimg decoding=\"async\" src=\"\u002Fapi\u002Fproxy-image?url=https%3A%2F%2Fpost.billxu.net%2Fwp-content%2Fuploads%2F2022%2F12%2F%E6%88%AA%E5%9C%96-2022-12-21-%E4%B8%8B%E5%8D%8812.08.03.png\" alt=\"\" \u002F>\u003C\u002Fp>\n\u003Cpre>\u003Ccode>const sendMessegeToOther = () =&gt; {\n  \u002F\u002F 傳送訊息給朋友\n  \u002F\u002F 發訊息的可用參數：https:\u002F\u002Fdevelopers.line.biz\u002Fen\u002Freference\u002Fliff\u002F#share-target-picker\n  if(sysdata.isLoggedIn &amp;&amp; liff.isApiAvailable(&#039;shareTargetPicker&#039;)) {\n    liff.shareTargetPicker([\n      {\n        type: &quot;text&quot;,\n        text: &lt;發送訊息&gt;\n      }\n    ])\n    .then(res =&gt; window.alert(res.status))\n    .catch(error =&gt; window.alert(error))\n  }\n}\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2>QRcode\u003C\u002Fh2>\n\u003Cp>很多人都會介紹，但IOS目前不能用，所以先筆記一下\u003C\u002Fp>\n\u003Cpre>\u003Ccode>liff.scanCode()\n  .then(function(res) {\n    console.log(res);\n  })\n  .catch(function(error) {\n    console.log(error);\n  });\u003C\u002Fcode>\u003C\u002Fpre>\n","2023-01-10T12:05:31","\u002Fapi\u002Fproxy-image?url=https%3A%2F%2Fpost.billxu.net%2Fwp-content%2Fuploads%2F2022%2F12%2FLINE_logo.svg.png",{"name":88,"link":89},"Chih Fan","http:\u002F\u002Fpost.billxu.net",[91,92,93],{"name":22,"slug":22},{"name":33,"slug":34},{"name":61,"slug":61},"\u002Fblog\u002Fvue初探liff的一些筆記-開發篇",{"id":96,"slug":97,"title":98,"description":99,"content":100,"date":101,"image":102,"imageAlt":98,"author":103,"categories":104,"path":107,"minRead":29},130,"omkeas關於資源取用的xmlhttprequest問題","[OmkeaS]關於資源取用的XMLHttpRequest問題","關於資源取用的XMLHttpRequest問題 終於將機器從VM搬到Proxmox上了，也移植到docker中 […]","\u003Ch1>關於資源取用的XMLHttpRequest問題\u003C\u002Fh1>\n\u003Cp>終於將機器從VM搬到Proxmox上了，也移植到docker中，然後就發現到一個問題，條目的圖片居然無法從Viewer中讀取出來。怎麼會這樣勒，從console中會看到有個錯誤，寫著\u003Cem>This request has been blocked; the content must be served over HTTPS\u003C\u002Fem>，\u003Cem>會發現到有個關鍵字XMLHttpRequest\u003C\u002Fem>，看來是出現了Https取用Http的的混用問題。\u003Cbr \u002F>\n但說來慚愧，現在才注意到這個問題也是因為原本網站還沒有使用Https，所以一直沒發現到OmekaS存在這個狀況。\u003C\u002Fp>\n\u003Ch2>OmekaS的資源取用問題\u003C\u002Fh2>\n\u003Cp>我們會發生這個問題要先提到Universal viewer這個模組，經過檢查發現Universal viewer會呼叫配置檔以及IIIF的API，然後都是走\u003Cem>Http\u003C\u002Fem>，而這個取用路徑似乎包在Universal viewer的JS中，很難直接修改。\u003C\u002Fp>\n\u003Ch2>解決作法\u003C\u002Fh2>\n\u003Cp>遇到XMLHttpRequest問題其實滿好處理的，從Stockflow上可以找到好幾種建議，大致上會分三種：\u003C\u002Fp>\n\u003Cblockquote>\n\u003Col>\n\u003Cli>As Chrome suggests, change your API calls to use HTTPs (recommended)：將取用資源也改為Https\u003C\u002Fli>\n\u003Cli>Use HTTP instead of HTTPs：網站改為Http\u003C\u002Fli>\n\u003Cli>Add the following meta tag to your \u003Chead> element in your HTML：在head加入以下宣告\u003C\u002Fli>\n\u003C\u002Fol>\n\u003C\u002Fblockquote>\n\u003Cpre>\u003Ccode class=\"language-html\">&lt;meta http-equiv=&quot;Content-Security-Policy&quot; content=&quot;upgrade-insecure-requests&quot;&gt;\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>第二種很明顯在這個年代來說不適合，而第一種因為很難改動Universal viewer的呼叫方式變得很困難執行，雖然是最佳解。於是剩下第三種，直接允許瀏覽器接受混用狀態。\u003C\u002Fp>\n\u003Cp>實作方式有兩種：\u003C\u002Fp>\n\u003Col>\n\u003Cli>在theme的view&gt;layout.phtml中加入標頭\u003C\u002Fli>\n\u003Cli>在theme中的view&gt;universal viewer&gt;play.phtml中加入標頭\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>就看專案中怎麼取用Universal viewer工具囉。\u003C\u002Fp>\n","2022-09-20T12:00:42","",{"name":88,"link":89},[105,106],{"name":33,"slug":34},{"name":57,"slug":57},"\u002Fblog\u002Fomkeas關於資源取用的xmlhttprequest問題",{"id":109,"slug":110,"title":111,"description":112,"content":113,"date":114,"image":102,"imageAlt":111,"author":115,"categories":116,"path":119,"minRead":29},113,"frontend筆記-使用selector尋找父元素的方式parent幾種相關做法","[Frontend]筆記-使用Selector尋找父元素的方式(parent)幾種相關做法","筆記-使用Selector尋找父元素的方式(parent)幾種相關做法 最近有個小需求得回去寫了點jquery […]","\u003Ch1>筆記-使用Selector尋找父元素的方式(parent)幾種相關做法\u003C\u002Fh1>\n\u003Cp>最近有個小需求得回去寫了點jquery，因為很久沒寫，也意外的發現以前沒使用過的一個api。\u003C\u002Fp>\n\u003Cp>通常要透過selector找特定父元素時都會使用\u003Cem>.parent('element')\u003C\u002Fem>吧，但\u003Cem>.parent('element')\u003C\u002Fem>只會往前一層，如果想要繼續往前找，可以使用\u003Cem>.parents('element')\u003C\u002Fem>。\u003Cbr \u002F>\n但\u003Cem>.parents('element')\u003C\u002Fem>會有個特性，會不斷的往前找，把所有符合條件的元素都撈出來。\u003Cbr \u002F>\n如果只想要往前撈到一個特定父元素的話，可以使用\u003Cem>closest()\u003C\u002Fem>，這樣就只會往前找但符合條件就會停止。\u003C\u002Fp>\n\u003Ch2>範例\u003C\u002Fh2>\n\u003Cpre>\u003Ccode class=\"language-html\">&lt;div class=&quot;parnet selected&quot;&gt;\n  Hello Parent\n  &lt;div class=&quot;child selected&quot;&gt;\n    &lt;div&gt;\n      &lt;p&gt;Hello &lt;\u002Fp&gt;\n    &lt;\u002Fdiv&gt;\n  &lt;\u002Fdiv&gt;\n&lt;\u002Fdiv&gt;\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>以上述解釋的話會有以下狀況\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-jquery\">$(&#039;p&#039;).parent(&#039;selected&#039;);\u002F\u002F找到&lt;div class=&quot;child selected&quot;&gt;\n$(&#039;p&#039;).parents(&#039;selected&#039;);\u002F\u002F找到&lt;div class=&quot;child selected&quot;&gt;與&lt;div class=&quot;parnet selected&quot;&gt;\n$(&#039;p&#039;).closest(&#039;selected&#039;);\u002F\u002F找到&lt;div class=&quot;child selected&quot;&gt;\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2>小結\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>parent() 只往上找一層\u003C\u002Fli>\n\u003Cli>closest() 往上找，找到符合條件的就會停止\u003C\u002Fli>\n\u003Cli>parents() 一直往上找，找出所有符合條件的(會丟回陣列)\u003C\u002Fli>\n\u003C\u002Ful>\n","2022-09-10T20:00:53",{"name":88,"link":89},[117,118],{"name":22,"slug":22},{"name":33,"slug":34},"\u002Fblog\u002Ffrontend筆記-使用selector尋找父元素的方式parent幾種相關做法",{"id":121,"slug":122,"title":123,"description":124,"content":125,"date":126,"image":102,"imageAlt":123,"author":127,"categories":128,"path":130,"minRead":29},48,"html在form表單上取得複數相同name的資料","[HTML]在form表單上取得複數相同name的資料","在form表單上取得複數相同name的資料 說來真慚愧，寫了好幾年的網頁現在才遇到這問題。 在HTML中使用f […]","\u003Ch1>在form表單上取得複數相同name的資料\u003C\u002Fh1>\n\u003Cp>說來真慚愧，寫了好幾年的網頁現在才遇到這問題。\u003C\u002Fp>\n\u003Cp>在HTML中使用form來做資料傳遞是很基礎的一個做法，例如像這樣：\u003Cbr \u002F>\n將name以POST方式傳到example.com的api\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-html\">&lt;form action=&quot;http:\u002F\u002Fexample.com&quot; method=&quot;post&quot;&gt;\n    &lt;input name=&quot;name&quot; value=&quot;val&quot;&gt;\n    &lt;input type=&quot;submit&quot;&gt;\n&lt;\u002Fform&gt;\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>在api那邊就可能會取得長得像這樣的JSON\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-json\">{&quot;name&quot;:&quot;val&quot;}\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>基本上一個name對應一個val，遇到欄位有相同的name則會取最後一個值。\u003C\u002Fp>\n\u003Cp>最近專案中有個表單，裡面會有個動態產生資料的需求(如下)\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-html\">&lt;form action=&quot;http:\u002F\u002Fexample.com&quot; method=&quot;post&quot;&gt;\n    &lt;!--名為name的input動態產生--&gt;\n    &lt;input name=&quot;name&quot; value=&quot;val_1&quot;&gt; \n    &lt;input name=&quot;name&quot; value=&quot;val_2&quot;&gt;\n    &lt;input name=&quot;name&quot; value=&quot;val_3&quot;&gt;\n    &lt;input type=&quot;submit&quot;&gt;\n&lt;\u002Fform&gt;\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>照基本做法只會得到最後一個&quot;val_3&quot;，那麼要怎麼做呢？\u003C\u002Fp>\n\u003Ch2>將name陣列化\u003C\u002Fh2>\n\u003Cpre>\u003Ccode class=\"language-html\">&lt;form action=&quot;http:\u002F\u002Fexample.com&quot; method=&quot;post&quot;&gt;\n    &lt;input name=&quot;name[]&quot; value=&quot;val_1&quot;&gt;\n    &lt;input name=&quot;name[]&quot; value=&quot;val_2&quot;&gt;\n    &lt;input name=&quot;name[]&quot; value=&quot;val_3&quot;&gt;\n    &lt;input type=&quot;submit&quot;&gt;\n&lt;\u002Fform&gt;\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>答案很簡單，只要將name命名為陣列就可以，就能取得包起來的陣列囉。\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-json\">{&quot;name&quot;:[&quot;val_1&quot;,&quot;val_2&quot;,&quot;val_3&quot;]}\u003C\u002Fcode>\u003C\u002Fpre>\n","2022-06-10T16:00:36",{"name":88,"link":89},[129],{"name":33,"slug":34},"\u002Fblog\u002Fhtml在form表單上取得複數相同name的資料"]