LoginSignup
1
2

More than 3 years have passed since last update.

ログイン機能とフォロー機能

Posted at

Controllerを作成

ResourceController

Controllerファイルを生成する際--resourceと付けることでResourceに対応したControllerを自動的に生成。

HTTP動詞 URL アクション 役割
GET /tweets index 一覧表示
GET /tweets/create create 新規ツイート入力画面
POST /tweets store 新規ツイート投稿処理
GET /tweets/{tweet}/show show ツイート詳細画面
GET /tweets/{tweet}/edit edit ツイート編集画面
PUT/PATCH /tweets/{tweet} update ツイート編集処理
DELETE /tweets/{tweet} destory ツイート削除処理
TweetsConroller.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class TweetsConroller extends Controller
{
 // 一覧表示
 public function index()
 {
 //
 }
 // 新規ツイート入力画面
 public function create()
 {
 //
 }
 // 新規ツイート投稿処理
 public function store(Request $request)
 {
 //
 }
 // ツイート詳細画面
 public function show($id)
 {
 //
 }
 // ツイート編集画面
 public function edit($id)
 {
 //
 }
 // ツイート編集処理
 public function update(Request $request, $id)
 {
 //
 }
 // ツイート削除処理
 public function destroy($id)
 {
 //
 }
}

UsersController

php artisan make:controller UsersController --resource

Routing

routes/web.php
<?php
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', function () {
 return view('welcome');
});
Auth::routes();
Route::get('/home', 'HomeController@index')->name('home');
// ログイン状態
Route::group(['middleware' => 'auth'], function() {
 // ユーザ関連
 Route::resource('users', 'UsersController');
});

このクロージャーの中にルートを設定することでログインした時にしかアクセス出来ないようにする。

Route::group(['middleware' => 'auth'], function() {
 //
});
Route::resource('users', 'UsersController');

ユーザ機能では一覧/詳細/編集/更新のみを使用するので第3引数にonlyと記述して使うアクションのみを設定。
php
Route::resource('users', 'UsersController', ['only' => ['index', 'show', 'edit', 'update']]);

ユーザを取得

ユーザ一覧表示画面

Controller

app/Http/Controllers/UsersController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use App\Models\User;
use App\Models\Tweet;
use App\Models\Follower;
class UsersController extends Controller
{
 public function index(User $user)
 {
 $all_users = $user->getAllUsers(auth()->user()->id);
 return view('users.index', [
 'all_users' => $all_users
 ]);
 }
}
メソッドインジェクション

LaravelにはDI(依存性の注入)というのが内蔵されており、メソッドの引数にインジェクトしたいオブジェクトを書くだけで、そのインスタンスが使用できる。

public function index(User $user)
{
 $all_users = $user->getAllUsers(auth()->user()->id);
}

Model

app/Models/User.php
 public function getAllUsers(Int $user_id)
 {
 return $this->Where('id', '<>', $user_id)->paginate(5);
 }

View

resources/views/users/index.blade.php
@extends('layouts.app')
@section('content')
 <div class="container">
 <div class="row justify-content-center">
 <div class="col-md-8">
 @foreach ($all_users as $user)
 <div class="card">
 <div class="card-haeder p-3 w-100 d-flex">
 <img src="{{ $user->profile_image }}" class="rounded-circle" width="50" height="50">
 <div class="ml-2 d-flex flex-column">
 <p class="mb-0">{{ $user->name }}</p>
 <a href="{{ url('users/' .$user->id) }}" class="text-secondary">{{ $user->screen_name }}</a>
 </div>
 </div>
 </div>
 @endforeach
 </div>
 </div>
 <div class="my-4 d-flex justify-content-center">
 {{ $all_users->links() }}
 </div>
 </div>
@endsection

フォロー関連の処理

フォロー/フォロー解除/フォローされているか

Controller

フォローとフォロー解除はresourceのどのアクションにも該当しないので、独自に追加。

app/Http/Controllers/UsersController.php
 // フォロー
 public function follow(User $user)
 {
 $follower = auth()->user();
 // フォローしているか
 $is_following = $follower->isFollowing($user->id);
 if(!$is_following) {
 // フォローしていなければフォローする
 $follower->follow($user->id);
 return back();
 }
 }
 // フォロー解除
 public function unfollow(User $user)
 {
 $follower = auth()->user();
 // フォローしているか
 $is_following = $follower->isFollowing($user->id);
 if($is_following) {
 // フォローしていればフォローを解除する
 $follower->unfollow($user->id);
 return back();
 }
 }

Model

app/User.php
 // フォローする
 public function follow(Int $user_id)
 {
 return $this->follows()->attach($user_id);
 }
 // フォロー解除する
 public function unfollow(Int $user_id)
 {
 return $this->follows()->detach($user_id);
 }
 // フォローしているか
 public function isFollowing(Int $user_id)
 {
 return (boolean) $this->follows()->where('followed_id', $user_id)->first(['id']);
 }
 // フォローされているか
 public function isFollowed(Int $user_id)
 {
 return (boolean) $this->followers()->where('following_id', $user_id)->first(['id']);
 }

フォローされているかの判定

resources/views/users/index.blade.php
@if (auth()->user()->isFollowed($user->id))

フォローしているかの判定

resources/views/users/index.blade.php
@if (auth()->user()->isFollowing($user->id))

Routing

routes/web.php
// ログイン状態
Route::group(['middleware' => 'auth'], function() {
 // ユーザ関連
 Route::resource('users', 'UsersController', ['only' => ['index', 'show', 'edit', 'update']]);
 // フォロー/フォロー解除を追加
 Route::post('users/{user}/follow', 'UsersController@follow')->name('follow');
 Route::delete('users/{user}/unfollow', 'UsersController@unfollow')->name('unfollow');
});

ユーザ詳細画面

  • プロフィール
  • プロフィールが自身だった時に編集ボタンを追加
  • プロフィールが自身以外のユーザだった時にフォロー/フォロー解除/フォローされているかの判定を追加
  • 総ツイート数/フォロー数/フォロワー数の表示
  • ユーザがツイートしたタイムラインの表示

Controller

app/Http/Controllers/UsersController.php
 public function show(User $user, Tweet $tweet, Follower $follower)
 {
 $login_user = auth()->user();
 $is_following = $login_user->isFollowing($user->id);
 $is_followed = $login_user->isFollowed($user->id);
 $timelines = $tweet->getUserTimeLine($user->id);
 $tweet_count = $tweet->getTweetCount($user->id);
 $follow_count = $follower->getFollowCount($user->id);
 $follower_count = $follower->getFollowerCount($user->id);
 return view('users.show', [
 'user' => $user,
 'is_following' => $is_following,
 'is_followed' => $is_followed,
 'timelines' => $timelines,
 'tweet_count' => $tweet_count,
 'follow_count' => $follow_count,
 'follower_count' => $follower_count
 ]);
 }

Model

Tweet
app/Tweet.php
 public function getUserTimeLine(Int $user_id)
 {
 return $this->where('user_id', $user_id)->orderBy('created_at', 'DESC')->paginate(50);
 }
 public function getTweetCount(Int $user_id)
 {
 return $this->where('user_id', $user_id)->count();
 }
Follower
app/Follower.php
 public function getFollowCount($user_id)
 {
 return $this->where('following_id', $user_id)->count();
 }
 public function getFollowerCount($user_id)
 {
 return $this->where('followed_id', $user_id)->count();
 }

ユーザ編集

Controller

$requestで取得したデータをValidator::makeを使ってバリデーションをかける。
Rule::unique('users')->ignore($user->id)の部分はユニークに設定しているscreen_nameemailを自身のIDの時だけ無効にする設定。

app/Http/Controllers/UsersController.php
 public function edit(User $user)
 {
 return view('users.edit', ['user' => $user]);
 }
 public function update(Request $request, User $user)
 {
 $data = $request->all();
 $validator = Validator::make($data, [
 'screen_name' => ['required', 'string', 'max:50', Rule::unique('users')->ignore($user->id)],
 'name' => ['required', 'string', 'max:255'],
 'profile_image' => ['file', 'image', 'mimes:jpeg,png,jpg', 'max:2048'],
 'email' => ['required', 'string', 'email', 'max:255', Rule::unique('users')->ignore($user->id)]
 ]);
 $validator->validate();
 $user->updateProfile($data);
 return redirect('users/'.$user->id);
 }
Model

$paramsの中に画像があれば処理を分けています。
$file_name = $params['profile_image']->store('public/profile_image/');
とすることで画像ファイルが/storage/app/public/profile_image/に保存される。

app/User.php
 public function updateProfile(Array $params)
 {
 if (isset($params['profile_image'])) {
 $file_name = $params['profile_image']->store('public/profile_image/');
 $this::where('id', $this->id)
 ->update([
 'screen_name' => $params['screen_name'],
 'name' => $params['name'],
 'profile_image' => basename($file_name),
 'email' => $params['email'],
 ]);
 } else {
 $this::where('id', $this->id)
 ->update([
 'screen_name' => $params['screen_name'],
 'name' => $params['name'],
 'email' => $params['email'],
 ]);
 }
 return;
 }
1
2
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
2