1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Go langでfwを使わずにcrudのappを作成しました 2

Last updated at Posted at 2019-12-15

part 1
https://qiita.com/dossy/items/721db0ab74afd8e78599
さぁ、part 1でhttp requestとdb 接続ができるようになりましたので、本格的にcrudの処理を行いましょう。
main.goにそれぞれのrequestが呼べるように記述しておきましょう。

main.go
http.HandleFunc("/new", handle.New)
http.HandleFunc("/create", handle.Create)
http.HandleFunc("/edit", handle.Edit)
http.HandleFunc("/update", handle.Update)
http.HandleFunc("/delete", handle.Delete)

createを定義

createするときは
formが必要なのでformがあるnew.htmlを呼び出します。これは/newのリクエストを送ってhtmlを表示させます。

handle/handle.go

func New(w http.ResponseWriter, r *http.Request) {
	
	tem, _ := template.ParseFiles("new.html")
	tem.Execute(w, "")
//どうやら、Executeは引数を2つ必要とするみたいです。
//new.htmlが呼び出せるように追記。


func Create(w http.ResponseWriter, r *http.Request) {
	if r.Method == "POST" {
		r.ParseForm() // Bodyデータを扱うには、事前にパースを行う

		// Formデータを取得
		form := r.PostForm
		body := form["body"][0]
		image := form["image"][0] //form is map value is []string of slice
		serv.Create(body, image) //insert to db

		http.Redirect(w, r, "/", http.StatusMovedPermanently) //code 301
       //rootにredirectさせてます
	}
}
}
new.html

<form action="/create" method="POST">
      <div>
        <label for="say">Let's write a comment!</label>
        <input class="textarea" name="body" id="say" placeholder="input commnet" maxlength="100" required>
      </div>
      <div>
        <label for="to">imageのurlを貼り付け</label>
        <input class="textarea" name="image" id="to" placeholder="input image" required>
      </div>
      <div>
        <button>Send my greetings</button>
      </div>
    </form>

serv/data.go

func Create(body string, image string) {
	db := database.ConnectDB()
	defer db.Close()

	create_time := time.Now() //time.Time型で現時刻を取得
	rows, err := db.Prepare("INSERT INTO posts(body,image,created_at,updated_at) VALUES(?,?,?,?)")
	if err != nil {
		log.Fatal(err)
	}
	rows.Exec(body, image, create_time, create_time)
	// Exec()にプリペアードステートメントを指定してSQLを実行する

}

formから情報を送れるようになりました。formに情報を入れてsubmitすればpost のリクエストがきます。

(注)この辺りから、ゴリゴリの自己実装です。あくまで参考程度でお願いします。何かいい方法などありましたら、コメントまで!!

さて、create funcではpost methodかどうかを判別するために条件分岐を入れています。

*http.Requestの情報をもつ?? rに対してparseをかけて情報を読める状態にします。
その後、formの中身を取り出しますが、どうやら中身はmapとsliceの二重構造になっているらしく、form["image"][0]みたいな取り方になりました。
そして、serv.Create funcが動いて取得したformの情報をinsertを使って、dbに入れ込みます。

edit deleteを定義

editとdeleteがかなり詰まったのを覚えています。
なぜなら、どのidの情報を編集、削除するのかを機械にどうやって渡すかがかなり悩ましかったですね。
httpのリクエストには/edit/2みたいなidをつけて渡すことができなかったんです。

探しあぐねましたが、しかし、見つけました。?をつけるとリクエストに値をつけれるみたいです。
http://cai.cs.shinshu-u.ac.jp/sugsi/Lecture/php/http/2-arg.html

handle/handle.go
func Edit(w http.ResponseWriter, r *http.Request) {
	tem, _ := template.ParseFiles("edit.html")
	params := r.URL.Query()       //Queryで取得 map
	e := serv.Edit(Getid(params)) //return []serv.Vertex
	tem.Execute(w, e[0])
//newとほぼ一緒

func Update(w http.ResponseWriter, r *http.Request) {
	if r.PostFormValue("_method") == "PUT" {
		r.ParseForm()

		form := r.PostForm
		params := r.URL.Query()
		id := Getid(params)
		body := form["body"][0]
		image := form["image"][0]

		serv.Update(id, body, image)
		http.Redirect(w, r, "/", http.StatusMovedPermanently)
	}
}

func Delete(w http.ResponseWriter, r *http.Request) {
	if r.Method == "DELETE" {
		params := r.URL.Query()    //to use Getid
		serv.Delete(Getid(params)) //use sql delete func

		http.Redirect(w, r, "/", http.StatusMovedPermanently)
	}
}

func Getid(params url.Values) int { //get id from httprequest
	var num string
	for k, _ := range params { //get map_key
		num = k
	}

	i, _ := strconv.Atoi(num) //string to int
	return i
}

}

serv/data.go

func Edit(id int) []Vertex {
	db := database.ConnectDB()
	defer db.Close()
	rows, err := db.Query("SELECT * FROM posts WHERE id = ?", id)
	//where分は配列で取得しよる
	if err != nil {
		log.Fatal(err)
	}
	
	var sli []Vertex  // sliceをVertexで定義
	var v1 Vertex     //structをv1で使用する宣言
	for rows.Next() { //next is needed to use scan
		if err := rows.Scan(&v1.Id, &v1.Body, &v1.Image, &v1.Created_time, &v1.Updated_time); err != nil {
			log.Fatal(err)
		}
		sli = append(sli, v1) // [{v1}]
	}
	return sli
}

func Update(id int, body string, image string) {
	db := database.ConnectDB()
	defer db.Close()
	update_time := time.Now()

	rows, err := db.Prepare("UPDATE posts SET body =?,image =?,updated_at = ? WHERE id = ?")

	if err != nil {
		log.Fatal(err)

	}
	rows.Exec(body, image, update_time, id)
}

func Delete(id int) {
	db := database.ConnectDB()
	defer db.Close()
	rows, err := db.Prepare("DELETE FROM posts WHERE id=?")
	if err != nil {
		log.Fatal(err)
	}
	rows.Exec(id)
}

苦労したのが、
params := r.URL.Query() id := Getid(params)
この部分でしょうか。

rのURLの情報をQueryで取得。ただ、そのままだと扱えないのでidの情報だけを取るGetid funcを作成しました。
urlの情報はurl.Valuesという型だそうです。

https://golang.org/pkg/net/url/
http://golang.jp/pkg/strconv
https://qiita.com/nakabonne/items/2720bac7027115b1d004

part 3
https://qiita.com/dossy/items/4e05e8048a7885156a31

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?