<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Potchara Pruksasri</title>
    <description>The latest articles on DEV Community by Potchara Pruksasri (@b49dev).</description>
    <link>https://dev.to/b49dev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F904618%2Ffffc67da-12da-4cef-af51-fa6ec596e4b3.jpeg</url>
      <title>DEV Community: Potchara Pruksasri</title>
      <link>https://dev.to/b49dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/b49dev"/>
    <language>en</language>
    <item>
      <title>Java: เพิ่ม Root Cert เพื่อเรียก API SSL ที่มี Cert ของตัวเอง</title>
      <dc:creator>Potchara Pruksasri</dc:creator>
      <pubDate>Sun, 16 Oct 2022 00:55:51 +0000</pubDate>
      <link>https://dev.to/b49dev/java-ephim-root-cert-ephuueeriiyk-api-ssl-thiimii-cert-khngtaweng-3n0c</link>
      <guid>https://dev.to/b49dev/java-ephim-root-cert-ephuueeriiyk-api-ssl-thiimii-cert-khngtaweng-3n0c</guid>
      <description>&lt;p&gt;เวลาเราเขียน Java รันบน Application Server เช่น Tomcat หรือ Glassfish ถ้าเราเรียกหรือทำงานเกี่ยวกับพวก SSL Cert ที่เราสร้างเอง (จาก EJBCA) มันจะ Error ประมาณว่า มันทำ SSL Handcheck กันไม่สำเร็จ &lt;/p&gt;

&lt;p&gt;เพราะว่าใน Java มันก็ต้องมีการใส่ Root CA เพื่อให้ Trust SSL Cert นั้นด้วย เราสามารถแก้ได้ดังนี้&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;เช็คให้ชัวร์ว่า Application Server ของเรารันด้วย Java ในเครื่องเวอร์ชันไหน (ในเครื่องอาจมี Java หลายเวอร์ชัน)&lt;/li&gt;
&lt;li&gt;เข้าไปที่ folder security ของ Java Home เช่น ถ้า Java 11 ใน Windows ก็เข้าที่ C:\Program Files\Java\jdk-11.0.11\lib\security  มันจะมีไฟล์ชื่อ cacerts อยู่&lt;/li&gt;
&lt;li&gt;เอา cert ของเรา (ของเราได้จาก EJBCA เป็น .jks) มา export เป็น .cert โดยใช้โปรแกรม KeyStore Explorer หรือถ้าได้ Cert ของ Root ที่เป็น .DER มาก็ได้ &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--x04mcnjc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hcv3tpe4p523ftg2q0tx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--x04mcnjc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hcv3tpe4p523ftg2q0tx.png" alt="Image description" width="647" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;เพิ่ม cert นั้นเข้า cacerts ของ Java &lt;strong&gt;กำหนด -alias ให้ตรงกับใน .jks ของเราด้วยนะ&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;keytool -import -alias alias -keystore path-to-jre/lib/security/cacerts -file path-to-certificate-file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เช่น&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;keytool -import -alias xxxxxx -keystore "C:\Program Files\Java\jdk-11.0.11\lib\security\cacerts" -file "D:\certs\mycert.cer"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;มันจะมี default password เป็น changeit
&lt;strong&gt;ลองใช้โปรแกรม KeyStore Explorer เปิดเข้าไปดูใน cacerts หรือ ไฟล์ cert ของเราได้&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Maven: สร้างไฟล์ war แบบไม่เอาเวอร์ชันมาด้วย</title>
      <dc:creator>Potchara Pruksasri</dc:creator>
      <pubDate>Fri, 14 Oct 2022 00:44:23 +0000</pubDate>
      <link>https://dev.to/b49dev/maven-sraangaifl-war-aebbaimeaaewrchanmaadwy-15oh</link>
      <guid>https://dev.to/b49dev/maven-sraangaifl-war-aebbaimeaaewrchanmaadwy-15oh</guid>
      <description>&lt;p&gt;อ้างอิง: &lt;a href="https://stackoverflow.com/a/9593611"&gt;https://stackoverflow.com/a/9593611&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;เพิ่มใน pom.xml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;project&amp;gt;
    ...
    &amp;lt;build&amp;gt;
        ...
        &amp;lt;finalName&amp;gt;${project.artifactId}&amp;lt;/finalName&amp;gt;
        ...
    &amp;lt;/build&amp;gt;
    ...
&amp;lt;/project&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Java: Skip checking DataSource</title>
      <dc:creator>Potchara Pruksasri</dc:creator>
      <pubDate>Fri, 14 Oct 2022 00:40:03 +0000</pubDate>
      <link>https://dev.to/b49dev/java-skip-checking-datasource-kh</link>
      <guid>https://dev.to/b49dev/java-skip-checking-datasource-kh</guid>
      <description>&lt;p&gt;ถ้าไม่ต้องการให้ Spring Application ตรวจสอบการเชื่อมต่อฐานข้อมูลตอนเริ่มรันโปรแกรม ให้เพิ่มการตั้งค่านี้ใน  application.properties&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ที่มา: &lt;a href="https://www.baeldung.com/spring-boot-failed-to-configure-data-source"&gt;https://www.baeldung.com/spring-boot-failed-to-configure-data-source&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Go: Deploy Go (Gin) Application on Docker</title>
      <dc:creator>Potchara Pruksasri</dc:creator>
      <pubDate>Wed, 14 Sep 2022 00:28:10 +0000</pubDate>
      <link>https://dev.to/b49dev/go-deploy-go-gin-application-on-docker-5g4</link>
      <guid>https://dev.to/b49dev/go-deploy-go-gin-application-on-docker-5g4</guid>
      <description>&lt;p&gt;ตัวอย่างกันลืมของ Dockerfile ที่เอาไว้ Deploy Go Application โดยการ Clone จาก Private github ไปบน Docker (Portainer)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM golang

WORKDIR /app

RUN git clone -b develop https://&amp;lt;username&amp;gt;:&amp;lt;token&amp;gt;@github.com/&amp;lt;username&amp;gt;/&amp;lt;gitrepo&amp;gt;.git .

RUN go mod download

ENV GIN_MODE=release

COPY ./ ./

RUN go install github.com/cosmtrek/air@latest

# Don't forget to add .air.toml .gitignore
RUN air init

EXPOSE 8888

CMD ["air"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Flutter: Call Restful API (Provider+Retrofit)</title>
      <dc:creator>Potchara Pruksasri</dc:creator>
      <pubDate>Mon, 05 Sep 2022 13:48:43 +0000</pubDate>
      <link>https://dev.to/b49dev/flutter-call-restful-api-providerretrofit-gb7</link>
      <guid>https://dev.to/b49dev/flutter-call-restful-api-providerretrofit-gb7</guid>
      <description>&lt;h2&gt;
  
  
  สร้าง Project
&lt;/h2&gt;

&lt;p&gt;เริ่มต้นสร้าง Flutter project ชื่อ tripbooking (project ตัวอย่าง) กันก่อนเลย โดยการรันคำสั่งสร้าง project และเปิด vscode ที่ folder นั้น&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flutter create tripbooking
cd tripbooking
code .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;สร้าง folder ที่จะเอาไว้เก็บไฟล์ต่างๆให้เป็นระเบียบ โดยในที่นี่ขึ้นอยู่กับความเหมาะสม สำหรับที่จะแนะนำให้สร้าง folder ทั้งหมด 3 folder คือ&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;page = เอาไว้เก็บหน้าต่างๆ ของ application&lt;/li&gt;
&lt;li&gt;service = ส่วนประมวลผลเรียก Api&lt;/li&gt;
&lt;li&gt;model = สำหรับเก็บ database model&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4sazty0tlkvbacdug26d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4sazty0tlkvbacdug26d.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;เพิ่ม libraries ที่เกี่ยวข้องกับ project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flutter pub add retrofit
flutter pub add retrofit_generator
flutter pub add json_serializable
flutter pub add build_runner --dev
flutter pub add dio
flutter pub add provider
flutter pub add get
flutter pub add get_storage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  สร้าง Provider ไว้จัดการข้อมูลที่ใช้ใน Application
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;สร้าง Folder ย่อยชื่อ provider ภายใน folder service &lt;/li&gt;
&lt;li&gt;สร้างไฟล์ของ provider ชื่อ appdata.dart&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ในไฟล์ appdata.dart สร้างตัวแปล baseUrl ของ api ที่ application เราต้องติดต่อ ตามตัวอย่าง&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:flutter/material.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppData&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;ChangeNotifier&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;//Api baseurl&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;baseurl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"http://192.168.1.100:8888"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ไปที่ main.dart แก้ Code ใน main() เพื่อใช้งาน provider ที่สร้างขึ้น&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;runApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MultiProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;providers:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;ChangeNotifierProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;create:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AppData&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MyApp&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เรียบร้อยเรามี provider ไว้ใช้งานใน application เราแล้ว&lt;/p&gt;




&lt;h2&gt;
  
  
  สร้าง RestClient โดยใช้ Retrofit
&lt;/h2&gt;

&lt;p&gt;ตัวเรียก api ในที่นี้เราจะเรียกว่า service เป็นไฟล์ที่เก็บใน folder service ซึ่งเราจะแยกตาม path (url) ของ restful api เช่น จะเรียกใช้งาน api ที่มี path เป็น /destination เราก็จะสร้างไฟล์ชื่อ destination.dart&lt;/p&gt;

&lt;p&gt;สร้างไฟล์ destination.dart ใน folder service&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:retrofit/retrofit.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:dio/dio.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:tripbooking/model/destination.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;part&lt;/span&gt; &lt;span class="s"&gt;'destination.g.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@RestApi&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DestinationService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;factory&lt;/span&gt; &lt;span class="n"&gt;DestinationService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Dio&lt;/span&gt; &lt;span class="n"&gt;dio&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_DestinationService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;ซึ่งเมื่อพิมพ์คำสั่งเสร็จแล้วมันจะ Error ซึ่งถูกแล้ว&lt;/strong&gt; เพราะว่า Retrofit ต้องมีการ generate คำสั่งใหม่ของมัน (&lt;a href="https://pub.dev/packages/retrofit" rel="noopener noreferrer"&gt;https://pub.dev/packages/retrofit&lt;/a&gt;) เป็นไฟล์ชื่อ destination.g.dart ตามที่เราระบุ &lt;/p&gt;

&lt;p&gt;เปิด terminal แล้วพิมพ์คำสั่งให้ retrofit generate ไฟล์&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flutter pub run build_runner watch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;มันจะ generate ไฟล์แล้วเปิดค้างรอ ถ้าเราแก้ไขไฟล์มันก็จะ auto generate ใหม่ ถ้าจะยกเลิก ก็กด Ctrl+C หรือเราสามารถ ใช้คำสั่ง flutter pub run build_runner build (ใช้ option build) ก็ได้ มันจะ generate ครั้งเดียว ถ้าแก้ไฟล์ ต้องมาสั่ง generate ใหม่เอง&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F11g6xjxcjwqxywd9npq6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F11g6xjxcjwqxywd9npq6.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ไฟล์ที่ generate ขึ้นเราไม่แก้ไขมัน เพราะมันจะถูกลบแล้วถูกสร้างใหม่ตลอด&lt;/p&gt;

&lt;p&gt;ตอนนี้จะมี Retrofit client (service) ที่ใช้ติดต่อไปยัง api แล้ว ต่อไปจะเป็นการสร้าง method ในการเรียก api แต่จะเรียก api ได้ ต้องมี model มารับข้อมูลที่ได้คืนมาจาก api ด้วยด้วย ดังนั้น ต้องสร้าง model ก่อน&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;สร้างไฟล์ destination.dart ใน folder model&lt;/li&gt;
&lt;li&gt;เข้าเวบ &lt;a href="https://app.quicktype.io" rel="noopener noreferrer"&gt;https://app.quicktype.io&lt;/a&gt; แล้วก็เอา json ที่ได้จาก api มาวางเพื่อให้เวบมันสร้าง class ของ dart ให้ตามรูปตัวอย่าง&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9lyqx236yz1hqqu4tvts.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9lyqx236yz1hqqu4tvts.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ตั้งชื่อ class เป็น Destination (เพราะเป็นข้อมูลที่ได้จากการเรียก api destination)&lt;/li&gt;
&lt;li&gt;วาง json ได้มา ลงไป&lt;/li&gt;
&lt;li&gt;เลือกภาษาเป็น Dart&lt;/li&gt;
&lt;li&gt;เลือกตัวเลือกแค่ตัวเดียวคือ Make all properties required&lt;/li&gt;
&lt;li&gt;กด copy code&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;กลับไปที่ไฟล์ destination.dart ใน model แล้ววาง code ลงไป แต่ใน flutter จะ Error เพราะ @required ให้ลง @ ออก&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6frpeern4a97fqsuyy2z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6frpeern4a97fqsuyy2z.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0avu06e4zvichl9kst2v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0avu06e4zvichl9kst2v.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ตอนนี้ เราก็จะมี model ไว้รับข้อมูลจาก api แล้ว&lt;/p&gt;

&lt;p&gt;กลับไปที่ไฟล์ destination.dart ใน folder service (retrofit) แล้วเขียน คำสั่งเพิ่มเพื่อสร้าง method ในการเรียก api&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DestinationService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;factory&lt;/span&gt; &lt;span class="n"&gt;DestinationService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Dio&lt;/span&gt; &lt;span class="n"&gt;dio&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_DestinationService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nd"&gt;@GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/destination"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Destination&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;getDestinations&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;จะเป็นการเรียกไปยัง path /destination และจะได้ผลลัพธ์ออกมาเป็น List ของ Destination (mode ที่เราเพิ่งสร้าง) นั่นเอง เมื่อ save ตัว retrofit จะ generate ไฟล์ให้ (ถ้าเรายังสั่งเป็น watch อยู่) หรือสั่ง build เพื่อ generate ใหม่อีกครั้ง&lt;/p&gt;

&lt;p&gt;เรียบร้อย เราสร้างตัว service ที่เอาไว้เรียก api ได้แล้ว&lt;/p&gt;

&lt;p&gt;อ่านเพิ่มเติมรูปแบบการใช้ retrofit ที่ (&lt;a href="https://pub.dev/packages/retrofit" rel="noopener noreferrer"&gt;https://pub.dev/packages/retrofit&lt;/a&gt;)&lt;/p&gt;




&lt;h2&gt;
  
  
  เรียกใช้งาน service ที่เราสร้าง
&lt;/h2&gt;

&lt;p&gt;ตัวอย่างเช่น เราสร้างหน้า home.dart ใน folder page ในรูปแบบ FutureBuilder&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'dart:convert'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'dart:developer'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:dio/dio.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:flutter/material.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:tripbooking/model/destination.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:tripbooking/service/destination.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:provider/provider.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:tripbooking/service/provider/appdata.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HomePage&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatefulWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;HomePage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;HomePage&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;createState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_HomePageState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_HomePageState&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;HomePage&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// 1. กำหนดตัวแปร&lt;/span&gt;
  &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Destination&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;destinations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="kd"&gt;late&lt;/span&gt; &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;loadDataMethod&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;late&lt;/span&gt; &lt;span class="n"&gt;DestinationService&lt;/span&gt; &lt;span class="n"&gt;destinationService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// 2. สร้าง initState เพื่อสร้าง object ของ service &lt;/span&gt;
  &lt;span class="c1"&gt;// และ async method ที่จะใช้กับ FutureBuilder&lt;/span&gt;
  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;initState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="c1"&gt;// 2.1 object ของ service โดยต้องส่ง baseUrl (จาก provider) เข้าไปด้วย&lt;/span&gt;
    &lt;span class="n"&gt;destinationService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
        &lt;span class="n"&gt;DestinationService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Dio&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nl"&gt;baseUrl:&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;read&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AppData&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;baseurl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
  &lt;span class="c1"&gt;// 2.2 async method&lt;/span&gt;
    &lt;span class="n"&gt;loadDataMethod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;loadData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;appBar:&lt;/span&gt; &lt;span class="n"&gt;AppBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;title:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Home Page'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="c1"&gt;// 3. เรียก service ในรูปแบบของ FutureBuilder (หรือจะไม่ใช้ก็ได้ แค่ตัวอย่างให้ดูเฉยๆ)&lt;/span&gt;
      &lt;span class="nl"&gt;body:&lt;/span&gt; &lt;span class="n"&gt;FutureBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;future:&lt;/span&gt; &lt;span class="n"&gt;loadDataMethod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 3.1 object ของ async method&lt;/span&gt;
          &lt;span class="nl"&gt;builder:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;snapshot&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;connectionState&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;ConnectionState&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;done&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Center&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jsonEncode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;destinations&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Center&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;CircularProgressIndicator&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// 4. Async method ที่เรียก service เมื่อได้ข้อมูลก็เอาไปเก็บไว้ที่ destinations ที่ประกาศไว้ด้านบนเป็น List&lt;/span&gt;
  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;loadData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;destinations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;destinationService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDestinations&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Error: &lt;/span&gt;&lt;span class="si"&gt;$err&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เท่านี้ เราก็เรียกใช้ service ได้อย่างง่ายๆ &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;แต่ปัญหาคือต้องฝึกดูเวลามันผิดพลาด เกิด Error ตอนเรียก service มันจะต้องใช้ try catch จับ ตามตัวอย่าง&lt;/strong&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>GO: Database Restful API (GIN+GORM)</title>
      <dc:creator>Potchara Pruksasri</dc:creator>
      <pubDate>Sun, 04 Sep 2022 11:20:07 +0000</pubDate>
      <link>https://dev.to/b49dev/go-database-restful-api-gingorm-1ad7</link>
      <guid>https://dev.to/b49dev/go-database-restful-api-gingorm-1ad7</guid>
      <description>&lt;h2&gt;
  
  
  สร้าง Project
&lt;/h2&gt;

&lt;p&gt;เริ่มต้นสร้าง Go project ชื่อ tripbooking (project ตัวอย่าง) กันก่อนเลย โดยสร้าง folder ชื่อ tripbooking  แล้วเข้าไป folder รันคำสั่งสร้าง project และเปิด vscode ที่ folder นั้น&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir tripbooking 
cd tripbooking 
go mod init tripbooking 
code .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;สร้าง folder ที่จะเอาไว้เก็บไฟล์ต่างๆให้เป็นระเบียบ โดยในที่นี่ขึ้นอยู่กับความเหมาะสม สำหรับที่จะแนะนำให้สร้าง folder ทั้งหมด 4 folder คือ &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;controller = เอาไว้เก็บ restful api controller (path) ต่างๆ&lt;/li&gt;
&lt;li&gt;service = ส่วนประมวลผลต่างๆของ Api&lt;/li&gt;
&lt;li&gt;model = struct ของ database model &lt;/li&gt;
&lt;li&gt;repository = ส่วนที่เชื่อมต่อไปยัง database&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;และสร้างไฟล์อีก 3 ไฟล์คือ&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;config.yaml = ไฟล์การตั้งค่าต่างๆของ project&lt;/li&gt;
&lt;li&gt;server.go = ไฟล์เริ่มต้นการทำงานของ Server โดย GIN&lt;/li&gt;
&lt;li&gt;main.go = ไฟล์เริ่มต้นการทำงานของ project&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;โดยใน main.go ก็จะมี code ของ func main() เริ่มต้น ตามรูป&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--apyzypFT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9rkzwqqqrljp78s3ptcn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--apyzypFT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9rkzwqqqrljp78s3ptcn.png" alt="Image description" width="536" height="319"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;เพิ่ม libraries ที่เกี่ยวข้องกับ project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go get github.com/gin-gonic/gin
go get gorm.io/gorm
go get gorm.io/driver/mysql
go get github.com/spf13/viper
go install github.com/cosmtrek/air@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  สร้าง Server ด้วย GIN
&lt;/h2&gt;

&lt;p&gt;ที่ไฟล์ server.go สร้าง server ของ restful api ด้วย GIN&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/gin-gonic/gin"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;StartServer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;router&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetTrustedProxies&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PORT"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"8888"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusOK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;"message"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Hello World!!!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ใน main.go สั่งให้เรียก func StartServer()&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;StartServer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;รันโปรแกรมด้วย plugin air เพื่อให้ auto reload เมื่อเราแก้ไข code โดยต้องกำหนดค่าเริ่มต้นให้ก่อน&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;air init
air
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ทดสอบเรียก Api อาจใช้ Thunder Client, Talend หรือ Postman ก็ได้&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lXq7F79K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w10mwk579c9t6pe396r1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lXq7F79K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w10mwk579c9t6pe396r1.png" alt="Image description" width="654" height="423"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ติดต่อ Database ด้วย GORM
&lt;/h2&gt;

&lt;p&gt;ตั้งค่า dsn ที่จะเชื่อมไปยังฐานข้อมูล MySQL ในไฟล์ config.yaml (อย่าลืมเปิด Server MySQL ตัวอย่างล่ะ หรือ ถ้าเชื่อมไปยัง Server ที่ Online อยู่ก็ได้เลย)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;mysql&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;dsn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;username:password@tcp(localhost:3306)/tripbooking?collation=utf8mb4_unicode_ci&amp;amp;parseTime=true"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;จากนั้น สร้างไฟล์ database.go ใน folder repository แล้วเขียนคำสั่งใช้การติดต่อไปยังฐานข้อมูล&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;


&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/spf13/viper"&lt;/span&gt;
    &lt;span class="s"&gt;"gorm.io/driver/mysql"&lt;/span&gt;
    &lt;span class="s"&gt;"gorm.io/gorm"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gorm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DB&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;NewDatabaseConnection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gorm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;viper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetConfigName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"config"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;viper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddConfigPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;viper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadInConfig&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;dsn&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;viper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"mysql.dsn"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;dialector&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dsn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gorm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dialector&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ซึ่งได้จะ func NewDatabaseConnection() ไว้ใช้ในการติดต่อไปยังฐานข้อมูลที่เราได้ตั้งค่าไว้&lt;/p&gt;




&lt;p&gt;ติดต่อไปดึงข้อมูลจากฐานข้อมูล (Table) ต้องมี Model (Entity) ที่เป็นตัวแทนของ Table นั้นๆ ตัวอย่างเช่น จะดึงข้อมูลจาก Table destination ก็ต้องสร้าง Model Destination ขี้นมาก่อน&lt;/p&gt;

&lt;p&gt;สร้างไฟล์ destinationModel.go ใน folder model และเขียน model ตามโครงสร้างของ table destination&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Destination&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ID&lt;/span&gt;   &lt;span class="kt"&gt;uint&lt;/span&gt;   &lt;span class="s"&gt;`gorm:"column:idx;primaryKey"`&lt;/span&gt;
    &lt;span class="n"&gt;Zone&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`gorm:"column:zone;size:255"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Destination&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;TableName&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"destination"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ในกรณีที่ไม่อยากเขียน struct ของ model เอง ให้ใช้วิธีนี้คือ&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;เข้า phpmyadmin แล้วรันคำสั่ง (destination คือชื่อ table ที่ต้องการ) โดยเลือกการแสดงผลตรง option ให้เป็น แบบ Full Text
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SHOW CREATE TABLE destination
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--a_5QXl-d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4cd1kfch1d8detju66yb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--a_5QXl-d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4cd1kfch1d8detju66yb.png" alt="Image description" width="802" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;จะได้คำสั่งสร้าง Table ออกมา ให้ copy คำสั่ง Create นั้นไว้ แล้วเข้าที่เวบ &lt;a href="https://sql2gorm.mccode.info"&gt;https://sql2gorm.mccode.info&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;วางคำสั่ง sql ลงไป เวบจะสร้าง struct ของ model ให้ตามรูป (เลือก json tag เป็น include ด้วยนะ ถ้าจะใช้เป็น DTO รับข้อมูลรูปแบบ json)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MsafO-Jw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l0gdev0hqgzpg4xme4el.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MsafO-Jw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l0gdev0hqgzpg4xme4el.png" alt="Image description" width="880" height="386"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;สร้าง Repositoy ที่เป็นตัวเชื่อมไปยังฐานข้อมูล โดยในการเขียนนี้ เราจะสร้างให้อยู่ในรูปแบบ Interface (ถ้ายังไม่รู้จักจะงงๆหน่อยนะ) เพื่อให้สะดวกต่อการใช้งาน อาจดูยุ่งยาก แต่มันดีในอนาคตเวลาโปรแกรมมันขยายและซับซ้อนขึ้น&lt;/p&gt;

&lt;p&gt;สร้างไฟล์ destinationRepository.go ไว้ใน folder repository และเขียนให้ไปดึงข้อมูลของ table destination มา (FindAll) โดยมี pattern ของการเขียนดังตัวอย่าง&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"tripbooking/model"&lt;/span&gt;

    &lt;span class="s"&gt;"gorm.io/gorm"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// repository struct (&amp;lt;name&amp;gt;DB)&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;destinationRepo&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gorm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DB&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// repository contructor (New&amp;lt;name&amp;gt;Repository)&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;NewDestinationRepository&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;DestinationRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;NewDatabaseConnection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;destinationRepo&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// repository interface (&amp;lt;name&amp;gt;Repository)&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;DestinationRepository&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;FindAll&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Destination&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// implement functions conformed interface&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="n"&gt;destinationRepo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;FindAll&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Destination&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;destinations&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Destination&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;destinations&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;destinations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;เมื่อสร้าง Repository เสร็จแล้ว ขี้นต่อไปคือการสร้าง Service เพื่อใช้ประมวลผลต่างๆ &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;เราจะไม่ประมวลใน repository และ controller ถ้าไม่จำเป็น&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;สร้างไฟล์ destinationService.go ใน folder service เพื่อใช้เขียนการประมวลผลในรูปแบบของ service ซึ่งจะมี pattern การเขียนแบบ interface  เหมือน repository&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"tripbooking/model"&lt;/span&gt;
    &lt;span class="s"&gt;"tripbooking/repository"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// service struct (&amp;lt;name&amp;gt;Serv)&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;destinationServ&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="c"&gt;// service contructor (New&amp;lt;name&amp;gt;Service)&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;NewDestinationService&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;DestinationService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;destinationServ&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// create repositories&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;destinationRepo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDestinationRepository&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c"&gt;// service interface (&amp;lt;name&amp;gt;Service)&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;DestinationService&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;GetAllDestinations&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Destination&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="n"&gt;destinationServ&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetAllDestinations&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Destination&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="n"&gt;destinations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;destinationRepo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FindAll&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;destinations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;เมื่อได้ส่วนประมวลผลแล้ว ต่อไปจะทำการสร้าง controller เพื่อให้ user สามารถเรียกใช้งาน api เราได้ โดยสร้างไฟล์ destinationController.go ใน folder controller แล้วเขียนเรียกใช้งาน service ดังตัวอย่าง&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;controller&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
    &lt;span class="s"&gt;"tripbooking/service"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/gin-gonic/gin"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// create services&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;destinationServ&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDestinationService&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c"&gt;// Initiate Controller&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;NewDestinationController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;router&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/destination"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;findAll&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Implement Controller&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;findAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;destinations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;destinationServ&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetAllDestinations&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusBadRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;"error"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusOK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;destinations&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;เมื่อได้ controller แล้ว ต่อไป จะเป็นการผูก Controller เข้าไปยัง Server ที่เราสร้าง &lt;/p&gt;

&lt;p&gt;มาที่ไฟล์ server.go และเพิ่ม (Register) Controller ของเราเข้าไป ตาม code ตัวอย่าง&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;StartServer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;router&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetTrustedProxies&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PORT"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"8888"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// **** Register controllers&lt;/span&gt;
    &lt;span class="n"&gt;controller&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDestinationController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;จากนั้นทดลองเรียก api โดยใช้ /destination จะได้ผลลัพธ์ตามตัวอย่าง&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2Zmft_QQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/50fmcl4i151rk9tpmiai.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2Zmft_QQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/50fmcl4i151rk9tpmiai.png" alt="Image description" width="615" height="512"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;เสร็จสิ้นการเริ่มต้น GO Project ในการสร้าง Restful api เชื่อมต่อไปยัง MySQL ด้วย GIN และ GORM&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Flutter Fix: flutter_tags type 'Null' is not a subtype of type 'DataList' in type cast</title>
      <dc:creator>Potchara Pruksasri</dc:creator>
      <pubDate>Wed, 31 Aug 2022 16:27:24 +0000</pubDate>
      <link>https://dev.to/b49dev/fix-fluttertags-type-null-is-not-a-subtype-of-type-datalist-in-type-cast-16pp</link>
      <guid>https://dev.to/b49dev/fix-fluttertags-type-null-is-not-a-subtype-of-type-datalist-in-type-cast-16pp</guid>
      <description>&lt;p&gt;&lt;a href="https://pub.dev/packages/flutter_tags"&gt;https://pub.dev/packages/flutter_tags&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/Dn-a/flutter_tags/issues/79"&gt;https://github.com/Dn-a/flutter_tags/issues/79&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Flutter Fix: flutter_facebook_auth 4+ No implementation found</title>
      <dc:creator>Potchara Pruksasri</dc:creator>
      <pubDate>Mon, 29 Aug 2022 18:01:00 +0000</pubDate>
      <link>https://dev.to/b49dev/fix-flutterfacebookauth-4-no-implementation-found-3p8c</link>
      <guid>https://dev.to/b49dev/fix-flutterfacebookauth-4-no-implementation-found-3p8c</guid>
      <description>&lt;p&gt;MUST HAVE!!!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Y-dGuGOz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nuqtl6ifzwwcaatziazs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Y-dGuGOz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nuqtl6ifzwwcaatziazs.png" alt="Image description" width="880" height="607"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Fvd4NjRK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2d6qb6mllargg59gx3y5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Fvd4NjRK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2d6qb6mllargg59gx3y5.png" alt="Image description" width="880" height="729"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YIoJ0Fhq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y72ebktewjv4qgqhkcpq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YIoJ0Fhq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y72ebktewjv4qgqhkcpq.png" alt="Image description" width="880" height="98"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gMv6Kgw6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5o8zpbb4lyul7ym60mlo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gMv6Kgw6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5o8zpbb4lyul7ym60mlo.png" alt="Image description" width="856" height="262"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PBaCSkJT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g0yfzv8n6z34359gx4b4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PBaCSkJT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g0yfzv8n6z34359gx4b4.png" alt="Image description" width="567" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E9Qh6AHr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dqxlrx7arem8d3u0z5sk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E9Qh6AHr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dqxlrx7arem8d3u0z5sk.png" alt="Image description" width="880" height="504"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Flutter: Facebook Login โดยไม่ต้องผ่าน Firebase</title>
      <dc:creator>Potchara Pruksasri</dc:creator>
      <pubDate>Mon, 29 Aug 2022 16:12:34 +0000</pubDate>
      <link>https://dev.to/b49dev/flutter-facebook-login-odyaimtngphaan-firebase-48f7</link>
      <guid>https://dev.to/b49dev/flutter-facebook-login-odyaimtngphaan-firebase-48f7</guid>
      <description>&lt;p&gt;เขียน Flutter ให้ Login ด้วย Facebook โดยไม่ต้องผ่าน Firebase แบ่งออกเป็น 3 ขั้นตอน&lt;/p&gt;

&lt;h2&gt;
  
  
  สร้างและตั้งค่า Facebook App ก่อน
&lt;/h2&gt;

&lt;p&gt;ขั้นที่ 1. เข้า &lt;a href="https://developers.facebook.com/" rel="noopener noreferrer"&gt;https://developers.facebook.com/&lt;/a&gt; โดยใช้ Account facebook ของเราเอง&lt;/p&gt;

&lt;p&gt;ขั้นที่ 2. เลือก MyApp แล้วก็ Create App&lt;/p&gt;

&lt;p&gt;ขั้นที่ 3. เลือก app type เป็น Consumer&lt;/p&gt;

&lt;p&gt;ขั้นที่ 4. ตั้งชื่อ App อะไรก็ได้ ใส่ Email แล้วกด Create App ระบบจะถาม Password ของ facebook ก็ใส่แล้วกด submit &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft6blygeu2vhiq8temj0x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft6blygeu2vhiq8temj0x.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;จะได้ App ตามตัวอย่างข้างล่าง&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5biasisn2md9adhcacfw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5biasisn2md9adhcacfw.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ขั้นที่ 5. กด Set up ที่ Facebook Login แล้วเลือก Android (กรณีที่เป็น Android app)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fobde3g0dqvy2eqx2l2uy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fobde3g0dqvy2eqx2l2uy.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ขั้นที่ 6. ตั้งค่าสำหรับ Android app กด Next ไปถึง &lt;strong&gt;Step 3&lt;/strong&gt; เลย&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ขั้นที่ 6.1. Package Name ให้ใส่ package name ของ app โดยไปที่ไฟล์ android/app/src/build.gradle&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ขั้นที่ 6.2. Default Activity ก็ใส่ package name ตามข้างบนแล้วตามด้วย .MainActivity&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9h8x1k5q4suh0yncx67k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9h8x1k5q4suh0yncx67k.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ขั้นที่ 7. ที่ &lt;strong&gt;Step 4&lt;/strong&gt; ต้องสร้าง Key hash ของเครื่องที่เขียนโปรแกรม Android นั้นๆ &lt;strong&gt;ต้องทำทุกเครื่องที่ใช้ Build application ถ้าเป็นเครื่อง Build ก็ต้องทำใหม่&lt;/strong&gt;&lt;br&gt;
** หรือ ใช้ package &lt;a href="https://pub.dev/packages/flutter_facebook_keyhash" rel="noopener noreferrer"&gt;https://pub.dev/packages/flutter_facebook_keyhash&lt;/a&gt; ช่วยในการหา key hash **&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ขั้นที่ 7.1. ใช้โปรแกรม openssl ในการรัน ถ้าเครื่องไม่มี openssl ก็ให้ดาวน์โหลดจาก &lt;a href="https://code.google.com/archive/p/openssl-for-windows/downloads" rel="noopener noreferrer"&gt;https://code.google.com/archive/p/openssl-for-windows/downloads&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ขั้นที่ 7.2. รันคำสั่ง โดยต้องเปลี่ยน C:\Users\USERNAME เป็น path ของ user ในเครื่อง windows และ PATH_TO_OPENSSL_LIBRARY เป็น path ที่เก็บโปรแกรม openssl ที่แตก zip ไว้&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;keytool -exportcert -alias androiddebugkey -keystore "C:\Users\USERNAME\.android\debug.keystore" | "PATH_TO_OPENSSL_LIBRARY\bin\openssl" sha1 -binary | "PATH_TO_OPENSSL_LIBRARY\bin\openssl" base64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ขั้นที่ 7.3. มันถาม password ให้ใส่เป็น "android" แล้วจะได้ Key hash ออกมา&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxwh0ywkio17o4mwegg7d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxwh0ywkio17o4mwegg7d.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ขั้นที่ 7.4. Copy Key hash ไปใส่ในช่องของ Step 4&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;ถ้ามันถูกต้องมันต้องมีเป็นข้อความ &lt;strong&gt;Warning&lt;/strong&gt; ออกมา ถ้ามันเป็น keyhash ออกมาเลย แบบนั้นอาจไม่ได้เพราะว่าตัว debug.keystore มันไม่ได้มี password (default) เป็น android ถ้าเอา keyhash ไปใช้แล้ว มันจะไม่สามารถ login กับ facebook account อื่นได้ มันจะได้แต่กับ facebook ตัวเอง&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;ขั้นที่ 8. ข้าม Step 5 ไปที่ Step 6 ต้องไปเพิ่มที่ Android app&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ขั้นที่ 8.1. ไปที่ folder android/app/src/main/res/values (ใน flutter จะไม่เหมือนที่แสดงในเวบ facebook นะ)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ขั้นที่ 8.2. สร้างไฟล์ชื่อ *&lt;em&gt;strings.xml *&lt;/em&gt;แล้วเพิ่ม code โดยใส่ FACEBOK_APPNAME และ FACEBOK_APPID&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;resources&amp;gt;
&amp;lt;string name="app_name"&amp;gt;FACEBOK_APPNAME&amp;lt;/string&amp;gt;    
&amp;lt;string name="facebook_app_id"&amp;gt;FACEBOK_APPID&amp;lt;/string&amp;gt;
&amp;lt;string name="fb_login_protocol_scheme"&amp;gt;fbFACEBOK_APPID&amp;lt;/string&amp;gt;
&amp;lt;string name="facebook_client_token"&amp;gt;FACEBOOK_CLIENT_TOKEN&amp;lt;/string&amp;gt;
&amp;lt;/resources&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;ขั้นที่ 8.3. ไปที่ไฟล์ android/app/src/main/AndroidManifest.xml เพิ่ม Code อนุญาตการเชื่อมต่ออินเทอร์เข้าไป &lt;strong&gt;ก่อน tag Application&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;uses-permission android:name="android.permission.INTERNET"/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;ขั้นที่ 8.4. เพิ่ม Code เข้าไป &lt;strong&gt;ใน tag Application&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/&amp;gt;
&amp;lt;meta-data android:name="com.facebook.sdk.ClientToken" android:value="@string/facebook_client_token"/&amp;gt;
&amp;lt;activity android:name="com.facebook.FacebookActivity"
android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:label="@string/app_name" /&amp;gt;
&amp;lt;activity
android:name="com.facebook.CustomTabActivity"
android:exported="true"&amp;gt;
&amp;lt;intent-filter&amp;gt;
   &amp;lt;action android:name="android.intent.action.VIEW" /&amp;gt;
   &amp;lt;category android:name="android.intent.category.DEFAULT" /&amp;gt;
   &amp;lt;category android:name="android.intent.category.BROWSABLE" /&amp;gt;
   &amp;lt;data android:scheme="@string/fb_login_protocol_scheme" /&amp;gt;
&amp;lt;/intent-filter&amp;gt;
&amp;lt;/activity&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;ขั้นที่ 9. กด Next ไปเรื่อยๆ เสร็จสิ้นการตั้งค่าใน Facebook App (ช่วงแรก)&lt;/p&gt;
&lt;h2&gt;
  
  
  ติดตั้งและใช้ Flutter plugin
&lt;/h2&gt;

&lt;p&gt;ขั้นที่ 1. ติดตั้ง package &lt;a href="https://pub.dev/packages/flutter_facebook_auth" rel="noopener noreferrer"&gt;https://pub.dev/packages/flutter_facebook_auth &lt;/a&gt;(คู่มือ facebook.meedu.app)&lt;/p&gt;

&lt;p&gt;ขั้นที่ 2. &lt;strong&gt;ถ้ารัน Flutter อยู่ต้อง Stop Flutter ก่อนแล้ว Build ใหม่&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ขั้นที่ 3. import library ในหน้าที่จะเขียนเชื่อมต่อกับ facebook api&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ขั้นที่ 4. เขียน Code ในปุ่มเพื่อเรียกการ login&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;final LoginResult result = await FacebookAuth.instance.login(); // by default we request the email and the public profile
// or FacebookAuth.i.login()
if (result.status == LoginStatus.success) {
 // you are logged
 final AccessToken accessToken = result.accessToken!;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ขั้นที่ 5. ถ้าสำเร็จจะได้ accressToken กลับมา &lt;strong&gt;แต่ตอนนี้จะใช้ได้แค่ Account facebook ที่เป็น account ที่สร้าง Facebook app เท่านั้น&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ขั้นที่ 6. ใช้คำสั่ง เพื่อเรียกข้อมูล User (ค่า default จะเป็น public_profile, email)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;final userData = await FacebookAuth.instance.getUserData();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "email" = "dsmr.apps@gmail.com",
  "id" = 3003332493073668,
  "name" = "Darwin Morocho",
  "picture" = {
      "data" = {
          "height" = 50,
          "is_silhouette" = 0,
          "url" = "https://platform-lookaside.fbsbx.com/platform/profilepic/?asid=3003332493073668",
          "width" = 50,
      },
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  เปิด Mode ของ Facebook App เป็น Live Mode เพื่อให้ใช้งาน Login กับ Facebook Account อื่นได้
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;ถ้าไม่เปิดจะใช้งานได้แค่ Facebook Account ของ Dev คนนั้นเท่านั้น&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ขั้นที่ 1. การเปิด Live mode ของ Facebook ต้องมีการใส่ privacy policy ด้วย ซึ่งเราอาจจะไปสร้างได้จากเวบของไทย &lt;a href="//pdpa.pro"&gt;pdpa.pro&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ขั้นที่ 2. เลือก สร้าง Policy&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqk6lhyhfuae6x9v3cuar.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqk6lhyhfuae6x9v3cuar.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ขั้นที่ 3. เลือก Privacy Policy, ยอมรับเงื่อนไข, กดยืนยันการเลือก&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgt89toxqlnqgrnky1m1i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgt89toxqlnqgrnky1m1i.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ขั้นที่ 4. กรอก email แล้วกด เริ่มสร้าง&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2dtqmarkufy8fzk6rkfs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2dtqmarkufy8fzk6rkfs.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ขั้นที่ 4. กรอกชื่อแอปภาษาไทย ภาษาอังกฤษ เลือกไทย แล้วกดถัดไป&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ks5woloqsoqwt3y2qg5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ks5woloqsoqwt3y2qg5.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ขั้นที่ 5. เลือก Facebook login แล้วกดถัดไป&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcr72uva4vryvbubf90rg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcr72uva4vryvbubf90rg.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ขั้นที่ 6. เลือกตามภาพ&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9zp3bsei08t7vi8vxbmw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9zp3bsei08t7vi8vxbmw.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc2isfuvw9ttrlueol54z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc2isfuvw9ttrlueol54z.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcnms5wrl285rfbpiuzis.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcnms5wrl285rfbpiuzis.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fastuhkcrq5l3j6z49ev1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fastuhkcrq5l3j6z49ev1.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6o365ls46y4qfforjd6c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6o365ls46y4qfforjd6c.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffx6npv966idycij8avv2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffx6npv966idycij8avv2.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2nvsy4cubflzorohi2g4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2nvsy4cubflzorohi2g4.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3w0ioxd6upzupkj5tb7r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3w0ioxd6upzupkj5tb7r.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ขั้นที่ 7. บันทึกข้อมูล และกดรับ Policy&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fohjzle3a7c31v129vpc2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fohjzle3a7c31v129vpc2.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ขั้นที่ 8. ระบบจะส่งเมล์เข้าไปยังเมล์ที่เรากรอกไว้&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuywdn25m2bzw554m4i9t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuywdn25m2bzw554m4i9t.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ขั้นที่ 9. เข้าเมล์แล้วกดยืนยันอีเมล์&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8tixm1i1axn3ags9cm1h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8tixm1i1axn3ags9cm1h.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ขั้นที่ 10. ตั้งรหัสและเข้าระบบ &lt;strong&gt;จะเห็น policy ให้ copy url มา&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgdmm8ixkommk51vkp0cn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgdmm8ixkommk51vkp0cn.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ขั้นที่ 11. &lt;strong&gt;กลับไปที่ Facebook APP&lt;/strong&gt;  เอาลิงค์ไปใส่ที่ Privacy Policy URL และ User data deletion แล้วกด &lt;strong&gt;save changes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa7wog3v6il56a96bkd18.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa7wog3v6il56a96bkd18.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ขั้นที่ 12. ตรวจนี้มี Error ไม่ต้องกังวล &lt;strong&gt;ให้ copy key hashes ทั้งหมดใส่ notepad ไว้ก่อน&lt;/strong&gt; กด Remove App Store ออกก่อน แล้วกด save changes&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwqo3l431ucgj68au3h9x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwqo3l431ucgj68au3h9x.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ขั้นที่ 13. มาที่เมนู App Review แล้วเลือก Permission and Features&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi7fpxbrnm35lfiaa0ww0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi7fpxbrnm35lfiaa0ww0.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ขั้นที่ 14. ถ้ามีหน้าต่างนี้กด Not Now&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdo5mwbtazs1ha5lpltzo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdo5mwbtazs1ha5lpltzo.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ขั้นที่ 15. ส่วนของ** Email** ถ้าเป็น Standard access อยู่ จะใช้กับ Facebook account อื่นไม่ได้ จะได้แค่ตัวเอง ให้กด &lt;strong&gt;get advanced access&lt;/strong&gt;&lt;br&gt;
กดแล้วต้องรอประมาณ 5-10 วินาที&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiz1mdvolslyyxyipckwy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiz1mdvolslyyxyipckwy.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ถ้าขึ้นมาแบบนี้ แสดงว่า ไม่ได้ ให้กลับไปลบ App Store ขั้นตอนที่ 12&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flqhrracujiy33bnrmgmj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flqhrracujiy33bnrmgmj.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ถ้าขึ้นมาแบบนี้ แสดงว่า ได้ ติ๊กแล้วกด Confirm มันจะถามให้ใส่ password ของ facebook 1 ครั้ง&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1zuia9g47s8se8gltoq6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1zuia9g47s8se8gltoq6.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ถ้าสำเร็จจะเป็นแบบนี้&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxtb6oqa81xazb63tjjjr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxtb6oqa81xazb63tjjjr.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ขั้นที่ 16. ส่วนของ** public_profile** ถ้าเป็น Standard access อยู่ จะใช้กับ Facebook account อื่นไม่ได้ จะได้แค่ตัวเอง ให้กด &lt;strong&gt;get advanced access&lt;/strong&gt;&lt;br&gt;
กดแล้วต้องรอประมาณ 5-10 วินาที&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ljzp3yuk4v2ewoyo3ep.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ljzp3yuk4v2ewoyo3ep.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ทำเหมือน email&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9710cl6rwl7a32s39zmc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9710cl6rwl7a32s39zmc.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;จนได้แบบนี้ ถือว่า สมบูรณ์&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6letwcz4eh1kcll80j58.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6letwcz4eh1kcll80j58.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ขั้นที่ 17. ไปที่เมนู Setting &amp;gt; Basic&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4gsh83co3k81yakv51go.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4gsh83co3k81yakv51go.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;กดเปิดโหมด Live&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftr8ru9z9e92o9v9be978.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftr8ru9z9e92o9v9be978.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;จะขึ้นให้เช็คเรื่องของการใช้ข้อมูล กด Start Checkup&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqcka6siaa7gfqh6t708q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqcka6siaa7gfqh6t708q.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;กด Get Started&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5nlj21dkrqpxpmx8x6jt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5nlj21dkrqpxpmx8x6jt.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;เลือก 2 ตัวแล้วกด Continue&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqu4r4ey7qqxdovem6s1d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqu4r4ey7qqxdovem6s1d.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;เลือก แล้ว กด Continue&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvpd55dc4brch3dumtkw2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvpd55dc4brch3dumtkw2.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;กด Submit&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkfw2slxsmwefqgfas7mh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkfw2slxsmwefqgfas7mh.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ขั้นที่ 18. กดเปิดโหมด live อีกรอบ จะเปิดได้&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhv2270nixx3mw11blhy1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhv2270nixx3mw11blhy1.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ขั้นที่ 19. เลื่อนลงมาที่ปุ่ม + Add Platform แล้วกด&lt;/p&gt;

&lt;p&gt;เลือก Android แล้วกด Next&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F50f6v5jjang4zvkj8yln.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F50f6v5jjang4zvkj8yln.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;เลือก Google Play แล้วกด Next&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftdyxzkzlufoy3fnnsde2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftdyxzkzlufoy3fnnsde2.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;เอา Key hashes ที่ Copy ไว้มาวาง ถ้าหายแล้ว ก็ไปทำให้ที่ ส่วนที่ 1 ข้อ 7.2&lt;/strong&gt;&lt;br&gt;
ใส่ Package name, Class name &lt;strong&gt;ต้องพิมพ์เอานะ ห้าม Copy วางพิมพ์เสร็จแต่ละช่องกด Enter ด้วย&lt;/strong&gt;&lt;br&gt;
แล้วกด save changes&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Error อยู่ไม่เป็นไร&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fav4uu8foghsv6gwk12wl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fav4uu8foghsv6gwk12wl.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;จบกระบวนการฝั่งตั้งค่า ต่อไปจะเป็นฝั่งการเขียน Code ใน Flutter&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Android: การส่งแอปที่เขียนไปรันบนโทรศัพท์แบบไร้สาย (ADB Wi-Fi)</title>
      <dc:creator>Potchara Pruksasri</dc:creator>
      <pubDate>Sun, 07 Aug 2022 10:36:00 +0000</pubDate>
      <link>https://dev.to/b49dev/android-kaarsngaepthiiekhiiynaipranbnothrsaphthaebbairsaay-adb-wi-fi-387c</link>
      <guid>https://dev.to/b49dev/android-kaarsngaepthiiekhiiynaipranbnothrsaphthaebbairsaay-adb-wi-fi-387c</guid>
      <description>&lt;p&gt;ปกติเราต้องต่อสาย USB เข้ากับโทรศัพท์ android เพื่อให้เครื่องคอมพิวเตอร์ (flutter) ของเรา detect เจอว่ามีโทรศัพท์ต่ออยู่ บางทีก็ไม่สะดวก เพราะมีสายเกะกะ ซึ่งใน android version ใหม่ๆ (จำไม่ได้แล้วว่า 10 หรือ 11 ขึ้นไป) จะมี feature ให้สามารถเชื่อม adb ผ่านทาง wifi ได้ โดยมีขั้นตอนดังนี้&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ต่อสาย usb กับโทรศัพท์แบบปกติก่อน (ตรวจสอบด้วยว่า มันเชื่อมกันชัวร์แล้วใช่ไหม) โดยคำสั่ง adb devices
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Qsi5avlH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vuwji2d6rc16sjm0rpwc.png" alt="" width="478" height="146"&gt;
&lt;/li&gt;
&lt;li&gt;จากนั้นสั่งให้เครื่องที่เราเชื่อมต่อนี้ เปิดการเชื่อมต่อแบบ Wi-Fi โดยระบุ port การเชื่อมต่อเป็น 5555 (ปกติเค้าก็ใช้ port นี้กัน) ด้วยคำสั่ง adb tcpip 5555
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BNP1IICY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sngeitwhdsd5as9bcbng.png" alt="" width="635" height="345"&gt;
กรณีทีมีอุปกรณ์ต่ออยู่หลายตัว เราสามารถระบุอุปกรณ์ที่จะเชื่อมต่อแบบเฉพาะเจาะจงได้โดยการใส่หมายเลขเครื่องด้วยพารมีเตอร์ -s ตามตัวอย่างข้างบน&lt;/li&gt;
&lt;li&gt;ตอนนี้เครื่องมือถือจะเปิดการเชื่อมต่อผ่านทางเน็ต (tcpip) แล้วเราก็จะเชื่อมต่อผ่านทาง wifi ได้แล้ว โดยเรา ถอดสาย usb ออกเลย&lt;/li&gt;
&lt;li&gt;ใช้คำสั่ง abd connect 192.168.1.116:5555 =&amp;gt; 192.168.1.116 คือ ip ของเครื่องโทรศัพท์นะ ถ้าไม่รู้ ip ให้ดูในโทรศัพท์ตรงการเชื่อมต่อ Wi-Fi เลือก Access point ที่มือถือเชื่อมอยู่แล้วกดฟันเฟือนเข้าไปดู (กรณีที่เป็น android samsung)
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mWnEsmnS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0zpntph16aygp5w8vdsb.png" alt="Image description" width="624" height="160"&gt;
&lt;/li&gt;
&lt;li&gt;เท่านี้เครื่องคอมพิวเตอร์ ก็เชื่อมกับโทรศัพท์ผ่าน wifi แล้ว โดยตรวจสอบได้จากคำสั่ง adb devices อีกครั้ง จะเห็นว่ามันเชื่อมผ่าน ip แล้ว
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRg06zdy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/61wqypr80cyji8sgciuo.png" alt="Image description" width="608" height="273"&gt;
&lt;/li&gt;
&lt;li&gt;การยกเลิกการเชื่อมต่อผ่าน ip ใช้คำสั่ง adb disconnect 192.168.1.116:5555 =&amp;gt; 192.168.1.116 คือ ip ของเครื่องโทรศัพท์นะ
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zkLDrPyV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/041g22tcdhri9ef2vuj8.png" alt="Image description" width="663" height="251"&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>flutter</category>
      <category>android</category>
    </item>
  </channel>
</rss>
