20200325のlaravelに関する記事は16件です。

【Laravel】 From句にサブクエリを使用する

結論

laravel 5.6.3から
joinSub、leftJoinSubが使える.

$subQuery = ProfileUserView::select(['user_id', 'company_id'])
    ->whereBetween('created_at', [$from, $to])
    ->distinct();

$mostViewQuery = \DB::query()
    ->selectRaw('company_id, COUNT(user_id) AS pv')
    ->fromSub($subQuery, 'sub')
    ->groupBy('company_id');

ver 5.6.3以前

それより以前は mergeBindings使う.

https://github.com/laravel/framework/issues/19711

$count = DB::table( DB::raw("({$sub->toSql()}) as sub") )
    ->mergeBindings($sub->getQuery()) // you need to get underlying Query Builder
    ->count();

こんな感じ

$subQuery = ProfileUserView::select(['user_id', 'company_id'])
    ->whereBetween('created_at', [$from, $to])
    ->distinct();

$mostViewQuery = \DB::table(\DB::raw("({$subQuery->toSql()}) as sub") )
    ->mergeBindings($subQuery->getQuery())
    ->selectRaw('company_id, COUNT(user_id) AS pv')
    ->groupBy('company_id');

ただしmergeBindingsは、bindするパラメーターの順序を気をつけないといけないので注意する

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel base64エンコードされた画像を保存する

    /**
     * 画像保存
     * @param  string $base64Context
     * @param  string $storage
     * @param  string $dir
     * @return App\Models\Image
     */
    public function storeImage($base64Context, $storage, $dir)
    {
        try {
            preg_match('/data:image\/(\w+);base64,/', $base64Context, $matches);
            $extension = $matches[1];

            $img = preg_replace('/^data:image.*base64,/', '', $base64Context);
            $img = str_replace(' ', '+', $img);
            $fileData = base64_decode($img);

            $dir = rtrim($dir, '/').'/';
            $fileName = md5($img);
            $path = $dir.$fileName.'.'.$extension;

            Storage::disk($storage)->put($path, $fileData);

            return $path;

        } catch (Exception $e) {
            Log::error($e);
            return null;
        }
    }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】 base64エンコードされた画像を保存する

    /**
     * 画像保存
     * @param  string $base64Context
     * @param  string $storage
     * @param  string $dir
     * @return App\Models\Image
     */
    public function storeImage($base64Context, $storage, $dir)
    {
        try {
            preg_match('/data:image\/(\w+);base64,/', $base64Context, $matches);
            $extension = $matches[1];

            $img = preg_replace('/^data:image.*base64,/', '', $base64Context);
            $img = str_replace(' ', '+', $img);
            $fileData = base64_decode($img);

            $dir = rtrim($dir, '/').'/';
            $fileName = md5($img);
            $path = $dir.$fileName.'.'.$extension;

            Storage::disk($storage)->put($path, $fileData);

            return $path;

        } catch (Exception $e) {
            Log::error($e);
            return null;
        }
    }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

セッション

Request->session()->put('キー', 値);
$変数 = Request->session()->get('キー');

sessionの格納先は
strage/framework/sessionsになる。

データベースでセッションを使う

下記設定に変更する

config/session.php
'driver' => env('SESSION_DRIVER', 'database')
SESSION_DRIVER=database

コマンド実行

php artisan session:table

マイグレーションファイルが作成されるのでphp artisan migrateすればDBでセッションを扱えるようになる

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Elastic BeanstalkでのLaravelにてstorageへのシンボリックリンクを張る方法

はじめに

Elastic BeanstalkでのLaravelにてstorageへのシンボリックリンクを張る方法で手こずったので備忘録です

TL;DR

container_commandsにて「ln」を使用して、相対パスでシンボリックリンクを貼りました

コード

ebextensions/commands.config
container_commands:
   0x_storage_link:
      command: "ln -s ../storage/app/public storage"
      cwd: "/var/app/ondeck/public"

最後に

他に良い方法がありそうですが。。。

補足

「php artisan storage:link」でシンボリックリンクを貼ると絶対パスになりました。(参考サイトと同事象)

参考

php artisan storage:link linking wrong directory

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravelを利用したWebアプリ制作を学べる教材まとめ

はじめに

あらゆる教材に手を出すと、結局この教材はどういうことが学べるんだっけ??と失念しがちなので自分用に作ってみました。

※随時更新予定※

Techpitの教材編


Laravel(+Vue.js)でSNS風Webサービスを作ろう!


ページリンク
https://www.techpit.jp/p/laravel-vue-sns

完成見本サンプル(※私がデプロイしたもの。Mail機能のみ未実装。)
http://laravel-vue-sns.herokuapp.com/

開発環境


Mac,Docker(Laradock)
PHP 7.3、Node.js 10、Vue.js 2.6.11、Laravel 6.8、PostgreSQL 11.6


~Dockerを利用するメリット~

Webサーバーやデータベース本体やその設定内容をファイル化できるという点が挙げられます。

そのようなファイルをほかの人に配布することで、誰でも同じ環境を構築できます。

本教材では、そうしたDocker用に作られたファイルを利用して開発環境を作ります。


活用ライブラリ


MDBootStrap、Vue Tags Input

学べる内容


初学者がポートフォリオ作成で躓く(私含め)であろうミドルウェア、リクエスト、認可、ポリシー、さらにはフロンドエンドフレームワーク(Vue.js)との連携まで、実際にアプリを作りながら体験できる。

以下、以前書いた感想記事。

https://chobimusic.com/laravel_vue_sns/

 

進め方


2章・3章:ログイン機能

4章:記事投稿機能
4-3 authミドルウェア 4-4 フォームリクエストの作成 4-5 依存性の注入(DI)、fillableの利用

5章:記事更新・削除機能
5-2 null演算子 5-5 認可(ポリシーの作成)によるユーザー権限の考慮

6章:パスワード再設定メール(MailHogでのテストメール/Sendgridでの本番メール)

7章:いいね機能(VueコンポーネントをBladeに組み込み)
7-5 @json 7-7 いいね機能のアクションメソッド追加(web.php)

8章:タグ機能
8-6 フォームリクエストのバリデーション(鬼門)

9章:フォロー&ユーザーページ機能

10章:Googleアカウントを使ったログイン機能

11章:デバッグバーの活用(SQLの改善)

12章:Herokuへデプロイ

所感


このチュートリアルで連携するVue.jsに関しては、Vue Routerなどの公式ライブラリを活用しない。

また、blade側に@jsonディレクティブを記載してデータ転送(サーバー上にあげる。Vueで取り出し。)しているのが印象的。

SPA開発ではないのでVueで非同期のデータ受け渡し&装飾をしている感じ。(フォローボタン・いいね機能)

URLの遷移がある部分は全てLaravel側で構築している。

内容自体かなり濃いので、Laravel、Vue.js共にある程度わかっていないと理解が難しいが、とても勉強になる。

SPA開発まではいかずともLaravelとVue.jsを連携させたい!といった方にはとてもおすすめ!!

Googleアカウントでログイン機能を実装することで、アプリ運用に伴うセキュリティ面のハードルが少し下がる。

どこからどこまでBladeで作ってVue側で補うか、境目の判断が難しい。。。

ちょっと動的なコンテンツを入れるだけならならjQueryを活用するのもアリ??

【Laravel x Vue.js】SPAクイズアプリケーションを作ってみよう!


ページリンク
https://www.techpit.jp/p/laravel-vue-quiz

完成見本サンプル
https://laravel-vue-quiz.herokuapp.com/

開発環境


Mac,Homebrew
PHP 7.3、Node.js 10、Vue.js 2.6.10、Laravel 6.8、SQLite

活用ライブラリ


Chart.js,Axios(API※非同期でのサーバーアクセス※をより使いやすくしたもの),Laravel-Admin

学べる内容


サーバーサイドにLaravel、フロントサイド(表示部分)は、Vueで作成。

メインとなるビューはトップ("/")と("/quiz")クイズの2画面。

Vue Router(ルーティング制御ができる公式プラグイン)でSPA化("/"と"/quiz"ページの遷移がリロードせずにできる)。

進め方


3章:Laravelプロジェクトとは別のディレクトリでVue.jsのプロジェクトを作成。

4章:LaravelディレクトリとVueディレクトリをがっちゃんこ。index.blade.phpでvueを読み込み。

5章:Vou Router(router.js)の導入でSPA化

6章:API連携の実装(api.phpの編集)。Laravel側で取得したDB情報 をVue(フロントサイド)からAPIで読み込む。

7章・8章:ログイン、ユーザー登録もVue側でビューを作成。

9章:ランキング機能、キーワード画面の実装 ※いずれもAPIを使う

10章:ブラッシュアップ

11章:Laravel-Adminの導入

12章:Herokuへデプロイ

所感


LaravelにVueを組み込むにしてもどこまで組み込むのかで難易度が大きく変わることに気付けた。

例えばいいねボタンの実装とかであれば簡単だが、SPA化するとなるとAxiosやVue Routerなどの知識も必要になる。

また、Laravel-adminが使いこなせればWordPressを使用することなくブログ運営なんかもできるなと感じた。(同じようなものだと他にはVoyagerなどがあるみたい。これを駆使したチュートリアルが見つからなかったのは残念。)

Laravel6とAWSで作るブックレビューサイト


ページリンク
https://www.techpit.jp/p/laravel6-aws

完成見本サンプル
https://laravel-vue-quiz.herokuapp.com/

開発環境


AWS,cloud9(win,mac共通)
PHP 7.3、Node.js 10、MySQL5.7、Laravel 6

学べる内容


AWSでのアプリ開発

画像投稿機能(シンボリックリンク)

GitHubリポジトリの作成~cloud9からの独自ドメインへのデプロイ

EC2インスタンスの立ち上げ、TeraTermでのSSH接続

所感


最初に作ったポートフォリオはこちらの教材を参考にした。

削除・編集機能までは実装しないのが残念だが、AWSの活用を学べるのはありがたい。

最後にカスタマイズ提案があり、いいね機能やコメント機能など。

こちらはまだ未実装なので試してみてもいいかもしれない。

無料でできるチュートリアル


Vue + Vue Router + Vuex + Laravelで写真共有アプリを作ろう


ページリンク
https://www.hypertextcandy.com/vue-laravel-tutorial-introduction/

開発環境


Mac,Docker(Laradockを用いていない!!)
PHP 7.4、Node.js 10、Vue.js 2.6、Laravel 6、PostgreSQL、AWS S3(写真保存)

学べる内容


フロントエンドに Vue.js + Vue Router + Vuex 、サーバーサイドに Laravel を使用したSPAアプリ開発。

進め方


3章:Laravelプロジェクト作成。Laravel Mixでフロントをビルド。Vue Routerを導入。

4章:api.phpを編集してサーバーサイドのAPIを実装。(会員登録,ログイン,ログアウト)

6章・7章:状態管理ライブラリVuexの導入。ユーザー認証データなどコンポーネントをまたいで参照したいデータを入れておけるストアの実装。

10章:写真投稿フォーム Vue.jsで投稿機能を実装。

11章:JSONへの変換。

16章:Herokuへのデプロイ&カスタマイズ提案

所感


無料のチュートリアルとしては断トツで深いところまで学べる。

Laradockを使わずともDockerでLaravelは使えることにも気づいたので挑戦してみたい。

データの受け渡しやいいねなどあらゆる機能をVue.jsで実装。

教本含め、ここまで複雑なアプリ開発ができるチュートリアルを見たことがない。

もっとこういうチュートリアルが増えてほしい!!

おわりに


1つの教材ですべてを網羅することはできないので、いろんなチュートリアルをこなしながらスキルアップを目指したい。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Docker+Laravel】テスト用のダミーファイルの生成の際に出たエラーたち

状況

Dockerの環境でLaravelアプリのテストの際、ダミーの画像ファイルを作ろうと思い、公式リファレンスにもあるfile()を利用しました。

公式リファレンス(ファイルアップロードのテスト)
https://readouble.com/laravel/5.8/ja/http-tests.html?header=%25E3%2583%2595%25E3%2582%25A1%25E3%2582%25A4%25E3%2583%25AB%25E3%2582%25A2%25E3%2583%2583%25E3%2583%2597%25E3%2583%25AD%25E3%2583%25BC%25E3%2583%2589%25E3%2581%25AE%25E3%2583%2586%25E3%2582%25B9%25E3%2583%2588

$file = UploadedFile::fake()->image('avatar.jpg');

テストしてみるとこんなエラーが...

Tests\Feature\InformationControllerTest::testStore
Call to undefined function Illuminate\Http\Testing\imagecreatetruecolor()

最初はクラスをuseしてないのかな?とかLaravelアプリ側の問題だと思いましたが、どうやらこのfile()メソッドが定義されるIlluminate\Http\UploadedFileクラスを使うには、PHP GDというPHPのライブラリが必要なようです。

PHP GDのインストール

DockerfileにPHP GDのインストールを追加してみます。

RUN apt-get update && apt-get install -y \
    zlib1g-dev \
    libzip-dev \
    mariadb-client \
  && docker-php-ext-install zip pdo_mysql gd 

上のように書き換え、再構築してみると、次はこんなエラーが

configure: error: png.h not found

調べるとdocker-php-ext-install gdをするだけでは足りず、
libfreetype6-dev
libjpeg62-turbo-dev
libpng-dev
依存関係のある三つのパッケージを事前に apt-get install する必要があるみたいです。

Dockerfileを修正します。
docker-php-ext-install gdの実行前に三つのパッケージのapt-get installを書きます。

RUN apt-get update && apt-get install -y \
    zlib1g-dev \
    libzip-dev \
    mariadb-client \
    libfreetype6-dev \
    libjpeg62-turbo-dev \
    libpng-dev \
  && docker-php-ext-install zip pdo_mysql gd 

再度buildしてみると正常に構築できました。

本当にインストールできているか確認してみます。

gd

GD Support => enabled
GD Version => bundled (2.1.0 compatible)
GIF Read Support => enabled
GIF Create Support => enabled
PNG Support => enabled
libPNG Version => 1.6.36
WBMP Support => enabled
XBM Support => enabled

ちゃんとインストールできたようですね。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravelでいいね機能を実装しよう

1. はじめに

いいね機能とは、最近のSNSにはほとんどと言ってもいいほど実装されている機能で、「好き」,「わかる」,「支持できる」などの意思表示を表すコミュニケーションツールの一種です。

いいね機能があることによって、

・(ユーザー視点)多くの投稿からどの投稿が人気もしくは信憑性があるのか。
・(投稿者視点)これまで投稿した記事でどの記事がユーザーの求めている記事なのか。

などを判断する1つの材料となります。

今回はPHPのフレームワークLaravelを使用して、いいね機能を実装していきます。
※今回はLaravelの勉強を兼ねているため、いいね機能をサーバーサイドで処理を実装しています。本来のプロダクトであれば処理を軽くするためにもフロント側で処理を実装するかと思いますので、その点についてはご了承ください。

1-1. 開発環境

PHPとLaravelのバージョンは下記のグラフの通りとします。

言語・FW     バージョン
PHP 7.2.26
Laravel 6.17.1

2. どのような仕様にするか

仕様としては1つの投稿(discussion)に複数のリプライ(Reply)が紐づくようになっていて、リプライに対していいね(Like)をつけることができます。
細かい仕様は以下のように定義します。

・初期値はいいねボタンがグレーで、いいねボタンを押すとボタンが緑色になる
・いいね数をいいねボタンの右横に表示する
・いいねボタンを2度押すといいねを取り消すことができる
・自分のリプライに対してもいいねをすることができる
・ログイン中のみに限り、リプライにいいねすることができる

スクリーンショット 2020-03-19 20.12.56.png

3. いいね機能の実装

それでは実際にいいね機能の実装に入っていきます。

3-1. ルーティング

まずはじめにいいね機能を実装する上でのルーティングを定義します。
リプライにいいねをする処理をRepliesControllerのlike()に、
リプライに付けたいいねを解除する処理をRepliesControllerのunlike()に記述するという定義を行います。

web.php
Route::get('/reply/like/{id}', 'RepliesController@like')->name('reply.like');
Route::get('/reply/unlike/{id}', 'RepliesController@unlike')->name('reply.unlike');
3-2. 情報の関係性について考える

リプライ(Reply)といいね(Like)の関係性は以下のようになります。

・1つのリプライに対して複数のいいねが紐づく
・1つのいいねに対して紐づくリプライは1つのみ

RepliesテーブルとLikesテーブルのE-R図
スクリーンショット 2020-03-19 21.03.07.png

ユーザー(User)といいね(Like)の関係性は以下のようになります。

・1人のユーザーに対して複数のいいねが紐づく
・1つのいいねに対して紐づくユーザーは1人のみ

UsersテーブルとLikesテーブルのE-R図
スクリーンショット 2020-03-19 21.09.40.png

3-3. モデルの作成と修正

artisanコマンドでLikeモデルとマイグレーションファイルを生成します。

$ php artisan make:model Like -m

3-2の情報の関係性を基にしてマイグレーションファイルとモデルを修正します。

create_likes_teble.php
class CreateLikesTable extends Migration
{
 /**
  * Run the migrations.
  *
  * @return void
  */
  public function up()
  {
    Schema::create('likes', function (Blueprint $table) {
      $table->bigIncrements('id');
      $table->integer('reply_id')->unsigned();
      $table->integer('user_id')->unsigned();
      $table->timestamps();
   });
  ...
 }
}
Like.php
class Like extends Model
{
  // 配列内の要素を書き込み可能にする
  protected $fillable = ['reply_id','user_id'];

  public function reply()
  {
    return $this->belongsTo(Reply::class);
  }

  public function user()
  {
    return $this->belongsTo(User::class);
  }
}
Reply.php
class Reply extends Model
{
  ...
  public function likes()
  {
    return $this->hasMany(Like::class, 'reply_id');
  }
}
3-4. いいね機能のビジネスロジックの実装

いいね機能のロジックを実装する上で以下の2点がポイントとなります。

・いいねボタンを押下したら、Likeテーブルに新たにレコードが生成されて、ユーザーIDとリプライIDが保存される。
・いいねしたボタンに対して、再度いいねボタンを押すと上記で生成したレコードが削除される。

上記のポイントを基に実装すると下記のようになります。

RepliesController.php
class RepliesController extends Controller
{
  // only()の引数内のメソッドはログイン時のみ有効
  public function __construct()
  {
    $this->middleware(['auth', 'verified'])->only(['like', 'unlike']);
  }

  ...

 /**
  * 引数のIDに紐づくリプライにLIKEする
  *
  * @param $id リプライID
  * @return \Illuminate\Http\RedirectResponse
  */
  public function like($id)
  {
    Like::create([
      'reply_id' => $id,
      'user_id' => Auth::id(),
    ]);

    session()->flash('success', 'You Liked the Reply.');

    return redirect()->back();
  }

  /**
   * 引数のIDに紐づくリプライにUNLIKEする
   *
   * @param $id リプライID
   * @return \Illuminate\Http\RedirectResponse
   */
  public function unlike($id)
  {
    $like = Like::where('reply_id', $id)->where('user_id', Auth::id())->first();
    $like->delete();

    session()->flash('success', 'You Unliked the Reply.');

    return redirect()->back();
  }

...

}

4. いいねボタンの実装

4-1. いいね状態非いいね状態 の表示制御

初期表示ではリプライにいいねがついておらず、いいねボタンはグレーでカウントは0、いいねをいている状態だと、いいねボタンが緑色になりカウントが1加算されます。

いいねがついているかどうかの判定を、 is_liked_by_auth_user() 内で判定して判定値をbooleanで返してあげます。

show.blade.php
<div>
  @if($reply->is_liked_by_auth_user())
    <a href="{{ route('reply.unlike', ['id' => $reply->id]) }}" class="btn btn-success btn-sm">いいね<span class="badge">{{ $reply->likes->count() }}</span></a>
  @else
    <a href="{{ route('reply.like', ['id' => $reply->id]) }}" class="btn btn-secondary btn-sm">いいね<span class="badge">{{ $reply->likes->count() }}</span></a>
  @endif
</div>
Replay.php
 /**
  * リプライにLIKEを付いているかの判定
  *
  * @return bool true:Likeがついてる false:Likeがついてない
  */
  public function is_liked_by_auth_user()
  {
    $id = Auth::id();

    $likers = array();
    foreach($this->likes as $like) {
      array_push($likers, $like->user_id);
    }

    if (in_array($id, $likers)) {
      return true;
    } else {
      return false;
    }
  }
4-2. いいね数の表示

いいね数の表示は、ReplyLikeは既にアソシエーションされているので、count()でいいね数を取得することができます。

shwo.blade.php
{{ $reply->likes->count() }}

最後に

以上でLaravelでのいいね機能の実装のご紹介でした!!
誤字脱字や、もっとこうした方がいいという箇所がございましたらコメント欄から教えてください!!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravelのモデル結合ルート【暗黙の結合】を使ってみる

暗黙の結合とは

暗黙結合とはLaravelのルートURIセグメント名と一致するEloquentモデルを
勝手に紐付けてくれる機能です
また、入力されたセグメントと一致するモデルが存在しない場合は404が返ってきます

この説明だけではパッとしないと思いますが
とても便利な機能なので是非積極的に使っていきたい機能だと思い
私も調べて試してみたので記事にしてみました

準備

まずはデフォルトのUsersテーブルを作成します

$ php artisan migrate

シーダファイルを用意してUsersテーブルに値を用意しておきます

$ php artisan make:seeder UserSeeder

作成されたシーダファイルに記述します

UserSeeder.php
<?php

use Illuminate\Database\Seeder;

class PersonTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $param = [
            'name' => '太郎',
            'email' => 'taro@gmail.com',
            'password' => '99999999'
        ];

        DB::table('users')->insert($param);

        $param = [
            'name' => '花子',
            'email' => 'hanako@gmail.com',
            'password' => '99999999'
        ];

        DB::table('users')->insert($param);

        $param = [
            'name' => '次郎',
            'email' => 'ziro@gmail.com',
            'password' => '99999999'
        ];

        DB::table('users')->insert($param);
    }
}

作成したシーダファイルを実行します

$ php artisan db:seed

3件のダミーデータを用意しておきました

次に今回所得したデータを表示するviweを作成します
resourcesmainフォルダを作成しその中にindex.blade.phpを作成してください
中身はこんな感じにしておきます

index.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>ユーザー表示</title>
</head>
<body>
    {{ $user->name }}
</body>
</html>

コントローラーを作成します

$ php artisan make:controller MainController

ここまでは準備です
では実際に暗黙結合でUsersのデータを所得して表示してみます

実際に試す

ルート定義していきます

web.php
Route::get('/users/{user}', 'MainController@index');

コントローラーを修正します

MainController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\User;

class MainController extends Controller
{
    public function index(User $user)
    {
        return view('main.index', compact('user'));
    }
}

これで実際に/users/1とURLを叩いてみてください
ブラウザには太郎と表示されるかと思います
これが、暗黙に結合された結果です

ルートセグメントで/users/{user}としてEloquentモデルのUserと紐づけています
{user}に入ってきた数字がUserモデルのidと合致するものが結合されます
そのモデルがコントローラーのpublic function index(User $user ){この部分の引数に渡されています
暗黙の結合があることで、仮にそのUserの情報を所得したりしたい場合に
User::find($id)みたいなことを書くことなくそのまま受け取れるのでとてもスマートで
便利な機能だなと思いました

おまけ

今回の場合はすでにあるUserモデルに新たにコントローラーを作成して利用しましたが
Userモデルのリソースコントローラーを作成することも多くあるかと思います
その際にこのコマンドを実行しコントローラーを作成することで
暗黙の結合を行うのに楽に実装できるリソースコントローラーを簡単に用意できます
コマンドにて下記を実行

$ php artisan make:controller UserController --model=User

これでUserのリソースコントローラーで下記のようにいい感じに作成してくれます

UserController.php
<?php

namespace App\Http\Controllers;

use App\User;
use Illuminate\Http\Request;

class UserController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        //
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\User  $user
     * @return \Illuminate\Http\Response
     */
    public function show(User $user)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\User  $user
     * @return \Illuminate\Http\Response
     */
    public function edit(User $user)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\User  $user
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, User $user)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\User  $user
     * @return \Illuminate\Http\Response
     */
    public function destroy(User $user)
    {
        //
    }
}

アクションの引数には予め、指定してUserモデルが指定されていますね
これでこのリソースコントローラーもそのまま使うだけで、暗黙結合したものが利用できとても便利な機能です

今後はもっとこの機能を活用していこうと思います

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel 新規プロジェクト作成手順(laravel コマンドが使えなかったとき、composerコマンドでやってみよう)

 Laravel 新規プロジェクト作成手順

今回は、プロジェクト名を「laravelapp」にしています。
ここは、ご自身の指定したプロジェクト名に変更可能です。

laravel new new-project laravelapp

上記のコマンドが上手く動作しなかった場合、下記のコマンドを実行してみてください!!

composer create-project laravel/laravel laravelapp --prefer-dist
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

$thisとは。

$thisとは。

簡潔にいう。
$thisを使っているクラスのことだ。

具体的にいうと、コントローラーを見てみよう。

sample_controller.php
class NewsController extends Controller {

  public function add_index()
  {
      $this->なんやかんや;
  }
}

注目するのは、最初のここ!

class NewsController extends Controller {

これは、
Controllerクラスを継承して、NewsControllerクラスを作ります。中身は{}の中!!
という意味です。

結論!!
$thisとは、ここでいうNewsControllerクラスのオブジェクトのこと!!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel 7とSnappyでPDFを出力する

はじめに

LaravelでPDFを出力する方法です。

完成版のソースは以下に置いてあります。
https://github.com/naga3/snappy-sample

Laravelで使えるPDF出力ライブラリ

今回はバランスを考えてLaravel Snappyを選択しました。

Laravelプロジェクト作成

https://readouble.com/laravel/7.x/ja/installation.html

コチラを参考に適当なプロジェクトを作成します。Composerがインストールされていれば簡単に作成できます。

composer create-project --prefer-dist laravel/laravel snappy-sample
cd snappy-sample

Laravel Snappyのインストール

Laravel Snappyのドキュメントを見て進めて行きます。

まずwkhtmltopdfをインストールしますが、こちらもComposerで簡単に導入できます。WindowsやMacなど、バイナリが適合しない場合は上記ドキュメントを参照してください。

composer require h4cc/wkhtmltopdf-amd64 0.12.x

次にLaravel Snappy本体をインストールします。

composer require barryvdh/laravel-snappy

configファイルを作ります。

php artisan vendor:publish --provider="Barryvdh\Snappy\ServiceProvider"

configファイルにwkhtmltopdfの場所を書きます。上記のようにComposerからインストールした場合は

config/snappy.php
'binary' => base_path('vendor/h4cc/wkhtmltopdf-amd64/bin/wkhtmltopdf-amd64'),

PDF出力のテスト

正常にインストールできたかチェックしてみます。

routes/web.php
Route::get('/hello', function () {
    return PDF::loadHTML('<h1>Hello!</h1>')->inline();
});

image.png

 大丈夫そうですね。

Bladeを使ってPDFを出力する。

Snappyは、BladeにそのままHTMLを書いて出力できるので大変楽です。CSSも2くらいまでは正確に効きます。

まずRouteの部分です。

routes/web.php
Route::get('/members', function () {
    $member = Faker\Factory::create('ja_JP');
    return PDF::loadView('members', compact('member'))->inline();
});

Fakerでランダムなデータを生成してviewに渡しています。

次にテンプレートの部分です。

resources/views/members.blade.php
<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <title>名簿</title>
  <style>
    table {
      border-collapse: collapse;
    }

    tr {
      page-break-inside: avoid;
    }

    th,
    td {
      border: 1px solid black;
    }
  </style>
</head>

<body>
  <h1>名簿</h1>
  <table>
    <tr>
      <th>No.</th>
      <th>氏名</th>
      <th>住所</th>
      <th>電話番号</th>
      <th>備考</th>
      @for ($no = 1; $no <= 50; $no++) <tr>
        <td>{{ $no }}</td>
        <td style="white-space: nowrap">{{ $member->name }}</td>
        <td>{{ $member->address }}</td>
        <td>{{ $member->phoneNumber }}</td>
        <td>{{ $member->realText }}</td>
    </tr>
    @endfor
  </table>
</body>

</html>

ブラウザで確認してみます。

image.png

良さそうですね。

tr要素にpage-break-inside: avoid;を適用することによって、セルの途中で改ページされなくなります。

こんな感じ。

image.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

artisanコマンドもっと便利なものを使っておくべきだった話

今までの自分

今までコントローラーを作成する際は

$ php artisan make:controller HogeController

それに加えて、モデルも必要だな...と思い

$ php artisan make:model Hoge

モデルがあるってことはマイグレーションも必要だ

$ php artisan make:migration hoges_create_table

ダミーデータも必要だからシーダも必要だから作る

$ php artisan make:seeder HogesSeeder

今までこんな感じで個別で必要になった際に、毎回コマンドを実行していました
もうお気づきの方もおられるかもしれませんがとても効率悪いですね。

これからの自分

すると先生から、このコマンドで一発で全部できる
これを使う方が良いと教えていただいたのです
それがこれ

$ php artisan make:model Hoge --all

なんとこれだけなんですよね
聞いたことはあったものの、いつも自分の使い慣れていたコマンドを使って使ったことがなかったこのコマンド
めちゃくちゃ便利でした。。

このコマンドで、コントローラー、モデル、マイグレーション、シーダと
必要な物全て作ってくれます

とても素敵ですね

今までの自分何してたんだと言う気持ちと
便利すぎて感動する気持ちになりました

これからは間違いなくこれを使っていくことになると思います

弱々エンジニアの気付きと新たな発見でした

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

laravel のnamespaceについて

名前空間について調べることがあったので覚書として。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravelのライブラリ「laravel-dompdf」を使ってビューの表示をPDFとして表示しよう

目的

  • ライブラリを使用して現在のビューとして表示しているコードをそのままPDFで表示する方法をまとめる

実施環境

  • ハードウェア環境
項目 情報
OS macOS Catalina(10.15.3)
ハードウェア MacBook Air (11-inch ,2012)
プロセッサ 1.7 GHz デュアルコアIntel Core i5
メモリ 8 GB 1600 MHz DDR3
グラフィックス Intel HD Graphics 4000 1536 MB
  • ソフトウェア環境
項目 情報
PHP バージョン 7.4.3
Laravel バージョン 7.0.8
  • ライブラリ環境
項目 情報 備考
laravel-dompdf v0.8.6 アプリ名ディレクトリに移動後コマンド`composer show -i

実施条件

実施方法概要

  1. コントローラの確認
  2. アクションの記載変更
  3. 確認

実施方法詳細

  1. コントローラの確認

    1. PDFとして表示したいビューファイルが呼び出されているコントローラファイルを表示する。

      <?php
      
      namespace App\Http\Controllers;
      
      use Illuminate\Http\Request;
      
      
      
      
    2. use Illuminate\Http\Request;の下に下記の内容を記載する。

      use PDF;
      
    3. コントローラファイルの設定部分が下記の様になっていることを確認する。

      <?php
      
      namespace App\Http\Controllers;
      
      use Illuminate\Http\Request;
      
      use PDF;
      
      
      
      
  2. アクションの記載変更

    1. 先に確認したコントローラファイルのビューを表示しているアクションを確認する。

      return view('ビューファイルディレクトリ名.ビューファイル名');
      
    2. 先に確認したreturn部分を下記の様に記載する。

      $pdf = PDF::loadView('ビューファイルディレクトリ名.ビューファイル名');
      #変数などの引数を伴ってビューを呼んでいる場合
      $pdf = PDF::loadView('ビューファイルディレクトリ名.ビューファイル名', compact('変数や配列などの引数'));
      return $pdf->stream();
      
  3. 確認

    1. 下記コマンドを実行してローカルサーバを起動する。

      $ cd アプリ名ディレクトリ
      $ php artisan serve
      
    2. 修正したアクションとリンクするURLにアクセスする。

    3. PDFで表示されればOKである。(日本語は文字化け表示されるが、現在の設定だと正常である。)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】初学者が更なる高みを目指して学ぶべきこと

はじめに

自分のために更なるスキルアップを目指して書いてみました。

同じく簡易的なポートフォリオサイトを作れるくらいの方々の参考になれば幸いです。

※以下、私のレベル感。

https://chobimusic.com/laravel_craftbeers/

現状


・基礎的なRESTfulサービスは作れる。(index,createstore,show,edit,update,destroyまで実装)

・ユーザー認証機能は実装できる。

・Eloquentの基本は理解している。

学ぶべきこと


①ミドルウェア
②リクエスト
③依存性の注入
④認可機能(ポリシー)

①ミドルウェア


未ログインユーザーが投稿などできないようにするために必要。

以下はindex、show以外にアクセスしようとするとログイン画面へリダイレクトされるようにしている。

//web.php
<?php
Auth::routes();
Route::get('/', 'ArticleController@index')->name('articles.index');
Route::resource('/articles', 'ArticleController')->except(['index', 'show'])->middleware('auth');
Route::resource('/articles', 'ArticleController')->only(['show']);

※app/Http/MiddlewareディレクトリのAuthenticate.phpファイル記載のroute('login')の部分を編集すればリダイレクト先を変更できる。

また、上記のようにルーティングにもいろいろ使えるメソッドが存在する。

・nameメソッド(別名:名前付きルート)
URLを生成したり、リダイレクトしたりできる。

・onlyメソッド
resourceメソッドにそのアクションのみを指定できる。

・exceptメソッド
resourceメソッドからそのアクションを除外できる。

②リクエスト


以下でリクエストは作成できる。主にフォーム周りで送信された値のバリデーションを行う。
$ php artisan make:request ArticleRequest

(コントローラーでバリデーションを行わせることもできるが、一般的にコントローラーにはあまり多くの処理を持たせないようにすることが望ましい。)

・authorizeメソッド
リクエストの対象となるリソース(ここでは記事)をユーザーが更新して良いかどうかを判定する。

・rulesメソッド
バリデーションのルールを定義する。

・attributesメソッド
バリデーションエラーメッセージに表示される項目名をカスタマイズできる。

③依存性の注入 , DI(Dependency Injection)


コントローラーにおいて、アクションメソッドの引数で型宣言を行うと、そのクラスのインスタンスが自動で生成されてメソッド内で使えるようになる。

以下のように、外で生成されたクラスのインスタンスをメソッドの引数として受け取る流れのことをDIという。

//〇〇Controller
public function edit(Article $article)
    {
        return view('articles.edit', ['article' => $article]);
    }

最初はチュートリアルをやっていると、よくこのタイプの引数を見かけて、毎度意味が分からず頭を抱えていた。

例えば、URLがarticles/1/editだとすると、idが1であるArticleモデルのインスタンスが代入される形になる。

また、ビューには'article'というキー名で、変数$articleの値(Articleモデルのインスタンス)を渡している。

④認可機能(ポリシー)


①のミドルウェアでログイン有無によるアクセスの制限はできる。

しかし、ログイン後に考慮すべき投稿コンテンツの更新・削除・編集に関してはミドルウェアだけでは制限できない。

他人の投稿を編集などできないようにするのに必要になるのが認可機能の1つであるポリシー。

ポリシーの作成

$ php artisan make:policy ArticlePolicy --model=Article //--modelをつけることでモデルに対応したポリシーになる。

ポリシーのメソッドとコントローラーのアクションメソッド対応表



























ポリシーのメソッド コントローラーのアクションメソッド
viewAny index
view show
create create,store
update edit,update
destroy destroy

ポリシーでfalseを返す場合、対応するアクションメソッドは処理されず、ステータスコード403のHTTPレスポンスがクライアントに返さる。

public function view(?User $user, Article $article) //?を付けることで引数がnullでも許容される。(未ログインでも可)
    {
        return true; //誰でも詳細画面は見れることにする。
    }

public function delete(User $user, Article $article)
    {
        return $user->id === $article->user_id; //投稿したユーザーしか削除できないようにする。
    }


コントローラーに加えることでポリシーを適用。
public function construct()
  {
    $this->authorizeResource(Article::class, 'article');
  }

・constructメソッド
クラスのインスタンスが生成された時に初期処理として呼び出さなくても必ず実行される。

・authorizeResourceメソッド
第1引数にモデルのクラス名(App/Articleでも可)、第2引数にルーティングのパラメータ名。($ php artisan route:listで出力されるURIの{}内の部分)

知っておくと便利だなと思ったもの


Null合体演算子(??)


式1 ?? 式2という形式で記述。式1がnullでない場合は式1、式1がnullである場合は、式2が結果となる。

ルーティングの確認


$ php artisan route:list

最初のころは無視してチュートリアル進めていたけれどもこれみるとミドルウェアがどのアクションメソッドに適用されているか確認できたりする。

RESTfulに関して


ほぼほぼ以下のような規則になっているので、知っているとなにかと良い。



















































メソッドアクション ルート情報 引数 メソッド
index /コントローラ GET|HEAD
create /コントローラ/create GET|HEAD
store /コントローラ Request $request POST
show /コントローラ/{id} $id GET|HEAD
edit /コントローラ/{id}/edit $id GET|HEAD
update /コントローラ/{id} Request $request, $id PUT|PATCH
delete /コントローラ/{id} $id DELETE

更なる高みを目指して


まずはこれらの機能をポートフォリオに実装してみます。

今後はProviderやフロントエンドフレームワーク(Vue.js)との連携を目指します。

読んでいただきありがとうございました。

おしまい。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む