64
57

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.

PHPになるべく詳しくならずにWebアプリを作る (Slim + Vue.js)

Posted at

Vueにゃん

PHPは簡単に動かせるのがいいところですね。
その良さを生かしつつ、薄いフレームワークの組み合わせで掲示板を作ってみたいと思います。

経緯

  • Node.js + Express使いだが、実際のところNode.jsをサーバで動かしていい案件はまれ
  • PHP案件はいっぱいだし、動くレンタルサーバも多いぞ
  • 動作環境としてのPHPは魅力なので触っておきたい
  • PHPにあまり詳しくないし、コードを書いている時間よりも調べ物に時間の方が長くなるのが辛い
  • PHPフレームワークも分厚いものが多く、調べ物に時間が取られてやはり辛い
  • 何でも屋になりたいわけではないので、PHPのことは詳しく知らない自分のままでいたい

作りたいもの

とりあえず一行掲示板。

考えた構成

スクリーンショット 2015-08-25 18.06.38.png

  • SPA(PHPを書く量を最低限にするため)
  • PHP5.5 + ビルトインサーバ
  • Slim Framework2 (3も気になるがとりあえず)
  • Vue.js
  • Sqlite(mysqlを使うのがかったるい)

また、Sqliteなら、さくらインターネットの最下位プランでも動作するだろうという目論見。

SlimでJSONサーバを書く

Slimはsinatraライクに書ける。
JSONを吐くだけなら下記のようにする。

$app->get("/items/", function() (){
	echo '{"message" : "Hello, World"}';
}

とりあえず上記のように、適当なJSONを返すようにしておいて、先にフロントエンドを作るのが楽。

JSONを返す設定

JSONしか扱わないのであれば、ルーティング処理全体にContent-Typeを設定できる。下記のようにする。

$app = new \Slim\Slim();
$app->response->headers->set('Content-Type', 'application/json');

テーブルの作成

普通にPDOからSQLiteを使う。
1テーブル程度の小規模アプリなので、わざわざORMを使わなくても良さそう。

$db = new PDO('sqlite:bbs.db');
$db->exec('CREATE TABLE IF NOT EXISTS bbs(id INTEGER PRIMARY KEY, contents TEXT)');

記事一覧の取得

json_encodeを使って、DBからfetchしたものをそのままjsonに変換する。

$app->get("/items/", function() use ($app, $db){
	echo json_encode($db->query('SELECT id, contents FROM bbs ORDER by ID DESC')->fetchAll(PDO::FETCH_ASSOC));
}

記事の投稿

$app->post("/items/", function() use ($app, $db){
	$text = $app->request->post('text');
	$db->prepare('INSERT INTO bbs(contents) VALUES(?)')->execute([$text]);
	$result["status"] = "success";
	$result["text"] = $text;
	echo json_encode($result);
});

フロントエンドを作る

ビューのフレームワークとしてVue.js、Ajaxにはsuperagentを採用する。requireはbrowserifyで解決した。
フレームワークは別にVue.jsでなくても構わない。AngularでもReactでもjQueryでも素JSでも出来る事をやっている。

main.js

var Vue = require("vue");
var request = require("superagent");

new Vue({
	el: "#main",
	data: {
		text: "",
		items: []
	},
	methods: {
		fetchPosts: function(){
			var self = this;
			request
				.get("./api.php/items/")
				.end(function(err, res){
					self.items = res.body;
				})
		},
		createPost: function(text){
			var self = this;
			request
				.post("./api.php/items/")
				.type('form')
				.send({text: text})
				.end(function(err, res){
					if(err){
						console.error(err);
					}
					self.text = "";
					self.fetchPosts();
				});
		}
	},
	ready: function(){
		this.fetchPosts();
	}
})

index.html

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>BBS</title>
	<link rel="stylesheet" href="https://cdn.rawgit.com/mblode/marx/master/css/marx.min.css">
	<link rel="stylesheet" href="./index.css">
</head>
<body>
	<main id="main">
		<h1>BBS</h1>
		<textarea v-model="text" class="bbs__textarea"></textarea>
		<button v-on="click: createPost(text)">投稿</button>	
		<div class="bbs__item" v-repeat="item: items">
			<p>
				{{item.contents}}
			</p>
			<p class="bbs__item__id">
				No: {{item.id}}
			</p>
			<small></small>
		</div>

	</main>
	<script src="dist/bundle.js"></script>
</body>
</html>

リクエスト先のURLが./api.php/〜などとなっている。たいていは.htaccessでapi.phpを削除するなどして、綺麗なURLに直すところ。

だが、SPAにしてしまえば、URLの遷移はJavaScript側に任せることができる。APIのURLが汚い分には、見ている人にはわからないので、このままでいいことにする。

Vue.jsでルーティングを行なう場合は、vue-routerdirectorを使うことになるが、今回はやらない。

余談だが、.htaccessに依存するということは、IISやnginxにデプロイしたり、ビルトインサーバで動作させることができなくなるので、いずれバッドノウハウになるのではと思う。

完成品

とりあえずPHPのビルトインサーバで動作させる。

php -S localhost:8000

スクリーンショット 2015-08-25 16.53.27.png

レポジトリはこちら:GitHub

終わりに

ちゃんとするなら、ユーザ管理とか削除編集、ページネーションなんかも入れないとですね。
あと、今回marxというCSSフレームワークを使ってますが、Bootstrapと比べて余計な色付けが少なく、とても使いやすいのでおすすめです。

64
57
3

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
64
57

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?