20200804のPHPに関する記事は11件です。

【PHP・laravel】クエリパラメータを送る時まとめ(getとrequest)

初歩的なことですが、調べてもなかなか出てこなかったため、記録します。

HTMLからPHP側に送る

sample1.laravel.php
<a harf="http://ここがURL?suji=1">送信</a>
sample2.laravel.php
<a harf="http://ここがURL?moji='文字'">送信</a>

php側

index.php
$get1 = $_GET['suji'];//1
$get2 = $_GET['moji'];//'文字'

PHP内のやり取り(関数から関数)

数値や文字を送るとき

index.php
function a(){
  redirect('/b?suji=1');
}

function b(){
  $request1 = $_REQUEST['suji']//1
}
index.php
function a(){
  redirect("/b?moji='文字'");
}

function b(){
  $request2 = $_REQUEST['moji']//文字
}

変数を送るとき

index.php
function a(){
  $count = 2;
  redirect('/b?count='.$count);
}

function b(){
  $request3 = $_REQUEST['count']//2
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravelのブログ開発でmarkdown対応させてみた

はじめに

Laravelを使ってブログを開発している際に見出しや装飾を本文に反映させてみたいな
と思い、markdown対応させてみました。
至らない点がありますが暖かい目でみてやってください。

使用するmarkdown

Markdown Extraを使用します。
また、ライブラリはcebe\markdownを使用します。

markdown実装

markdownの実装自体は簡単なコードで完了します。

convertMarkdown.php
 $converter = new \cebe\markdown\MarkdownExtra();
 $String = $converter->parse("# AAA"); // <h1>AAA</h1>

Laravelプロジェクトに組み込む

convertMarkdown.phpで使用したコードをLaravelプロジェクトに組み込みます。
今回はブログでの使用なのでブログの本文が表示される画面で反映させたいので、
記事一覧画面(index.blade.php)と記事詳細画面(show.blade.php)に以下のコードを組み込みます。

index.blade.php&show.blade.php
<div class="body">
   @php
     $converter = new \cebe\markdown\MarkdownExtra();
     $item->contents = $converter->parse($item->contents);
   @endphp  
   {!! $item->contents !!}
</div>

{!! !!}でHTMLの要素をそのまま表示させています。(Laravel標準のhtmlspecialcharsを解除)

動作確認

記事一覧画面

markdown反映前

スクリーンショット 2020-08-04 19.50.55.png

markdown反映後

スクリーンショット 2020-08-04 19.52.48.png

 記事詳細画面

スクリーンショット 2020-08-04 19.54.39.png

markdown反映後

スクリーンショット 2020-08-04 19.55.22.png

終わりに

今回はLaravelを使ったブログにmarkdownを反映させる処理を書きました。
view部分にmarkdownの処理を書いたり、共通関数にしなかったりですっきりしたコードではないのですが、ひとまず実現できたのでOKとしています。
この記事に関して何かあればコメントや編集リクエスト投げていただけると幸いです!

参考文献

PHPでMarkdownをいい感じにやる
Laravel 5.5 Bladeテンプレート

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

Laravelでテーブルのcreated_at, updated_atに時刻をミリ秒単位で入れる

初めに

PHP(laravel)の開発で、
データベースにinsertする際、created_at、updated_atの時刻を、ミリ秒(3桁)まで指定する要件があり、ネットで探しても良記事が見つからなかったのでメモ。

1.getDateFormat()をModelに記載

例として、productsテーブルに商品を登録するという想定。

Product.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Product extends Model 
{
    //~省略~

    //この関数をモデルに追加
    public function getDateFormat()
    {
        return 'Y-m-d H:i:s.v';
    }
}

2.現在時刻をミリ秒単位に成型

コントローラにDBの処理を書くことはバットプラクティスかもしれませんが、
今回簡単な例としてコントローラーに下記のように記述。
*Carbonを使用。
(PHP7.2以降であればdate()->format('Y-m-d H:i:s.v')でもミリ秒に変換できるみたいです)

ProductController.php
//carbonを利用
use Carbon\Carbon;

function createProduct ($product)
{
    //現在時刻をミリ秒に変更("2020-08-04 12:45:07.105"のような形式になる)
    $now = Carbon::now()->format('Y-m-d H:i:s.v');

    $products = new Product();
    //~略~
    $products->created_at = $now;
    $products->updated_at = $now;
    $products->save()
}

これでcreated_at、updated_atからむに現在時刻がミリ秒の単位で登録される。

参考

https://stackoverflow.com/questions/50208932/laravel-model-trailing-data-when-save-the-model
https://hnw.hatenablog.com/entry/20180401

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

CakePHP3.8 と Laravel7.x の「書き方」の違い ~ORM周りその2~

CakePHP3.8 と Laravel7.x の「書き方」の違い ~ORM周りその2~

今回はアクセサー周り

前: クエリの要約

そもそもクエリオブジェクトの返り値が別

1件取得

  • CakePHP

Table クラスとは別に、Entity クラスがあり、それが返ってくる

// \App\Model\Entity\Users が返ってくる(Table クラスとは別)
$veteranHyphen = $usersTable->find('hyphen')->find('veteran')->first();
  • Laravel

Model が Cake で言う Table, Entity の役割を持っている。
なので Model 自身のインスタンスが返ってくる。

// \App\Users が返ってくる
$veteranHyphen = Users::hyphen()->veteran()->first();

複数件取得

  • CakePHP

Collection インスタンスが返ってくる。
Collection の要素には Entity インスタンスが入っている。

// \Cake\Collection\Collection
$veteranHyphenUsers = $usersTable->find('hyphen')->find('veteran')->all();
foreach ($veteranHyphenUsers as $veteranHyphenUser) // 中身は \App\Model\Entity\Users
  • Laravel

Collection インスタンスが返ってくる。
Collection の要素には Model インスタンスが入っている。

// \Illuminate\Database\Eloquent\Collection
$veteranHyphenUsers = Users::hyphen()->veteran()->get();
foreach ($veteranHyphenUsers as $veteranHyphenUser) // 中身は \App\Users

アクセサー

fetch したレコードの値を、参照するときにフォーマットすることができます。
DB からとってくるとき、ちょっとした整形が面倒くさいなぁ(CASE文大量など)といったときに便利です。

個人的には表示系をここに書いても良いんじゃないかなって思います。
(郵便番号 => 住所 とか 0,1 => 男女 とか)

  • CakePHP

CakePHP では「仮想プロパティ」と呼ばれています。
Entity クラスの中で、「_get」+ {仮想プロパティ名}で定義できます。

namespace App\Model\Entity;

use Cake\ORM\Entity;

class User extends Entity
{
    protected function _getFullName()
    {
        return $this->_properties['first_name'] . '  ' .
            $this->_properties['last_name'];
    }

}

// 参照する時
echo $user->full_name; // 横丁 小町

仮想プロパティはデータを保存するときには干渉しません。

  • Laravel

Laravel では「アクセサ」と呼ばれています。
get + {プロパティ名} + Attribute で定義できます。

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * ユーザーのフルネームを取得
     *
     * @return string
     */
    public function getFullNameAttribute()
    {
        return $this->first_name . '  ' .
            $this->last_name';
    }
}

// 参照する時
echo $user->full_name; // 横丁 小町

保存時にも影響を与えたい時

入力した値を、自動的に保存時にフォーマットしてほしい時

  • CakePHP3

ややこしいですが、CakePHP ではこれを アクセサ と呼びます。
値を参照するときにはもちろん、DBにデータを保存するときにも適用されます。

値を保存する時、値を参照する時、両方向に影響があるので、冪等性が担保されていなければなりません

namespace App\Model\Entity;

use Cake\ORM\Entity;

class Article extends Entity
{
    protected function _getTitle($title)
    {
        return ucwords($title);
    }
}
  • Laravel

Laravel では、カスタムキャスト でこれを実現します。
CakePHPと違って、値を取得する時、保存する時で処理を分けられるので、冪等性をそんなに気にしなくても良いです。

キャストを定義して、

namespace App\Casts;

use Illuminate\Contracts\Database\Eloquent\CastsAttributes;

class Ucwords implements CastsAttributes
{
    /**
     * 指定された値をキャストする
     *
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @param  string  $key
     * @param  mixed  $value
     * @param  array  $attributes
     * @return array
     */
    public function set($model, $key, $value, $attributes)
    {
        return ucwords($value);
    }
}

Model で設定

namespace App;

use App\Casts\Ucwords;
use Illuminate\Database\Eloquent\Model;

class Article extends Model
{
    /**
     * キャストする属性
     *
     * @var array
     */
    protected $casts = [
        'title' => Ucwords::class,
    ];
}

 おわりに

フレームワークごとに単語を統一してほしい。

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

Visual Studio Code設定メモ

Extensions

改行コードを変更する

settings.json設定例
{
   "files.eol": "\n"
}

参考 :

タブインデント、空白を表示させる設定

settings.json設定例
{
    "editor.insertSpaces": false,
    "editor.renderWhitespace": "all"
}

参考 :

インデント幅を言語毎に指定する

settings.json設定例
{
    "[javascript]": {
      "editor.tabSize": 2
    },
    "[html]": {
        "editor.tabSize": 4
    }
}

参考 :

Smartyのデリミタを変更

やったこと
blockComment ["{", "}"], => [ "<{*", "*}>" ] へ修正
brackets ["{", "}"], => ["<{", "}>"], へ修正
autoClosingPairs , surroundingPairs["<{", "}>"], を追加

C:\Users\<USER NAME>\.vscode\extensions\imperez.smarty-0.3.0\smarty.configuration.json

smarty.configuration.json設定例
{
    "comments": {
        // symbols used for start and end a block comment. Remove this entry if your language does not support block comments
        "blockComment": [ "<{*", "*}>" ]  // [ "{*", "*}" ]から変更
    },
    // symbols used as brackets
    "brackets": [
        ["<{", "}>"],  // ["{", "}"],から変更
        ["[{", "}]"],
        ["[", "]"],
        ["(", ")"]
    ],
    "autoClosingPairs": [
+       ["<{", "}>"],
        ["{", "}"],
        ["[", "]"],
        ["(", ")"],
        ["\"", "\""],
        ["'", "'"],
        ["`", "`"]
    ],
    "surroundingPairs": [
+       ["<{", "}>"],
        ["{", "}"],
        ["[", "]"],
        ["(", ")"],
        ["\"", "\""],
        ["'", "'"],
        ["`", "`"]
    ]
}

参考 :

*.tplなどでEmmet(Html/CSSの入力補完)を効かせる

settings.json設定例
    "emmet.includeLanguages": {
        "smarty": "html"
    },

参考 :

自動アップデートを無効化する方法

C:\Users\<ユーザー名>\AppData\Roaming\Code\User\settings.json

settings.json設定例
{
    "update.channel": "none"
}

参考 :

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

PHPのSwitch文の厳密な比較について

PHPのSwitch文は厳密比較===ではなく==で比較される

$param = "2";

switch ($param) {
  case 2:
    echo "paramはInteger型の2です";
    break;
  case "2":
    echo "paramはString型の2です";
    break;
}

これの出力結果はparamはInteger型の2です
String型なのにInteger型と判断されてしまう
コレを解決するには

$param = "2";

switch (true) {
  case $param === 2:
    echo "paramはInteger型の2です";
    break;
  case $param === "2":
    echo "paramはString型の2です";
    break;
}

こうしてやる必要がある
最初は条件式にtrueを入れるなんて!!!!と思ったけど

条件式に "2" をいれるとPHPがその時点で自動的にInteger型に型変換を行ってしまい
厳密な比較ができなくなってしまうようです

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

Laravelで和暦を扱う

和暦を扱う必要があったので,その実装をまとめてみました

環境

  • Laravel 5.8

作るもの

  • 年号を管理するテーブル(era_names)
  • 和暦クラス
  • 和暦と西暦の変換処理

年号テーブルの作成

年号を管理するテーブルには

  • 年号の名前
  • 略称
  • 開始日
  • 終了日

の4つのカラムを作成します.テーブル名をera_namesとし,マイグレーションファイルは次のようになります.

public function up()
{
    Schema::create('era_names', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->string('short_name');
        $table->date('start_at');
        $table->date('end_at');
        $table->timestamps();
    });
}

作成したマイグレーションを実行しテーブルを作成したら,モデルを作成します.

app\Models\EraName.php
class EraName extends Model
{
    /** @var string */
    protected $table = 'era_names';

    /** @var array */
    protected $dates = [
        'start_at',
        'end_at',
    ];

    /** @var array */
    protected $guarded = [
        'id',
    ];
}

最後にデータを追加します.追加する方法はシーダやtinkerを用いてください.

name short_name start_at end_at
昭和 S 1926-12-25 1989-01-07
平成 H 1989-01-08 2019-04-30
令和 R 2019-05-01 2100-01-01

和暦-西暦変換処理の作成

プロジェクトの方針にしたがって,和暦-西暦の変換処理を作成します.ここでは和暦クラスを作成し,Carbon(CarbonImmutable)と相互変換する形で実装します.他の実装として変換処理をすべてServiceに書き,ファサードやヘルパを通して変換することなどが考えられます.

Carbonに和暦への変換メソッドを実装するために,次のようなサービスプロバイダを用意します.

app\Providers\DateServiceProvider
namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Date;
use App\Models\EraName;
use App\Models\Wareki;
use Carbon\CarbonImmutable;

class DateServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        Date::use(CarbonImmutable::class);  // 日付を扱うクラスをCarbonImmutableに変更

        Date::macro('toWareki', function () {  // 日付を扱うクラスにtoWarekiメソッドを追加
            return new Wareki($this);
        });
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        $this->app->instance('era_names', EraName::all());  // サービスコンテナに年号を登録
    }
}

Date::macro(...)を用いることで,日付オブジェクトにメソッドを追加することができます.ここではtoWarekiメソッドを追加しています.

$this->app->instance('era_names', EraName::all());

この部分ではサービスコンテナに年号を登録し,どこでも同じインスタンスが取得できるようにします.取得方法は

app('era_names')

で取得することができます.これを行うことで,処理の途中でera_namesテーブルの内容が変更されても,処理開始時の年号データが使われるようになります.また,年号を取得するSQLが1度しか実行されなくなるなどの利点があります.

次に和暦クラスを実装します.場所はプロジェクトの方針にしたがいましょう.ここではapp\Models下に作成します.

app\Models\Wareki.php
namespace App\Models;

use Illuminate\Support\Facades\Date;
use Carbon\CarbonImmutable;
use App\Models\EraName;


class Wareki
{
    /** @var int */
    public $year;
    public $fiscalYear;
    public $month;
    public $day;

    /** @var EraName */
    public $eraName;

    /**
     * @param Carbon|CarbonImmutable
     */
    public function __construct($ymd) {
        $this->eraName = app('era_names')->first(function ($eraName) use ($ymd) {
            return $eraName->start_at->startOfDay() <= $ymd && $ymd <= $eraName->end_at->endOfDay();
        });

        $this->year = $ymd->year - $this->eraName->start_at->year + 1;
        $this->fiscalYear = $this->year - ((1 <= $ymd->month && $ymd->month <= 3) ? 1 : 0);
        $this->month = $ymd->month;
        $this->day = $ymd->day;
    }

    /**
     * @return Carbon|CarbonImmutable
     */
    public function toYmd() {
        return Date::createMidnightDate(
            $this->eraName->start_at->year + $this->year - 1,
            $this->month ?? 1,
            $this->day ?? 1,
        );
    }

    /**
     * @param string $format
     * @return string
     */
    public function format(string $format) {
        $ret = '';
        foreach (mb_str_split($format) as $str) {
            if ($str === 'Y') $ret .= sprintf('%s%02d', $this->eraName->name, $this->year);
            else if ($str === 'S') $ret .= sprintf('%s%02d', $this->eraName->short_name, $this->year);
            else if ($str === 'y') $ret .= sprintf('%s%02d', $this->eraName->name, $this->fiscalYear);
            else if ($str === 's') $ret .= sprintf('%s%02d', $this->eraName->short_name, $this->fiscalYear);
            else if ($str === 'm') $ret .= sprintf('%02d', $this->month);
            else if ($str === 'd') $ret .= sprintf('%02d', $this->day);
            else $ret .= $str;
        }

        return $ret;
    }
}

和暦-西暦の変換処理は和暦クラスにまとめることにしてあります.コンストラクタで西暦->和暦の変換を行い,toYmdメソッドで和暦->西暦の変換を行います.formatメソッドでは和暦を文字列に変換します.例えば

$ymd = Date::parse('2019-03-01');  \\ 平成年31年3月1日

$ymd->toWareki()->format('Y年');  \\ 平成31年
$ymd->toWareki()->format('S');  \\ H31
$ymd->toWareki()->format('y年度');  \\ 平成30年度
$ymd->toWareki()->format('s');  \\ H30
$ymd->toWareki()->format('m月d日');  \\ 03月01日

このようになっています.この和暦クラスでは時分秒を扱わない形で実装しています.

まとめ

Laravelで和暦を扱ってみました.年号データをDBではなくconfigなどに設定する場合も,$this->app->instance()の部分を調整することで実装することができます.また,Data::macroを用いて年度初めを取得する処理などを追加してもいいかもしれません.

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

Laravel5.6以降のログの機能をちょっと調べた

目的

  • Laravelのログに関する情報を調べてみたので簡単にまとめる

実施環境

  • ハードウェア環境
項目 情報
OS macOS Catalina(10.15.5)
ハードウェア MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports)
プロセッサ 2 GHz クアッドコアIntel Core i5
メモリ 32 GB 3733 MHz LPDDR4
グラフィックス Intel Iris Plus Graphics 1536 MB
  • ソフトウェア環境
項目 情報 備考
PHP バージョン 7.4.3 Homwbrewを用いて導入
Laravel バージョン 7.0.8 commposerを用いてこちらの方法で導入→Mac Laravelの環境構築を行う
MySQLバージョン 8.0.19 for osx10.13 on x86_64 Homwbrewを用いてこちらの方法で導入→Mac HomebrewでMySQLをインストールする

前提情報

  • Laravelのログ出力方法はMonologと言う名前のライブラリを使用している。
  • 本記事より公式ドキュメントの方がわかりやすいかもしれない。ログについて詳しく書いてあるLaravel5.6のドキュメントのリンクを下記に記載する。

ログチャンネル

  • ログの出力にはチャンネルと言う機能を使用する。
  • チャンネルは複数存在する。
  • チャンネル = ログ出力の方法と考えていただいても差し支えないと思う。
  • 下記にログチャンネルの種類を記載する。

    チャンネル 説明
    stack チャンネルをまとめるためのチャンネル
    single シングルチャンネル、一つのファイルにずっとログを書き込む。デフォルトの設定はこれ
    daily デイリーチャンネル一日毎にファイルを分けてログを出力してくれる。デフォルトだと14日間ログファイルを保持する。
    slack slackチャンネル、社内のコミュニケーションツールであるslackにログを送信するためのチャンネル
    syslog システムログチャンネル、アプリのシステムログを出力するためのチャンネル
    errorlog エラーログチャンネル、エラーメッセージを出力するためのチャンネル
    monolog そのほかのライブラリで定義されているログを出力するためのチャンネル
    custom カスタムチャンネル、開発者が任意のチャンネルを作成するためのチャンネル
  • 公式ドキュメントのログチャンネルの表を下記に記載する。

    ログ_5_6_Laravel.png

ログレベル

  • laravelのログにはレベルが存在する。
  • 出力の優先度によってレベル分けされている。
  • 8個のレベルが存在し、最も重要性の高いログのレベル名はemergencyで開発段階の情報など重要度の低いログを出力するレベルはdebugとなる
  • ログのレベルはチャンネル毎に設定可能である。ログ出力の指令を行うコードでも、出力したいログのレベルを指定することができる。
  • ログレベルの種類を下記に記載する。上位に行けば行くほど危険度が高いログレベルとして設計することが一般的である。

    ログレベル
    emergency
    alert
    critical
    error
    warning
    notice
    info
    debug
  • ログレベルは下記の規約で決められたものを使用している。

  • ログレベルはアプリ開発段階でのログに出力したい情報とデプロイしてユーザが使用している段階でのログに出力したい情報を分けるために存在する。

  • 後述するログの設定ファイルでdebugを選択していれば全てのログレベルのログがログファイルに記載される。

  • 後述するログの設定ファイルでを選択していれば全てのログレベルのログがログファイルに記載される。

ログの設定ファイル

  • laravel5.6からログの設定ファイルの場所が変更になった。
  • アプリ名ディレクトリ/config/直下のlogging.phpファイルがログの設定ファイルである。
  • 下記にloggingファイルの内容を記載する。

    アプリ名ディレクトリ/config/loggign.php
    <?php
    
    use Monolog\Handler\NullHandler;
    use Monolog\Handler\StreamHandler;
    use Monolog\Handler\SyslogUdpHandler;
    
    return [
    
        /*
        |--------------------------------------------------------------------------
        | Default Log Channel
        |--------------------------------------------------------------------------
        |
        | This option defines the default log channel that gets used when writing
        | messages to the logs. The name specified in this option should match
        | one of the channels defined in the "channels" configuration array.
        |
        */
    
        'default' => env('LOG_CHANNEL', 'stack'),
    
        /*
        |--------------------------------------------------------------------------
        | Log Channels
        |--------------------------------------------------------------------------
        |
        | Here you may configure the log channels for your application. Out of
        | the box, Laravel uses the Monolog PHP logging library. This gives
        | you a variety of powerful log handlers / formatters to utilize.
        |
        | Available Drivers: "single", "daily", "slack", "syslog",
        |                    "errorlog", "monolog",
        |                    "custom", "stack"
        |
        */
    
        'channels' => [
            'stack' => [
                'driver' => 'stack',
                'channels' => ['single'],
                'ignore_exceptions' => false,
            ],
    
            'single' => [
                'driver' => 'single',
                'path' => storage_path('logs/laravel.log'),
                'level' => 'debug',
            ],
    
            'daily' => [
                'driver' => 'daily',
                'path' => storage_path('logs/laravel.log'),
                'level' => 'debug',
                'days' => 14,
            ],
    
            'slack' => [
                'driver' => 'slack',
                'url' => env('LOG_SLACK_WEBHOOK_URL'),
                'username' => 'Laravel Log',
                'emoji' => ':boom:',
                'level' => 'critical',
            ],
    
            'papertrail' => [
                'driver' => 'monolog',
                'level' => 'debug',
                'handler' => SyslogUdpHandler::class,
                'handler_with' => [
                    'host' => env('PAPERTRAIL_URL'),
                    'port' => env('PAPERTRAIL_PORT'),
                ],
            ],
    
            'stderr' => [
                'driver' => 'monolog',
                'handler' => StreamHandler::class,
                'formatter' => env('LOG_STDERR_FORMATTER'),
                'with' => [
                    'stream' => 'php://stderr',
                ],
            ],
    
            'syslog' => [
                'driver' => 'syslog',
                'level' => 'debug',
            ],
    
            'errorlog' => [
                'driver' => 'errorlog',
                'level' => 'debug',
            ],
    
            'null' => [
                'driver' => 'monolog',
                'handler' => NullHandler::class,
            ],
    
            'emergency' => [
                'path' => storage_path('logs/laravel.log'),
            ],
        ],
    
    ];
    

ログチャンネルの指定

  • どのログチャンネルを指定してログを出力するのかの設定はアプリ名ディレクトリ/直下にある.envファイルに記載する。
  • .envの下記の部分でログチャンネルの設定を行っている。

    アプリ名ディレクトリ/.env
    LOG_CHANNEL=stack
    
  • 上記の様に記載されていると、stackチャンネル(チャンネルをまとめるためのチャンネル)が選択されていることになる。

  • dailyチャンネルでログを出力したい場合は下記の様に.envファイルに記載する。

    アプリ名ディレクトリ/.env
    LOG_CHANNEL=daily
    
  • 複数のログを出力するための方法は下記の記事にまとめてみた。(stackチャンネルに出力したいログチャンネルを配列状に追加することがセオリーの様である。)

ログの初期設定の状態

  • $ laravel new アプリ名を実行した直後の何もいじっていない状態のログの設定がどうなっているのか確認してみる。
  1. アプリの設定ファイルである.envファイルのログチャンネルの設定の確認

    • 下記に.envファイルのログチャンネルの記載部分のみ抜粋して記載する。

      アプリ名ディレクトリ/.env
      LOG_CHANNEL=stack
      
    • ログチャンネルはstackが選択されている。

  2. ログの設定ファイルlogging.phpの記載の確認

    • 下記にlogging.phpファイルの内容を記載する。

      アプリ名ディレクトリ/config/loggign.php
      <?php
      
      use Monolog\Handler\NullHandler;
      use Monolog\Handler\StreamHandler;
      use Monolog\Handler\SyslogUdpHandler;
      
      return [
      
          /*
          |--------------------------------------------------------------------------
          | Default Log Channel
          |--------------------------------------------------------------------------
          |
          | This option defines the default log channel that gets used when writing
          | messages to the logs. The name specified in this option should match
          | one of the channels defined in the "channels" configuration array.
          |
          */
      
          'default' => env('LOG_CHANNEL', 'stack'),
      
          /*
          |--------------------------------------------------------------------------
          | Log Channels
          |--------------------------------------------------------------------------
          |
          | Here you may configure the log channels for your application. Out of
          | the box, Laravel uses the Monolog PHP logging library. This gives
          | you a variety of powerful log handlers / formatters to utilize.
          |
          | Available Drivers: "single", "daily", "slack", "syslog",
          |                    "errorlog", "monolog",
          |                    "custom", "stack"
          |
          */
      
          'channels' => [
              'stack' => [
                  'driver' => 'stack',
                  'channels' => ['single'],
                  'ignore_exceptions' => false,
              ],
      
              'single' => [
                  'driver' => 'single',
                  'path' => storage_path('logs/laravel.log'),
                  'level' => 'debug',
              ],
      
              'daily' => [
                  'driver' => 'daily',
                  'path' => storage_path('logs/laravel.log'),
                  'level' => 'debug',
                  'days' => 14,
              ],
      
              'slack' => [
                  'driver' => 'slack',
                  'url' => env('LOG_SLACK_WEBHOOK_URL'),
                  'username' => 'Laravel Log',
                  'emoji' => ':boom:',
                  'level' => 'critical',
              ],
      
              'papertrail' => [
                  'driver' => 'monolog',
                  'level' => 'debug',
                  'handler' => SyslogUdpHandler::class,
                  'handler_with' => [
                      'host' => env('PAPERTRAIL_URL'),
                      'port' => env('PAPERTRAIL_PORT'),
                  ],
              ],
      
              'stderr' => [
                  'driver' => 'monolog',
                  'handler' => StreamHandler::class,
                  'formatter' => env('LOG_STDERR_FORMATTER'),
                  'with' => [
                      'stream' => 'php://stderr',
                  ],
              ],
      
              'syslog' => [
                  'driver' => 'syslog',
                  'level' => 'debug',
              ],
      
              'errorlog' => [
                  'driver' => 'errorlog',
                  'level' => 'debug',
              ],
      
              'null' => [
                  'driver' => 'monolog',
                  'handler' => NullHandler::class,
              ],
      
              'emergency' => [
                  'path' => storage_path('logs/laravel.log'),
              ],
          ],
      
      ];
      
    • コード'default' => env('LOG_CHANNEL', 'stack'),では.envファイルにてログチャンネルの設定が行われなかった場合に指定されるデフォルトのログチャンネルが記載されている。デフォルトではログチャンネルの設定が.envファイルにて行われなかった場合、stackチャンネルを指定する様に記載されている。本記載は基本的に変更しない。

    • 配列状に格納されているログチャンネルの情報について説明する。下記に.envファイルで指定されているstackチャンネルの記載部分のみ抜粋したコードを記載する。

      アプリ名ディレクトリ/config/loggign.php
      'stack' => [
          'driver' => 'stack',  //ライブラリの実行ドライバを指定している(チャンネル名を指定していると考えていただきたい)
          'channels' => ['single'],  //まとめて実行するログチャンネルを配列状に指定している デフォルトだとsingleチャンネルのみが指定されている。
          'ignore_exceptions' => false,  //本記載の意味を現在調査中です。
      ],
      

ログチャンネルを変更するには?

  • デフォルトのログチャンネルから変更する方法は主に二通りあると考える。下記に二通りの方法を記載する。
    • .envファイルにてLOG_CHANNEL=の記載を設定したいログチャンネルに変更する。
    • .envファイルのLOG_CHANNEL=の記載は弄らずに「stack」チャンネルを選択し、アプリ名ディレクトリ/config/loggign.phpの「stack」チャンネルの設定部分'channels' =>にて出力チャンネルを変更する。
  • 単一のログのみを出力するなら.envにてログチャンネルを設定するだけで良いが、「single」チャンネルと「daily」チャンネル両方のログが欲しい時はアプリ名ディレクトリ/config/loggign.phpの「stack」チャンネルの設定部分で指定する必要がある。下記に筆者が以前まとめた二種類のログを出力する方法の記事のリンクを記載する。

参考文献

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

Laravel Socialiteを使用してソーシャルログイン を実装する

Laravel Socialiteを使用してソーシャルログインでの登録・ログイン機能を実装していきます。

Googleの設定

GoogleAPIs
上記にアクセスして、『プロジェクトを作成』を選択する

新しいプロジェクト

プロジェクト名: 適宜
場所: 組織なし
を入力して『作成』を押下

Google Cloud Platform

利用規約をチェックし『同意して続行』を押下

左上ハンバーガーメニュー/『APIとサービス』/『OAUTH同意画面』を選択する

OAuth同意画面

UserType: 外部を(適宜)選択し『作成』を押下

アプリケーション名: 適宜
『保存』を押下

サイドメニュー/『認証情報認証情報を作成』/『OAuthクライアントID』を選択する

OAuthクライアントIDの作成

アプリケーションの種類: 『ウェブアプリケーション』をチェック
名前:適宜
承認済みのリダイレクトURI: http://localhost/login/google/callback
『作成』を押下

OAuthクライアントを作成しましたと表示されるので下記のファイルへ追記する

laravel/.env
GOOGLE_CLIENT_ID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=xxxxxxxxxxxxxxxxxxxxxxxx

うまく動作しない場合
APP_URL=http://localhost:10080などAPP_URLを細かく指定すると動作する可能性があります。

Laravel Socialiteをインストール

$ docker-compose exec workspace composer require laravel/socialite

configファイルを編集

laravel/config/services.php
 'google' => [
        'client_id' => env('GOOGLE_CLIENT_ID'),
        'client_secret' => env('GOOGLE_CLIENT_SECRET'),
        'redirect' => env('APP_URL') . '/login/google/callback',
    ],

returnの中に上記を追記する

Googleへのリダイレクト処理

laravel/routes/web.php
Route::prefix('login')->name('login.')->group(function () {
    Route::get('/{provider}', 'Auth\LoginController@redirectToProvider')->name('{provider}');
    Route::get('/{provider}/callback', 'Auth\LoginController@handleProviderCallback')->name('{provider}.callback');
});
Route::prefix('register')->name('register.')->group(function () {
    Route::get('/{provider}', 'Auth\RegisterController@showProviderUserRegistrationForm')->name('{provider}');
    Route::post('/{provider}', 'Auth\RegisterController@registerProviderUser')->name('{provider}');
});

ログインコントローラーにアクションメソッドを追加

下記をコントローラー内に追記する

laravel/app/Http/Controllers/Auth/LoginController.php
use App\User;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Laravel\Socialite\Facades\Socialite;
// 省略 
public function redirectToProvider(string $provider)
    {
        return Socialite::driver($provider)->redirect();
    }
public function handleProviderCallback(Request $request, string $provider)
    {
        $providerUser = Socialite::driver($provider)->stateless()->user();

        $user = User::where('email', $providerUser->getEmail())->first();

        if ($user) {
            $this->guard()->login($user, true);
            return $this->sendLoginResponse($request);
        }
        return redirect()->route('register.{provider}', [
            'provider' => $provider,
            'email' => $providerUser->getEmail(),
            'token' => $providerUser->token,
        ]); 
    }

ログイン画面のBladeを編集

laravel/resources/views/auth/login.blade.php
<a href="{{ route('login.{provider}', ['provider' => 'google']) }}" class="btn btn-block btn-danger">
  <i class="fab fa-google mr-1"></i>Googleでログイン
</a>

ユーザー登録コントローラーにアクションメソッドを追加

下記をコントローラー内に追記する

laravel/app/Http/Controllers/Auth/RegisterController.php
use Illuminate\Http\Request;
use Laravel\Socialite\Facades\Socialite;
// 省略
 public function showProviderUserRegistrationForm(Request $request, string $provider)
    {
        $token = $request->token;

        $providerUser = Socialite::driver($provider)->userFromToken($token);

        return view('auth.social_register', [
            'provider' => $provider,
            'email' => $providerUser->getEmail(),
            'token' => $token,
        ]);
    }

public function registerProviderUser(Request $request, string $provider)
    {
        $request->validate([
            'name' => ['required', 'string', 'alpha_num', 'min:3', 'max:16', 'unique:users'],
            'token' => ['required', 'string'],
        ]);

        $token = $request->token;

        $providerUser = Socialite::driver($provider)->userFromToken($token);
        $user = User::create([
            'name' => $request->name,
            'email' => $providerUser->getEmail(),
            'password' => null,
        ]);

        $this->guard()->login($user, true);

        return $this->registered($request, $user)
            ?: redirect($this->redirectPath());
    }
laravel/views/auth/register.blade.php
<a href="{{ route('login.{provider}', ['provider' => 'google']) }}" class="btn btn-block btn-danger">
  <i class="fab fa-google mr-1"></i>Googleで登録
</a>

以上でGoogleアカウントで登録・ログインができるようになりました。

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

Laravel + Vue.jsの導入方法

LaravelのBladeにVueコンポーネントを組み込む方法をまとめます。

環境

  • laradock
  • php: 7.3
  • Laravel: 7.2

Vue.jsをインストールする

laravel/package.json
"vue": "^2.6.11", 
"vue-template-compiler": "^2.6.11"
$ docker-compose exec workspace npm install

Vueコンポーネントを作成する

試しにハートボタンを作成します。

laravel/resources/js/components/SampleLike.vue
<template>
  <div>
    <button
      type="button"
      class="btn m-0 p-1 shadow-none"
    >
      <i class="fas fa-heart mr-1"
      />
    </button>
    10
  </div>
</template>

<script>
</script>

app.jsを編集

laravel/resources/js/app.js
import Vue from 'vue'
import Samplelike from './components/SampleLike'

const app = new Vue({
  el: '#app',
  components: {
    SampleLike,
  }
})

laravelの全画面で使用できるようにここで読み込みます。

Laravel Mixを編集

laravel/webpack.mix.js
mix.js('resources/js/app.js', 'public/js')
    .sass('resources/sass/app.scss', 'public/css')
    .version();

上記はresources/js/app.jsをトランスパイルしてpublic/jsのapp.jsというファイルで保存されるよというソースです。
.version()はトランスパイルされる時に毎回idを採番する役割ですが、これは同じidの古いjavascriptをブラウザキャッシュに残さないためです。

.gitignoreを編集

下記はjavascriptが編集される都度トランスパイルされてファイルが作成・更新されていくため、
管理対象から外しておきます。

laravel/.gitignore
/node_modules
/public/css # 追加
/public/hot
/public/js  # 追加
/public/mix-manifest.json # 追加

トランスパイルの実行

$ docker-compose exec workspace npm run watch-poll

DONE Compiled successfullyと表示されればトランスパイル成功です。
上記のコマンドはjavascriptが編集されたら自動でトランスパイルしてくれます。

app.blade.phpを編集

laravel/resources/views/app.blade.php
{{--省略--}}
<body>
  <div id="app"> {{--追加--}}
    @yield('content')
  </div> {{--追加--}}

  <script src="{{ mix('js/app.js') }}"></script> {{--追加--}}
{{--省略--}}
</body>

BladeにVueコンポーネントを組み込む

laravel/resources/views/posts/index.blade.php
<div class="card-body pt-0 pb-2 pl-3">
    <div class="card-text">
      <sample-like>
      </sample-like>
    </div>
  </div>

組み込むときはケバブケースで記述する。

これでハートボタンとダミーの10が表示でき、Vueコンポーネントを組み込めたかと思います。

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

Dockerコンテナを止めずにapache2を再起動する方法【php7-apache】

結論

下記コマンドでreloadさせれば、変更を有効化できます。

$ /etc/init.d/Apache2 reload

環境

Docker for Windows 19.03.8
DockerImage php:7.4-apache

背景

Dockerでローカル環境構築中に困りました。
普段CentOSで開発していると、設定ファイル変更後に有効化させる際、下記のコマンドをたたきたくなるところですが、
この場合コンテナごと停止してしまいます。

systemctl apache2[httpd] restart

コンテナを止めずに設定変更の有効化をするには下記のコマンドをたたきましょう。

$ /etc/init.d/Apache2 reload
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む