LaravelのEloquentでwithを使う方法

Laravelでwithを使う方法を解説していきます。

Eloquentでwithを使う目的

まず、withは何のために使うかというと
リレーションを用いて、Eloquentからデータ抽出したいときに使います。
(n + 1 問題の解決もできます。)

withの使い方

前提として、下記のリレーションが設定されていることとします。
チャットルームとチャットメッセージが、chat_room_idで接続されています。
チャットルームとチャットユーザーが、chat_room_idで接続されています。

class ChatRoom extends Model
{ 

public function chatMessages()
{
return $this->hasMany('App\Models\ChatMessage', 'chat_room_id', 'id' );
}

public function chatRoomUsers()
{
return $this->hasMany('App\Models\ChatRoomUser', 'chat_room_id','id' );
} 
} 

controller上で、どのように使うのかみていきましょう。

 $chatRooms = ChatRoom::with('chatMessages')
    ->get(); 

こうすることによって、chatroomの取得と同時に、chatMessagesもリレーションして取得することが出来ます。

withを複数使うことはできるのか。

結論:はい。できます。

どのように使うのかというと非常にシンプルです。

$chatRooms = ChatRoom::with('chatMessages')
    ->with('chatRoomUsers'); 
    ->get(); 

これで、チャットルームに、チャットメッセージとチャットルームユーザーがリレーションしたデータを抽出することが可能です。

withで抽出したデータを操作したい

withでリレーションしたデータを操作したい方法です。

例えば、withでリレーションしたデータを降順にしたい、昇順にしたいといった並べ替えの変更などあると思います。

 $myApplyChatRooms = ChatRoom::with('chatRoomUsers')
    ->with(['chatMessages' => function ($query) {
        $query->orderBy('created_at', 'desc');
    }])
    ->get(); 

withの中に、Queryを追加してあげることで、自由に操作することが可能です。

Internal GD font () not available. Use only 1-5.

Laravelで intervention/image を利用した中での文字描画をする際にエラーが発生しました。

原因はフォントのパス指定です。

 $img->text('こんにちわ!', $x, $y, function($font){
    $font->file('assets\fonts\SawarabiGothic-Regular.ttf');
    $font->size(25);
    $font->color('#333333');
    $font->align('center');
    $font->valign('top');
    $font->angle(30);
}); 
$font->file('assets\fonts\SawarabiGothic-Regular.ttf');

このように指定してあげると大丈夫です。

public\assets\fontsフォルダの配下に SawarabiGothic-Regular.ttf というwebフォントを格納しております。

Laravelで intervention/image を用いて、文字を描画するために全工程を下記にて紹介しているので、参考にしてみてください。

【Intervention Image】Laravelで画像を生成(文字追加)を導入する流れ(Error対処事例多数)

Laravelを使って画像生成したい(文章を追加した画像生成)ときの流れを解説します。導入するまでに、数々のerrorを対処してきたので記録して残したいと思います。
ライブラリの導入は正しく把握していないと苦労が多いですね…!!

環境:
Laravel 7
dokcer
docker-compose

必要な要素:

1:intervention/imageのインストール
2:開発環境へGDのインストール
3: intervention/image で画像を生成
4: intervention/image で画像 に文字を描画する

こちらの流れです。

1:intervention/imageのインストール

まずは、ライブラリのインストールです。
composerでインストールしていきます。

composer require intervention/image 

intervention/imageをファザードで活用するために設定を追加していきます。

> config/app.php
の中に2か所追加していきます。

 'providers' => [     
// 省略 
Intervention\Image\ImageServiceProvider::class ]


'aliases' => [ 
// 省略
'Image' => Intervention\Image\Facades\Image::class ] 

これにて基本の設定は完了です。
しかし、これだけで使用してみようとすると、errorがでます。

たとえば、
簡単に intervention/image を使うように下記を実行してみてください。

 use Intervention\Image\Facades\Image; 

//省略

public function imagerotate()
{
$path = storage_path('app/public/profile/profiledefault.png');
$img = Image::make($path);
$img->rotate(-45);
$save_path = storage_path('app/public/profile/profiledefault222.png');
$img->save($save_path); 
}

storage>app/public/profile/ フォルダを作成して、その中にprofiledefault.png を格納

これだと、下記のようなエラーがでると思います。
(正しくGDがインストールされている場合は問題ないです。)

GD Library extension not available with this PHP installation.

intervention/image を使うには、GDというライブラリも必要だということですね。

2:開発環境へGDのインストール

それでは、GDを開発環境にインストールしていきます。
dockerを使っているので、そちらへインストールしていきます。

RUN apt-get install -y zlib1g-dev \ 
    libzip-dev \
    libjpeg-dev \
    libpng-dev \
    libfreetype6-dev \
    libjpeg62-turbo-dev
RUN docker-php-ext-configure \
    gd --with-freetype-dir=/usr/include --with-png-dir=/usr/include --with-jpeg-dir=/usr/include
RUN docker-php-ext-install pdo_mysql zip gd 

関係している部分のみ記述しています。

RUN docker-php-ext-install でgdをインストールしているのですが、
gdをインストールするために
・RUN apt-get install
・RUN docker-php-ext-configure
を使って必要なものを準備しています。

--with-freetype-dir=/usr/include

こちらが無くても、画像の処理は可能です。
ただし、これが無いと画像に文字を描画することができません。

正しく動いたdockerfileのみ記述しましたが、こちらを整えるまでに幾つかのerrorがありました….

configure: error: jpeglib.h not found.
ERROR: Service 'php' failed to build: The command '/bin/sh -c docker-php-ext-configure  gd --with-png-dir=/usr/include --with-jpeg-dir=/usr/include' returned a non-zero code: 1 

errorの原因と対処法 ↓ ↓ ↓ ↓

 Call to undefined function Intervention\Image\Gd\imagettfbbox() 

errorの原因と対処法 ↓ ↓ ↓ ↓

それぞれ個別にerrorの原因と対処法を記述しましたので、そちらも参考にしてみ下さい。

3: intervention/image で画像を生成

ここまでくれば、画像を生成することができると思います。

前述した、下記を実行して確認してみてください。

use Intervention\Image\Facades\Image; 

//省略

public function imagerotate()
{
$path = storage_path('app/public/profile/profiledefault.png');
$img = Image::make($path);
$img->rotate(-45);
$save_path = storage_path('app/public/profile/profiledefault222.png');
$img->save($save_path); 
} 
// storage>app/public/profile/ フォルダを作成して、その中にprofiledefault.png を格納 

4: intervention/image で画像 に文字を描画する

いよいよ最後です。
画像に文字を描画していきます。

文字を描画する方法は、下記です。
canvasの作り方は他にもあります。例えば、既存の画像を使用することも可能です。

$x = 40;
$y = 20;
$img = Image::canvas(120, 60, '#fff');
$img->text('こんにちわ!', $x, $y, function($font){
    $font->file('assets\fonts\SawarabiGothic-Regular.ttf');
    $font->size(25);
    $font->color('#333333');
    $font->align('center');
    $font->valign('top');
    $font->angle(30);
});
$save_path = storage_path('app/public/profile/profiledefault222.png');
$img->save($save_path); 

public\assets\fontsフォルダの配下に SawarabiGothic-Regular.ttf というwebフォントを格納しております。

このフォントのパス指定も色々あるようです。
パス指定を間違えると、下記errorがでましたの注意して下さい。

 Internal GD font () not available. Use only 1-5. 

Call to undefined function Intervention\Image\Gd\imagettfbbox()

Laravelで intervention/image を利用した中でのerror解決方法を解説します。

環境:
Laravel 7
dokcer
docker-compose

errorの原因

intervention/image で文字を描画するためのライブラリが入っていない

解決方法

freetype を追加することです。

dockerfile
error時:

RUN apt-get install -y zlib1g-dev \ 
    libzip-dev \
    libjpeg-dev \
    libpng-dev \
RUN docker-php-ext-configure \
    gd --with-png-dir=/usr/include --with-jpeg-dir=/usr/include
RUN docker-php-ext-install pdo_mysql zip gd 

dockerfile
解決後:

RUN apt-get install -y zlib1g-dev \ 
    libzip-dev \
    libjpeg-dev \
    libpng-dev \
    libfreetype6-dev \
    libjpeg62-turbo-dev
RUN docker-php-ext-configure \
    gd --with-freetype-dir=/usr/include --with-png-dir=/usr/include --with-jpeg-dir=/usr/include
RUN docker-php-ext-install pdo_mysql zip gd

こちらを追加して完了です。

Laravelで intervention/image を用いて、文字を描画するために全工程を下記にて紹介しているので、参考にしてみてください。

configure: error: jpeglib.h not found. ERROR: Service ‘php’ failed to build:

Laravelで intervention/image を利用した中でのerror解決方法を解説します。

環境:
Laravel 7
dokcer
docker-compose

errorの原因

GDをインストールする際に他にもインストール必須のものがあり、そちらもインストールしてね~。ということです。

解決方法

dockerfile
error時:

RUN docker-php-ext-configure \
    gd --with-png-dir=/usr/include --with-jpeg-dir=/usr/include
    # gd --with-png-dir=/usr/include --with-jpeg-dir=/usr/include
RUN docker-php-ext-install pdo_mysql zip gd  

dockerfile
解決後:

RUN apt-get install -y zlib1g-dev \ 
    libzip-dev \
    libjpeg-dev \
    libpng-dev \
RUN docker-php-ext-configure \
    gd --with-png-dir=/usr/include --with-jpeg-dir=/usr/include
RUN docker-php-ext-install pdo_mysql zip gd 

    libzip-dev \
    libjpeg-dev \
    libpng-dev \

こちらをapt-get install していく必要があります。

Laravelで intervention/image を用いて、文字を描画するために全工程を下記にて紹介しているので、参考にしてみてください。

Laravelの認証確認メール・パスワードリセットメールを日本語化する方法

Laravel 7での、取り組みです。

Laravelは、メール送付機能を持っていますが、デフォルト設定は勿論英語の状態です。今回は、認証確認メール・パスワードリセットメール送付における日本語化を紹介していきます。

bladeを直接日本語へ変換するやり方もあるかと思いますが、お勧めしません。
というのも、Laravelでは、email送付の雛形を定めておいて、中身を認証確認メール・パスワードリセットメールと状況に応じて使い分けているので直接編集してしまうと、上手く切り替えが難しくなってしまうと思います。
あくまで、Laravelの設計に沿って日本語化していく方法を進めていきます。

ポイント:
1:メールの雛形を作っている php
2:メールの中身を作っている php
3:英語から日本語へ変換する設定

1:メールの雛形を作っている php

まずは、メールの雛形を作っている部分を紹介します。

vendor/laravel/framework/src/Illuminate/Notifications/resources/views/email.blade.php 

こちらのbladeがemail内容の雛形です。

{{ $line }} 、 {{ $actionText }}  などが後から紹介する「 2:メールの中身を作っている php 」部分で生成されて流れてきます。
ここの部分が、認証確認メール・パスワードリセットメールでは切り替えられています。

ここの「vendor」配下のbladeをいじっても内容を変更することは可能ですが、避けましょう。というのもバージョン変更などがあった際に上書きされてしまう場所だからです。

このbladeを編集できるように、オーバーライドするカタチで複製する方法があります。
それが下記のコマンドです。

 php artisan vendor:publish --tag=laravel-notifications 

こちらを実行すると、先ほどのbladeと同じ内容が、

resources/views/vendor/Notifications /email.blade.php 

に複製されます。
ここを編集したものが、メールの雛形として反映されます。
(オーバーライドされます。)

このemail.blade.php 日本語に変換しても、日本語文章を送ることは出来ますが、冒頭に言及した通りオススメは出来ません。
どうやって、日本語化していくは後述していきます。

その前に、2:メールの中身を作っている php を見ていきます。

2:メールの中身を作っている php

認証確認メール・パスワードリセットメールでファイルが違います。

パスワードリセットメール:

vendor/laravel/framework/src/Illuminate/Auth/Notifications/ResetPassword.php 

認証確認メール:

vendor/laravel/framework/src/Illuminate/Auth/Notifications/VerifyEmail.php

こちらで、色々な処理が行われています。

今回は文章の内容だけに注目していきます。

認証確認メール: の方で確認していきます。

return (new MailMessage)     
->subject(Lang::get(‘Verify Email Address’))    
 ->line(Lang::get(‘Please click the button below to verify your email address.’))     
->action(Lang::get(‘Verify Email Address’), $verificationUrl)     
->line(Lang::get(‘If you did not create an account, no further action is required.’));

この、 subject 、line、actionなどが、先ほどの、メールの雛形に送られます。
このままだと、英語がそのまんまおくられています。
・Verify Email Address  
・ Please click the button below to verify your email address.
などです。

これを、日本語に変換していきます。

3:英語から日本語へ変換する設定

2つの処理をしていきます。
・ config/app.php で日本語入力へ反映する指示
・英語文章から変換される日本語を指示

config/app.php で日本語入力へ反映する指示

 config/app.php

-'timezone' => 'UTC', 
+'timezone' => 'Asia/Tokyo', 


-'locale' => 'en', 
+'locale' => 'ja', 

-'faker_locale' => 'en_US', 
+'faker_locale' => 'ja_JP', 

上記、3箇所変更して下さい。

英語文章から変換される日本語を指示

resources/lang/ja.json

下記の位置に、ja.jsonというjsonファイルを作成してください。

 {
 "Thank you.": "ご利用頂きまして誠にありがとうございます。",
 "Verify Email Address": "メール認証をして登録を完了して下さい。",
 "Please click the button below to verify your email address.": "下のボタンをクリックしてメールアドレスの認証を完了してください。",
 "If you did not create an account, no further action is required.": "アカウントを作成していない場合は、何もしなくて大丈夫です。",
 "If you’re having trouble clicking the,": "もしもボタンをクリックしてもサイトへ遷移しない場合は、",
 "copy and paste the URL below": "下記のURLをコピーして",
 "into your web browser:": "ブラウザで反映して下さい。"
}

 

jsonファイルは上記のように、英語から日本語に変換したい対応を記述していきましょう。

先ほど紹介した

vendor/laravel/framework/src/Illuminate/Auth/Notifications/VerifyEmail.php ( ResetPassword.php  )

の中の、英語に対応する部分を日本語化していくこともできますし

return (new MailMessage)     
->subject(Lang::get(‘Verify Email Address’))    
 ->line(Lang::get(‘Please click the button below to verify your email address.’))     
->action(Lang::get(‘Verify Email Address’), $verificationUrl)     
->line(Lang::get(‘If you did not create an account, no further action is required.’));

雛形に存在している英語の中で

resources/views/vendor/Notifications /email.blade.php 

@lang( )で囲まれている部分も、日本語に変換できます。

たとえば、

@lang(‘Regards’)

@lang(‘Hello’)

などありますよね。
これに対応する日本語をjsonファイルに反映すれば、英語ではなくて日本語が反映されます。

Laravelで画像をアップロードするディレクトリを指定する方法

今回の記事は、Laravelでの画像アップロードの流れをある程度理解している方を対象としています。

画像アップロードについて、全体の流れは書きません。
ポイントは、
・画像アップロードのディレクト指定方法
・シンボリックリンクの方法
・画像の呼び出し方

この3点です。

画像アップロードのディレクト指定方法

画像をアップロードするディレクトリを指定する方法は
controller中で storeにディレクトリを指定します。

$fileImage = $request->file('image')->store('public/profile');
$user->image_path = basename($fileImage);

今回指定したのは、public/profile ディレクトリです。

store('public/profile');

これが実行されると
storage/appの配下にディレクトリが作成されます。
今回ので言うと
storage/app/public/profile ディレクトリが作成されて、
その配下に、画像がアップロードされます。

シンボリックリンクの方法

シンボリック方法です。

php artisan storage:link 

こちらのコマンドでpublic と storageが連携されるのは分かっているが、ディレクトを追加した際に、どうなるのか分からないという方もいるかと思います。

心配いりません。
こちらのコマンドを実行すると、publicディレクトリに、storageがリンクされます。

画像の呼び出し方

では、このリンクさせた画像を呼び出してみましょう。

 <img src="{{ asset('storage/profile/' . $user->image_path) }}" 
 ※$user->image_path storeする際に、保存していたファイル名 

これで、指定したディレクトリからファイルを呼び出すことが可能です。

【所要時間:1分で】Laravelの言語設定(エラー文言など)を日本語に変更する方法

Laravelで、日本語に変更する方法を紹介します。
Defaultでは、english指定かと思います。

言語設定はどこで制御されているかというと、
・言語ファイル:resources/lang/の配下(デフォルトでは、enフォルダが存在)
・ファイルの指定方法:config/app.php の  ‘locale’ で指定

なので、実施する必要があることは

1:言語ファイルのインストール
2:ファイル指定を日本語版のファイルを指定

この2種類です。

1:言語ファイルのインストール

Laravelのバージョンで少しやり方が異なる可能性もあります。
今回は、Laravel7のやり方です。

公式に記載されている通りですが

https://readouble.com/laravel/7.x/ja/validation-php.html

以下3つの、コマンド入力していきます。

コマンドを実行するディレクトリは、ルートディレクトリで大丈夫です。

以下、3つのコマンドを実行してください。

php -r "copy('https://readouble.com/laravel/7.x/ja/install-ja-lang-files.php', 'install-ja-lang.php');" 
php -f install-ja-lang.php 
php -r "unlink('install-ja-lang.php');" 

そうすると、
resources/lang/の配下 に jaフォルダが生成されます。

これで、日本語版ファイルの生成は完了です。

2:ファイル指定を日本語版のファイルを指定

いま、インストールしたファイルを呼び出すように、指定方法を変更しましょう。

config/app.php に入り、

 // 'locale' => 'en',  //コメントアウト(削除でも可) 
    'locale' => 'ja',

localeをjaに指定してください。

ついでに、timezoneも変更しましょう。

 // 'timezone' => 'UTC', //コメントアウト(削除でも可)
    'timezone' => 'Asia/Tokyo',

以上で、完了です。
およそ、1分程で完了するかと思います。
日本語を変更するには、生成したファイルを変更していくことで可能です。

Laravelのページネーション内容を新しい順番へ変更する方法

Laravelはページネーション機能を簡単に実装できるメソッドが組み込まれています。

一番簡単なのは、 simplePaginate に引数を渡す方法かと思います。

$posts = Post::simplePaginate(10); 

このままだと、PostのDBの古い順番からページネーションされてしまいます。

これを新しい順番へ変更します。

 $posts = Post::latest( 'created_at' )
 ->simplePaginate(10); 

latest()メソッドを追加することで、順番が変更されます。

LaravelのRoute設定で、同一階層(prefix)の中で認証あり、なしを分ける方法

LaravelのRoute設定を効率的にする方法をご紹介していきます。

一定慣れている方であれば、
・ディレクトリをまとめるために:prefix
・認証処理をまとめるために: middleware(‘auth’)
などを使うかたもいると思います。

これらを使う際に、同じディレクトリ階層だけども、認証が必要なページと、不要なページどちらもある、といったケースでの記述方法を紹介していきます。

やり方は色々とあります。

例えば、下記です。

 
Route::prefix('/article')->name('rec.')->group(function () {

    Route::get('/top', 'ArticleController@rec_top')->name('top');
    Route::get('/tag/{tag_id}', 'ArticleController@tag')->name('tag');

    Route::middleware('auth')->group(function () {
        Route::get('/postadd', 'ArticleController@postadd')->name('postadd');
        Route::post('/postdone', 'ArticleController@postdone')->name('postdone');
        });
});
 

まずは、下記のprefixで括ってしまいます。

 Route::prefix('/article')->name('rec.')->group(function () { }

その中に、

 Route::middleware('auth')->group(function () { }

括られるものと、括られないもので、認証あり、なしを分けていきます。