laravelをbackend、vueをfrontendにしたつぶやきwebアプリを作って自分の確認のために書いておきます。
まず、vueは画面表示だけ、laravelの方でつぶやきもユーザーも管理する方向で作っていきました。
laravelのAuthControllerもこんな感じ
<?php
namespace App\Http\Controllers;
use App\Http\Requests\UserLoginRequest;
use App\Http\Requests\UserRegisterRequest;
use App\Http\Resources\User as UserResource;
use App\User;
use Illuminate\Http\Request;
class AuthController extends Controller {
public function register(UserRegisterRequest $request) {
$user = User::create([
'email' => $request->email,
'name' => $request->name,
'password' => bcrypt($request->password),
]);
if (!$token = auth()->attempt($request->only(['email', 'password']))) {
return abort(401);
};
return (new UserResource($request->user()))->additional([
'meta' => [
'token' => $token,
],
]);
}
public function login(UserLoginRequest $request) {
if (!$token = auth()->attempt($request->only(['email', 'password']))) {
return response()->json([
'errors' => [
'email' => ['Sorry we cant find you with those details.'],
],
], 422);
};
return (new UserResource($request->user()))->additional([
'meta' => [
'token' => $token,
],
]);
}
public function user(Request $request) {
return new UserResource($request->user());
}
public function logout() {
auth()->logout();
}
}
backend/app/Http/Controllers/PostController.phpも
<?php
namespace App\Http\Controllers;
use App\Http\Requests\StorePostRequest;
use App\Http\Requests\UpdatePostRequest;
use App\Http\Resources\Post as PostResource;
use App\Post;
use App\Topic;
use Illuminate\Http\Request;
class PostController extends Controller {
public function store(StorePostRequest $request, Topic $topic) {
$post = new Post;
$post->body = $request->body;
$post->user()->associate($request->user());
$topic->posts()->save($post);
return new PostResource($post);
}
public function show(Request $request, Topic $topic, Post $post) {
return new PostResource($post);
}
public function update(UpdatePostRequest $request, Topic $topic, Post $post) {
$this->authorize('update', $post);
$post->body = $request->get('body', $post->body);
$post->save();
return new PostResource($post);
}
public function destroy(Topic $topic, Post $post) {
$this->authorize('destroy', $post);
$post->delete();
return response(null, 204);
}
}
backend/app/Http/Controllers/TopicsController.php
<?php
namespace App\Http\Controllers;
use App\Http\Requests\TopicCreateRequest;
use App\Http\Requests\UpdateTopicRequest;
use App\Http\Resources\Topic as TopicResource;
use App\Post;
// use Illuminate\Http\Request;
use App\Topic;
class TopicController extends Controller {
public function index() {
$topics = Topic::latestFirst()->paginate(5);
return TopicResource::collection($topics);
}
public function store(TopicCreateRequest $request) {
$topic = new Topic;
$topic->title = $request->title;
$topic->user()->associate($request->user());
$post = new Post;
$post->body = $request->body;
$post->user()->associate($request->user());
$topic->save();
$topic->posts()->save($post);
return new TopicResource($topic);
}
public function show(Topic $topic) {
return new TopicResource($topic);
}
public function update(UpdateTopicRequest $request, Topic $topic) {
$this->authorize('update', $topic);
$topic->title = $request->get('title', $topic->title);
$topic->save();
return new TopicResource($topic);
}
public function destroy(Topic $topic) {
$this->authorize('destroy', $topic);
$topic->delete();
return response(null, 204);
}
}
vue側で送られてきたデータを登録、消去、変更するだけ。
resources/viewsには何も記述しない、vueで表示するから。
ちなみにpostはトピックに対するコメント、topicはつぶやき本体。
おまちかねvueの処理の紹介
frontend/pages/topics/posts/index.vue
```
<template>
<div class="container">
<h2>Latest Topics</h2>
<div v-for="(topic, index) in topics" :key="index" class="bg-light mt-5 mb-5" style="padding:20px;">
<h2><nuxt-link :to="{name: 'topics-id', params: {id: topic.id}}">{{topic.title}}</nuxt-link></h2>
<div v-if="authenticated">
<div v-if="user.id === topic.user.id">
<button @click="deleteTopic(topic.id)" class="btn btn-outline-danger fa fa-trash fa-2x pull-right"></button>
<nuxt-link :to="{name: 'topics-edit', params: {id: topic.id}}">
<button class="btn btn-outline-success fa fa-edit fa-2x pull-right"></button>
</nuxt-link>
</div>
</div>
<p class="text-muted">{{topic.created_at}} by {{topic.user.name}}</p>
<div v-for="(content, index) in topic.posts" :key="index" class="ml-5 content">
{{content.body}}
<p class="text-muted">{{content.created_at}} by {{content.user.name}}</p>
<!-- add likes button -->
<div class="btn btn-outline-primary fa fa-thumbs-up ml-5 mb-2" @click="likePost(topic.id, content)">
<span class="badge">{{content.like_count}}</span>
</div>
</div>
</div>
<nav>
<ul class="pagination justify-content-center">
<li v-for="(key, value) in links" class="page-item">
<a @click="loadMore(key)" href="#" class="page-link">{{value}}</a>
</li>
</ul>
</nav>
</div>
</template>
<script>
export default {
data() {
return {
topics: [],
links: []
}
},
async asyncData({$axios}) {
let {data, links} = await $axios.$get('/topics')
console.log(links)
return {
topics: data,
links
}
},
methods: {
async loadMore(key) {
let {data} = await this.$axios.$get(key)
return this.topics = {...this.topics, ...data}
},
async deleteTopic(id) {
await this.$axios.$delete(`/topics/${id}`)
this.$router.push('/')
},
async likePost(topicId, content) {
const userFromVuex = this.$store.getters["auth/user"];
if (userFromVuex) {
// cant like your own post
if (userFromVuex.id === content.user.id) {
alert('You cant like your own post')
}
// if user have already liked
if (content.users) {
if (content.users.some(user => user.id === userFromVuex.id)) {
alert('You have already liked this post')
} else {
await this.$axios.$post(`/topics/${topicId}/posts/${content.id}/likes`)
let {data, links} = await this.$axios.$get(`/topics`)
this.topics = data
this.links = links
}
}
} else {
alert('Please log in')
this.$router.push('/login')
}
}
}
}
</script>
<style scoped>
.content {
border-left: 10px solid white;
padding: 0 10px 0 10px;
}
.btn-outline-success, .btn-outline-danger {
border: none;
}
</style>
```