20200731のlaravelに関する記事は8件です。

【Laravel】名前付きルートを設定して、ルート定義をもっと便利にしよう

Laravelのルートインスタンスには、nameメソッドという「定義したルートに名前をつける」便利なものがあります。
ルートインスタンスに、このnameメソッドをチェーンするだけなので気軽に使用できます。

routes/web.php
Route::get('user/profile', function () {
    //
})->name('profile');

上記の例ではルートに「profile」という名前が付いています。
このように名前が付けられることによって、
特定のルートへのURLを作成できたり、
または、リダイレクト時にルート定義で付けた名前を指定することが可能になります。

もちろん、コールバックがクロージャではなく、コントローラアクションの場合でも名前付きルートが設定できます。

routes/web.php
Route::get('user/profile', 'UserProfileController@show')->name('profile');

こちらも、「profile」という名前が付きました
こんな感じで、名前付きルートを設定してみましょう。

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

Docker for MacのLaravelが遅いから速くしたい

要約

  • Docker for Macのファイルマウントが遅すぎるので、ファイルマウント量を減らす
  • ファイルマウントに:delegatedや:cachedを使う
  • php.iniの設定でOPcacheを有効化する
  • composerも遅いのでリポジトリの変更し、プライグイン導入

ファイルマウント量を減らす、かつマウントする時は:delegatedや:cachedを使う

  • .gitはマウントする意味がないので、除外する
  • マウントがどうしても必要な時は:delegatedや:cachedを使う

docker-compose.yml
version: '3'
services:
  web:
    image: nginx:${Version}
    ports:
      - "8000:80"
    depends_on: # 追加
      - app
    volumes:
      - ./docker/web/default.conf:/etc/nginx/conf.d/default.conf
      - .:/var/www/html:delegated #:delegatedを追加
      - exclude:/var/www/html/laravel-dir/.git #追加
    container_name: web

  app:
    build: ./docker/php
    volumes:
     - .:/var/www/html:delegated #:delegatedを追加
     - exclude:/var/www/html/laravel-dir/.git #追加
    depends_on:
      - mysql

  mysql:
    image: mysql:5.7
    environment:
      MYSQL_DATABASE: hoge
      MYSQL_USER: hoge
      MYSQL_PASSWORD: hoge
      MYSQL_ROOT_PASSWORD: hoge
    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql:cached #:cachedを追加

volumes:
  exclude: #空のVolumeを追加
  mysql-data:

php.iniの設定でOPcacheを有効化する

php.ini
~~省略~~
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=60
opcache.fast_shutdown=1
opcache.enable_cli=1

composerも遅いのでリポジトリの変更し、プライグイン導入

FROM php:7.4-fpm

~~省略~~

# composerの高速化
RUN composer config -g repos.packagist composer https://packagist.jp && composer global require hirak/prestissimo

WORKDIR /var/www/html

参考

光遅い問題に対応して Composer を100倍速くする
Macのdockerが遅いストレスから解放されよう
Laravel で 最適化 高速化 手法一覧

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

LaravelでRedisを操作する

目次

Laravelの記事一覧は下記
PHPフレームワークLaravelの使い方

Laravelバージョン

動作確認はLaravel Framework 7.19.1で行っています

前提条件

eclipseでLaravel開発環境を構築する。デバッグでブレークポイントをつけて止める。(WindowsもVagrantもdockerも)
本記事は上記が完了している前提で書かれています
プロジェクトの作成もapacheの設定も上記で行っています

LaravelでDIを使う
本記事は上記で作成したフォルダとファイルを使用します

PhpRedisのインストール

PhpRedisを介してRedisを操作します
下記リンクで環境構築した人はインストールされているはずです
LAMP+Redis環境を超短手数で構築する
インストールしていない人は下記リンクに従ってインストールしてください
phpredis インストール

設定

(1) /sample/.env修正
Redisへアクセスするための設定を書く

‥‥
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
‥‥

REDIS_HOST、REDIS_PASSWORD、REDIS_PORTを自分の環境に合ったものにしてください
vagrantのforwarded_port設定でポートを変えたりしている場合、自分の環境にあった値に変えてください

(2) /sample/config/database.php修正
.envに書いたRedis接続定義はdatabase.phpで使われています
database.phpに定義されている配列の'redis'=>'default'要素修正、'redis'=>'db2'要素追加

‥‥
'redis' => [
‥‥
        'default' => [
            'url' => env('REDIS_URL'),
            'host' => env('REDIS_HOST', '127.0.0.1'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', '6379'),
            'database' => env('REDIS_DB', '0'),
        ],

        'db2' => [
            'url' => env('REDIS_URL'),
            'host' => env('REDIS_HOST', '127.0.0.1'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', '6379'),
            'database' => '2',
        ],
‥‥

Redisへの接続定義を2つ作りました

(3) /sample/config/app.php修正
aliases要素内のRedisをコメントにする

‥‥
//'Redis' => Illuminate\Support\Facades\Redis::class,
‥‥

サービスクラス作成

(1) /sample/app/Services/InterfacesフォルダにRedisService.php作成

RedisService.php
<?php
namespace App\Services\Interfaces;

interface RedisService
{
    public function __construct();

    public function setKey1($value);
    public function getKey1();

}

(2) /sample/tests/Services/ImplフォルダにRedisServiceImpl.php作成

Tests\Services\Impl\RedisServiceImpl.php
<?php
namespace Tests\Services\Impl;

use App\Services\Interfaces\RedisService;

class RedisServiceImpl implements RedisService
{

    public function __construct()
    {
    }

    public function setKey1($value)
    {
    }

    public function getKey1()
    {
    }

}

(3) /sample/app/Services/ImplフォルダにRedisServiceImpl.php作成

App\Services\Impl\RedisServiceImpl.php
<?php
namespace App\Services\Impl;

use App\Services\Interfaces\RedisService;
use Illuminate\Support\Facades\Redis;

class RedisServiceImpl implements RedisService
{

    private $redis = null;

    public function __construct()
    {
        $this->redis = Redis::connection('db2');
    }

    public function setKey1($value)
    {
        Redis::set('key1', 'default_' . $value);
        $this->redis->set('key1', 'db2_' . $value);
    }

    public function getKey1()
    {
        $default = Redis::get('key1');
        $db2 = $this->redis->get('key1');

        return [$default, $db2];

    }

}

static関数としてRedis::setのように書くと、さきほどdatabase.phpに書いたdefault接続が使われます。
他の接続を使いたい場合は、Redis::connection('db2');のように明示的に接続を取ってください
Redisクラスのメソッド名はRedisコマンド名がそのまま使えます

DI登録

(1) /sample/app/Providers/DiServiceProvider.phpに下記を追記
use App\Services\Interfaces\RedisService;

(2) /sample/app/Providers/DiServiceProvider.phpのregisterメソッドに下記を追記
app()->singleton(RedisService::class, $prefix . 'RedisServiceImpl');

DiServiceProvider.phpはLaravelでDIを使うで作成したファイルです
LaravelでDIを使うでconfig/app.phpのprovidersに登録してあります

Controllerにメソッド追加

(1) /sample/app/Http/Controllers/SampleController.phpにuse文を追記
use App\Services\Interfaces\RedisService;

(2) /sample/app/Http/Controllers/SampleController.phpにredis1メソッド、redis2メソッドを追記

SampleController.php
    public function redis1(Request $request, RedisService $redisService)
    {
        $key1Value = $request->input('key1');

        if (!is_null($key1Value)) {
            $redisService->setKey1($key1Value);
        }

        return view('sample.redis1');

    }

    public function redis2(RedisService $redisService)
    {
        $key1Value = $redisService->getKey1();

        $data = ['key1Value' => var_export($key1Value, true)];

        return view('sample.redis2', $data);
    }

(3) /sample/routes/web.phpに下記を追記
Route::get('sample/redis1', 'SampleController@redis1');
Route::get('sample/redis2', 'SampleController@redis2');

viewの作成

(1) /sample/resources/views/sample/redis1.blade.phpファイル作成

redis1.blade.php
<html>
    <head>
        <title>sample</title>
    </head>
    <body>

        <form action="{{ url('sample/redis1') }}" method="get">
            <div>key1<input type="text" name="key1" value=""></div>
            <input type="submit" >
        </form>

    </body>
</html>

(2) /sample/resources/views/sample/redis2.blade.phpファイル作成

redis2.blade.php
<html>
    <head>
        <title>sample</title>
    </head>
    <body>

        <div>{{$key1Value}}</div>

    </body>
</html>

動作確認1

http://localhost/laravelSample/sample/redis1
a.png
何か値を入れて送信ボタンをクリック

http://localhost/laravelSample/sample/redis2
b.png
sample/redis1で入力した値が出てくる

redisを見てみる

127.0.0.1:6379> select 0
OK
127.0.0.1:6379> keys *
1) "laravel_database_key1"

laravel_database_という接頭辞が付いた形で保存されています
これはconfig/database.phpのredis=>options=>prefix要素で接頭辞を設定しているためです

127.0.0.1:6379[2]> select 0
OK
127.0.0.1:6379> get laravel_database_key1
"default_value1"
127.0.0.1:6379> select 2
OK
127.0.0.1:6379[2]> get laravel_database_key1
"db2_value1"
127.0.0.1:6379[2]>

redisにも値が入っていることがわかります

sessionの格納先をRedisにする

(1) /sample/.env修正
sessionの設定を書く

‥‥
#SESSION_DRIVER=file
SESSION_DRIVER=redis
SESSION_CONNECTION=db2
‥‥

SESSION_DRIVERをredisに変える。SESSION_CONNECTIONに格納先のRedis接続を指定する

動作確認2

Laravelでセッションを使う
上記記事で作成した
http://localhost/laravelSample/sample/session1
にアクセスする

redisを見てみる

127.0.0.1:6379[2]> select 2
OK
127.0.0.1:6379[2]> keys *
1) "laravel_database_laravel_cache:xxxxxxxxxxxxxxxxxxxxxx"

Redisに入っていることがわかります

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

PHP Laravel `?:`の正体を知ってすっきりした話

目的

  • 先輩方が開発に携わったLaravelアプリのソースコードをみていたら自分の知らない処理が出てきて驚いた話をまとめる

初見のコード

  • 自分が初めて見たコードを下記に記載する。

    変数 = 比較対象A === 比較対象B ?文字列1:文字列2;
    

簡単な解説

  • 処理内容を下記に簡単に記載する。
    1. 比較対象Aと比較対象Bを比較する。
    2. データ型も含めて比較し、一致しているのかしていないのかを確認する。
    3. 一致していた(true)の場合、文字列1が変数に格納される。
    4. 一致していない(false)の場合、文字列2が変数に格納される。
  • この?:を用いた記載(?:)は条件演算子と呼ばれる物である。
  • 下記に処理を記載する。

    条件式 ?式1:式2;
    
  • 上記の様な処理の場合、条件式が真(true)の時に式1を実行し、偽(false)の時に式2を実行する。

具体例

  • 下記の様なコードを実行した時の結果を考える。

    $a = 'staging';
    $b = 'dev';
    
    echo $a === $b ? 'OK' : 'NO';
    
  • 上記を実行すると「NO」と出力される。

  • 下記の様なコードを実行した時の結果を考える。

    $a = 'dev';
    $b = 'dev';
    
    echo $a === $b ? 'OK' : 'NO';
    
  • 上記を実行すると「OK」と出力される。

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

【Laravel】マイグレーションとシーディング

こちらの記事は以下の書籍を参考にアウトプットとして執筆しました。
PHPフレームワークLaravel入門 第2版

マイグレーションとは

今使っているDBと同じ構造のDBを再現する仕組み

DBのバージョン管理機能があり、DB移行や新規作成がPHPスクリプトでできる。

マイグレーションの手順

専用スクリプトを作り、スクリプトを書き、実行する

マイグレーションファイル作成

php artisan make:migration ファイル名

出典PHPフレームワークLaravel入門 第2版

作成されたファイルの中身について

テーブルを作成する処理を書くupメソッドと、
テーブル削除する処理を書くdownメソッドの2つのメソッドがテーブル操作の基本

テーブル生成

タイムスタンプの設定

この書籍では$talbe->timestamp()を実行するとcreated_atとupdated_atが作成されると述べています。

テーブル削除

テーブルを削除(テーブルがない場合はエラー)

Schema::drop(テーブル名)

テーブルを削除(テーブルがあれば削除)

Schema::dropIfExists(テーブル名)

マイグレーションの実行コマンド

php artisan migrate

これでdatabase/migrations野中のファイルが実行される。

シーディング

マイグレーションでテーブルを作成してとき、最初にレコードを登録する
この機能をシーディング機能という

以下コマンドでシーダーファイルを作成する

php artisan make:seeder シーダーファイル名

このあとrunメソッドにレコードを作成するコードを書く

そしたらシーダーファイルが実行されるようにDatabaseSeederに登録する

このDatabaseSeederがシーダコマンドで実行される。

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

Laravel 公式ドキュメント 目次の変化 5.5 ⇒ 6.x

基礎

エラーとログ ⇒ エラー処理、ログとして別ページ

セキュリティ

メール確認追加

テスト

コンソールテスト追加

公式パッケージ

Duck追加
Telescope追加

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

新卒がLaravelでDIの流れを追う(サービスプロバイダーとコンテナ)

用語

DIとは

Dependency Injection。依存を回避しながらオブジェクトを注入するということ。
コンテナという容器に、いろいろなクラスのインスタンスを入れてあげる。アプリではそのコンテナが与えられているので、必要な時に、その中から任意のインスタンスを取り出して使ってあげる。

いったんコンテナという容器にインスタンスを入れる作業をしてやり、その後アプリではコンテナからインスタンスを取り出している。間接的なインスタンスの使用って感じ。こうすると保守がし易い。

サービスプロバイダー

LaravelでDIするためのクラス。今回のサービスプロバイダーではコンテナの中にクラス作成のためのメソッドを格納して、必要な時にそのメソッドを発動させてインスタンスを作り返すようになっている。

サービスの登録

登録を遡る

まずサービスプロバイダーから追っていく。register()でサービスを登録しているようだが、appとbindが謎なのでServiceProviderを追う。
こいつはlaravel自体のコードなので見に行く。

アプリのServiceProvider
use Illuminate\Support\ServiceProvider;

class SampleServiceProvider extends ServiceProvider
{
    public function register() { 
    $this->app->bind('Sample', function($app){
        Return new Sample();
    });
    }
}

⬇️
コンストラクタ でappがプロパティとして登録されている。そのappってのは\Illuminate\Contracts\Foundation\Applicationなんだとか。

framework/src/Illuminate/Support/ServiceProvider.php
namespace Illuminate\Support;

abstract class ServiceProvider
{ 
    /**
    * Create a new service provider instance.
    * 
    * @param  \Illuminate\Contracts\Foundation\Application  $app 
    * @return void 
    */ 
    public function __construct($app)
    {
        $this->app = $app;
    }

}

⬇️

Containerを継承している。コンテナにサービスをぶち込むというイメージなのだろう。Containerを確認。

framework/src/Illuminate/Foundation/Application.php
class Application extends Container implements ApplicationContract, CachesConfiguration, CachesRoutes, HttpKernelInterface
{
.
.
.
}

⬇️
bindメソッドを発見。
いろいろやっていたがcompactを使って、bindingsというプロパティーに\$abstractをキーにして$concreteを格納している。

framework/src/Illuminate/Container/Container.php
class Container implements ArrayAccess, ContainerContract
{
    public function bind($abstract, $concrete = null, $shared = false) {
    .
    .
    .
    $this->bindings[$abstract] = compact('concrete', 'shared');
    .
    .
    .
    }
}

サービスプロバイダに戻って確認

use Illuminate\Support\ServiceProvider;
use App\Sample;

class SampleServiceProvider extends ServiceProvider
{
    public function register() { 
    $this->app->bind('Sample', function($app){
        Return new Sample();
    });
    }
}

containerインスタンスのbindingsにSampleというキーで、Sampleクラスのインスタンス作成のためのメソッドがバリューとして登録されることになる。

登録のイメージ

以下の登録のイメージは自分の想像で書いています。間違っていたらすいません。

コンテナにいろいろなメソッド(必要インスタンスを作成)を登録するために、まず一つ目のサービスプロバイダーのプロパティーにコンテナインスタンスを代入。
⬇️
登録処理
⬇️
一つ目のサービスプロバイダーのコンテナプロパティーを、二つ目のサービスプロバイダーのプロパティーに代入。
⬇️
繰り返し

串カツ(コンテナインスタンス)をいろいろなタレ(サービスプロバイダー)に付けている感じ。
スクリーンショット 2020-07-31 9.05.05.png

サービスの使用

使用を遡る

サービスを使用する時は以下のように読み出してあげるんだとか。app()でコンテナが得られ、その後makeコマンドを実行している。makeを追う。

アプリのcontroller
$sample = app()->make('Sample');

⬇️
make()によって、$this->bindingsから必要なメソッド(インスタンスを作成する)を取り出し、そいつを返している。

framework/src/Illuminate/Container/Container.php
class Container implements ArrayAccess, ContainerContract
{

    public function make($abstract, array $parameters = []) { 
        return $this->resolve($abstract, $parameters); 
    } 

    protected function resolve($abstract, $parameters = [], $raiseEvents = true) {

        $concrete = $this->getContextualConcrete($abstract);
        .
        .
        .
        $object = $this->build($concrete);
        .
        .
        .
        return $object;
    }

    protected function getContextualConcrete($abstract) {

        if (! is_null($binding = $this->findInContextualBindings($abstract))) {
            return $binding; //ここで$this->bindingsから必要なインスタンスを作成するメソッドを取り出している
        }
        .
        .
        .
    }

    public function build($concrete) {

        if ($concrete instanceof Closure) {
            //$concreteが無名関数ならば、発動させて返す
            return $concrete($this, $this->getLastParameterOverride());
        }
        .
        .
        .
    }
}

参考文献

Laravelのサービスプロバイダーの仕組みやメリットとは
Laravel

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

herokuでホストしてたlaravelアプリをlightsailに移動してドメイン張り替えとかした作業ログ

1.インスタンス立ち上げ

スクリーンショット 2020-07-30 20.46.17.png

2.documentroot確認

スクリーンショット 2020-07-30 20.47.00.png
スクリーンショット 2020-07-30 20.47.39.png

3.デプロイ

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

Envoyと言う公式のデプロイタスク管理ツールがあるのでコレでデプロイスクリプトを管理してみる

Envoy.blade.php
@servers(['web' => ['-i ~/.ssh/LightsailDefaultKey-ap-northeast-1.pem bitnami@54.95.226.129']])

@task('deploy', ['on' => 'web'])
cd ~/htdocs/ta9to/
git pull origin master
composer install --optimize-autoloader --no-dev
php artisan config:cache
php artisan route:cache
php artisan view:cache
@endtask

4.Laravel動いてるの確認

# DocumentRoot設定
$ vim /opt/bitnami/apache2/conf/bitnami/bitnami.conf
<VirtualHost _default_:80>
  #DocumentRoot "/opt/bitnami/apache2/htdocs"
  DocumentRoot "/opt/bitnami/apache2/htdocs/ta9to/public"
# apache再起動
$ sudo /opt/bitnami/ctlscript.sh restart apache

スクリーンショット 2020-07-30 21.22.03.png

5.mysql設定

# mysqlパスワード確認
$ bitnami@ip-172-26-11-51:~$ cat /home/bitnami/bitnami_application_password

6.表示確認

スクリーンショット 2020-07-30 22.09.20.png

7.ドメイン張り替え
スクリーンショット 2020-07-30 22.15.30.png

8.Aレコード追加+レジストリのネームサーバ置き換え
スクリーンショット 2020-07-31 1.38.23.png

9.https設定
https://aws.amazon.com/jp/premiumsupport/knowledge-center/linux-lightsail-ssl-bitnami/

$ sudo /opt/bitnami/bncert-tool

↑のコマンドがapacheのconfに追記してくれるのでまたdocumentroot書き換える

/opt/bitnami/apache2/conf/bitnami/bitnami.conf
<VirtualHost _default_:443>
  #DocumentRoot "/opt/bitnami/apache2/htdocs"
  DocumentRoot "/opt/bitnami/apache2/htdocs/ta9to/public"
  SSLEngine on

10.完了
https://www.ta9to.com/blog/posts

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