20200219のlaravelに関する記事は5件です。

laravelで別々のDBから取得したデータをマージ、created_atでソートして最初の3件だけ取得する

やったこと

取得してきたデータをconcatメソッドでマージしてソート、切り分けの処理をした。

concatメソッドは、指定した「配列」やコレクションの値を元のコレクションの最後に追加します。(Laravel公式ドキュメントから引用)

なぜやったか

concat()を使うことでコレクションのままマージできるのでその後の処理もしやすいから。

コード

$formatData = $collection1->concat($collection2)->sortBy(‘created_at')->slice(0, 3);

ほかに試したこと

  • SQLを直接書いてUNIONでマージ→DBが違うため不可
  • toArray()で配列型してarray_mergeでマージ→日付の処理でformatが使いたかったので回避
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】日付処理ならCarbonにお任せ!!

PHPでは現在時刻を取得したり、一年後の日付を取得したりすることができる
「DateTimeクラス」がありますが、これがまた少し使いにくい、、、
そんな時に出てくるのがCarbonです!!
CarbonはDateTimeクラスを継承しており、言うなればDateTimeをもっと使いやすくしたクラスです。
しかも、PHPで人気なフレームワークLaravelには標準でインストールされています
Laravel内でupdated_atやcreated_atはCarbonインスタンスでできているらしい!!
というわけで、Laravelを使っているのであれば、使うしかないという状況です。

使用可能なクラスはCarbon、CarbonImmutableの2つ

こちらの章は細かいことについて書いているので読み飛ばしてもらっても大丈夫です

使用可能なクラスはCarbonとCarbonImmutableです
どちらのクラスとも同じメソッドを使えます
しかし、インスタンスからメソッドを呼び出した時の挙動が少し違います
下記の例で確認しましょう

//インスタンス作成
$mutable = Carbon::now();
$immutable = CarbonImmutable::now();
//1日後の日付を取得する
$modifiedMutable = $mutable->add(1, 'day');
$modifiedImmutable = $immutable->add(1, 'day');

//Carbonクラスの場合、返り値と元のインスタンスの値が同じになる
var_dump($modifiedMutable === $mutable);             // bool(true)
var_dump($mutable->isoFormat('dddd D'));             // string(11) "Saturday 15"
var_dump($modifiedMutable->isoFormat('dddd D'));     // string(11) "Saturday 15"

//CarbonImmutableクラスの場合、返り値と元のインスタンスの値は異なる
var_dump($modifiedImmutable === $immutable);         // bool(false)
var_dump($immutable->isoFormat('dddd D'));           // string(9) "Friday 14"
var_dump($modifiedImmutable->isoFormat('dddd D'));   // string(11) "Saturday 15"

Carbonクラスはメソッドを呼び出したインスタンスが書き換えられる
CarbonImmutableクラスはメソッドを呼び出したインスタンスはそのままになる

Carbon、CarbonImmutableは相互変換可能

Carbon、CarbonImmutableは相互に変換可能です
下記のようにtoMutable()toImmutable()メソッドを使用することで相互変換できます

toMutable()メソッドはCarbonImmutableクラスをCarbonクラスに変換します
toImmutable()メソッドはCarbonクラスをCarbonImmutableクラスに変換します

ちなみに
isMutable()メソッドはCarbonかどうかを判定します
isImmutable()メソッドはCarbonImmutableかどうかを判定します

<?php
use Carbon\Carbon;

$mutable = CarbonImmutable::now()->toMutable();
var_dump($mutable->isMutable());                     // bool(true)
var_dump($mutable->isImmutable());                   // bool(false)

$immutable = Carbon::now()->toImmutable();
var_dump($immutable->isMutable());                   // bool(false)
var_dump($immutable->isImmutable());                 // bool(true)

CarbonクラスとCarbonImmutableクラスは同じメソッドが使えるようなので、
CarbonImmutableクラスでも同じ方法で使えるはずです

以下に使い方の例を記載するので、活用してください

インスタンス作成方法

<?php
use Carbon\Carbon;

$carbon = new Carbon();
$now = Carbon::now();
$nowInLondonTz = Carbon::now('Europe/London');
$date = Carbon::now('+13:30');
$today = Carbon::today();
$tomorrow = Carbon::tomorrow();
$yesterday = Carbon::yesterday();

$tomorrow = Carbon::tomorrow('Europe/London');

// オリンピックの開会式の時間を変数に設定
$year = 2020; $month = 7; $day = 24;
$hour = 20; $minute = 00; $second = 00; $tz = 'Asia/Tokyo';

Carbon::createFromDate($year, $month, $day, $tz);
Carbon::createMidnightDate($year, $month, $day, $tz);
Carbon::createFromTime($hour, $minute, $second, $tz);
Carbon::create($year, $month, $day, $hour, $minute, $second, $tz);

$dt = new Carbon('2020-02-15');
echo $dt->copy()->subDay(); // 2020-02-15 00:00:00
echo $dt->subDay(); // 2020-02-15 00:00:00

ゲッター

<?php
use Carbon\Carbon;

$dt = Carbon::parse('2012-10-5 23:26:11.123789');

$dt->year;
    // int(2012)
$dt->month;
    // int(10)
$dt->day;
    // int(5)
$dt->hour;
    // int(23)
$dt->minute;
    // int(26)
$dt->second;
    // int(11)
$dt->micro;
    // int(123789)
$dt->dayOfWeek;
    // int(5)
$dt->dayOfWeekIso;
    // int(5)
$dt->englishDayOfWeek;
    // string(6) "Friday"
$dt->shortEnglishDayOfWeek;
    // string(3) "Fri"
$dt->locale('de')->dayName;
    // string(7) "Freitag"
$dt->locale('de')->shortDayName;
    // string(3) "Fr."
$dt->locale('de')->minDayName;
    // string(2) "Fr"
$dt->englishMonth;
    // string(7) "October"
$dt->shortEnglishMonth;
    // string(3) "Oct"
$dt->locale('de')->monthName;
    // string(7) "Oktober"
$dt->locale('de')->shortMonthName;
    // string(3) "Okt"
$dt->localeDayOfWeek;
    // string(7) "Freitag"
$dt->shortLocaleDayOfWeek;
    // string(2) "Fr"
$dt->localeMonth;
    // string(7) "Oktober"
$dt->shortLocaleMonth;
    // string(3) "Okt"
$dt->dayOfYear;
    // int(279)
$dt->weekNumberInMonth;
    // int(1)
$dt->weekOfMonth;
    // int(1)
$dt->weekOfYear;
    // int(40)
$dt->daysInMonth;
    // int(31)
$dt->timestamp;
    // int(1349479571)
Carbon::now()->timezoneName;
    // UTC
Carbon::now()->tzName;
    // UTC

比較

$first->equalTo($second);
$first->notEqualTo($second);
$first->greaterThan($second);
$first->greaterThanOrEqualTo($second);
$first->lessThan($second);
$first->lessThanOrEqualTo($second);

Carbon::create(2012, 9, 5, 5)->between($first, $second, false);

$dt = Carbon::now();
$dt2 = Carbon::createFromDate(1987, 4, 23);

$dt->isSameAs('w', $dt2);
$dt->isFuture();
$dt->isPast();

$dt->isSameYear($dt2);
$dt->isCurrentYear();
$dt->isNextYear();
$dt->isLastYear();
$dt->isLeapYear();
$dt->isCurrentMonth();
$dt->isNextMonth();
$dt->isLastMonth();
$dt->isWeekday();
$dt->isWeekend();
$dt->isMonday();
$dt->isTuesday();
$dt->isWednesday();
$dt->isThursday();
$dt->isFriday();
$dt->isSaturday();
$dt->isSunday();
$dt->isLastOfMonth();

$dt->is('Sunday');
$dt->is('June');
$dt->is('2019');
$dt->is('12:23');
$dt->is('2 June 2019');
$dt->isSameDay($dt2);
$dt->isCurrentDay();
$dt->isYesterday();
$dt->isToday();
$dt->isTomorrow();
$dt->isNextWeek();
$dt->isLastWeek();

$dt->isSameHour($dt2);
$dt->isCurrentHour();
$dt->isSameMinute($dt2);
$dt->isCurrentMinute();
$dt->isSameSecond($dt2);
$dt->isCurrentSecond();
$born->isBirthday($noCake);
$born->isBirthday($yesCake);
$overTheHill->isBirthday();

足し算、引き算

<?php
use Carbon\Carbon;

$dt = Carbon::create(2012, 1, 31, 0);

echo $dt->toDateTimeString();            // 2012-01-31 00:00:00

echo $dt->addCenturies(5);               // 2512-01-31 00:00:00
echo $dt->addCentury();                  // 2612-01-31 00:00:00
echo $dt->subCentury();                  // 2512-01-31 00:00:00
echo $dt->subCenturies(5);               // 2012-01-31 00:00:00

echo $dt->addYears(5);                   // 2017-01-31 00:00:00
echo $dt->addYear();                     // 2018-01-31 00:00:00
echo $dt->subYear();                     // 2017-01-31 00:00:00
echo $dt->subYears(5);                   // 2012-01-31 00:00:00

echo $dt->addQuarters(2);                // 2012-07-31 00:00:00
echo $dt->addQuarter();                  // 2012-10-31 00:00:00
echo $dt->subQuarter();                  // 2012-07-31 00:00:00
echo $dt->subQuarters(2);                // 2012-01-31 00:00:00

echo $dt->addMonths(60);                 // 2017-01-31 00:00:00
echo $dt->addMonth();                    // 2017-03-03 00:00:00
echo $dt->subMonth();                    // 2017-02-03 00:00:00
echo $dt->subMonths(60);                 // 2012-02-03 00:00:00

echo $dt->addDays(29);                   // 2012-03-03 00:00:00
echo $dt->addDay();                      // 2012-03-04 00:00:00
echo $dt->subDay();                      // 2012-03-03 00:00:00
echo $dt->subDays(29);                   // 2012-02-03 00:00:00

echo $dt->addWeekdays(4);                // 2012-02-09 00:00:00
echo $dt->addWeekday();                  // 2012-02-10 00:00:00
echo $dt->subWeekday();                  // 2012-02-09 00:00:00
echo $dt->subWeekdays(4);                // 2012-02-03 00:00:00

echo $dt->addWeeks(3);                   // 2012-02-24 00:00:00
echo $dt->addWeek();                     // 2012-03-02 00:00:00
echo $dt->subWeek();                     // 2012-02-24 00:00:00
echo $dt->subWeeks(3);                   // 2012-02-03 00:00:00

echo $dt->addHours(24);                  // 2012-02-04 00:00:00
echo $dt->addHour();                     // 2012-02-04 01:00:00
echo $dt->subHour();                     // 2012-02-04 00:00:00
echo $dt->subHours(24);                  // 2012-02-03 00:00:00

echo $dt->addMinutes(61);                // 2012-02-03 01:01:00
echo $dt->addMinute();                   // 2012-02-03 01:02:00
echo $dt->subMinute();                   // 2012-02-03 01:01:00
echo $dt->subMinutes(61);                // 2012-02-03 00:00:00

echo $dt->addSeconds(61);                // 2012-02-03 00:01:01
echo $dt->addSecond();                   // 2012-02-03 00:01:02
echo $dt->subSecond();                   // 2012-02-03 00:01:01
echo $dt->subSeconds(61);                // 2012-02-03 00:00:00

echo $dt->addMilliseconds(61);           // 2012-02-03 00:00:00
echo $dt->addMillisecond();              // 2012-02-03 00:00:00
echo $dt->subMillisecond();              // 2012-02-03 00:00:00
echo $dt->subMillisecond(61);            // 2012-02-03 00:00:00

echo $dt->addMicroseconds(61);           // 2012-02-03 00:00:00
echo $dt->addMicrosecond();              // 2012-02-03 00:00:00
echo $dt->subMicrosecond();              // 2012-02-03 00:00:00
echo $dt->subMicroseconds(61);           // 2012-02-03 00:00:00

echo $dt->add(61, 'seconds');                      // 2012-02-03 00:01:01
echo $dt->sub('1 day');                            // 2012-02-02 00:01:01
echo $dt->add(CarbonInterval::months(2));          // 2012-04-02 00:01:01
echo $dt->subtract(new DateInterval('PT1H'));      // 2012-04-01 23:01:01

<?php
use Carbon\Carbon;

echo Carbon::now('America/Vancouver')->diffInSeconds(Carbon::now('Europe/London')); // 0

$dtOttawa = Carbon::createMidnightDate(2000, 1, 1, 'America/Toronto');
$dtVancouver = Carbon::createMidnightDate(2000, 1, 1, 'America/Vancouver');
echo $dtOttawa->diffInHours($dtVancouver);                             // 3
echo $dtVancouver->diffInHours($dtOttawa);                             // 3

echo $dtOttawa->diffInHours($dtVancouver, false);                      // 3
echo $dtVancouver->diffInHours($dtOttawa, false);                      // -3

$dt = Carbon::createMidnightDate(2012, 1, 31);
echo $dt->diffInDays($dt->copy()->addMonth());                         // 31
echo $dt->diffInDays($dt->copy()->subMonth(), false);                  // -31

$dt = Carbon::createMidnightDate(2012, 4, 30);
echo $dt->diffInDays($dt->copy()->addMonth());                         // 30
echo $dt->diffInDays($dt->copy()->addWeek());                          // 7

$dt = Carbon::createMidnightDate(2012, 1, 1);
echo $dt->diffInMinutes($dt->copy()->addSeconds(59));                  // 0
echo $dt->diffInMinutes($dt->copy()->addSeconds(60));                  // 1
echo $dt->diffInMinutes($dt->copy()->addSeconds(119));                 // 1
echo $dt->diffInMinutes($dt->copy()->addSeconds(120));                 // 2

echo $dt->addSeconds(120)->secondsSinceMidnight();                     // 120

人との違い

<?php
use Carbon\Carbon;

$dt = CarbonImmutable::create(2017, 1, 31, 0);

echo $dt->addMonth();                    // 2017-03-03 00:00:00
echo $dt->subMonths(2);                  // 2016-12-01 00:00:00

定数

<?php
use Carbon\Carbon;

var_dump(Carbon::SUNDAY);                          // int(0)
var_dump(Carbon::MONDAY);                          // int(1)
var_dump(Carbon::TUESDAY);                         // int(2)
var_dump(Carbon::WEDNESDAY);                       // int(3)
var_dump(Carbon::THURSDAY);                        // int(4)
var_dump(Carbon::FRIDAY);                          // int(5)
var_dump(Carbon::SATURDAY);                        // int(6)

var_dump(Carbon::YEARS_PER_CENTURY);               // int(100)
var_dump(Carbon::YEARS_PER_DECADE);                // int(10)
var_dump(Carbon::MONTHS_PER_YEAR);                 // int(12)
var_dump(Carbon::WEEKS_PER_YEAR);                  // int(52)
var_dump(Carbon::DAYS_PER_WEEK);                   // int(7)
var_dump(Carbon::HOURS_PER_DAY);                   // int(24)
var_dump(Carbon::MINUTES_PER_HOUR);                // int(60)
var_dump(Carbon::SECONDS_PER_MINUTE);              // int(60)

以上です!!!
ここまで読んでいただきありがとうございました!!
疑問、気になるところがございましたら、質問、コメントよろしくお願いします!!!

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

【Laravel】循環的複雑度を可視化するためにphpmdを入れた話

Qiitaでトレンド入りしていた下記の記事を読んで
循環的複雑度を可視化し、強制的に改善させるにLaravelにphpmdを導入しました

プログラムの可読性を上げるための条件分岐を減らす方法7個
循環的複雑度について

phpmdのinstall

composer.jsonにphpmd/phpmdを追加する

composer.json
    "require-dev": {
        "phpmd/phpmd": "*"
    },

$ composer update

インストールが完了しました。

次にphpmdのルールファイル作成します

phpmd.xml
<?xml version="1.0"?>
<ruleset name="Custom_PHPMD">
    <description>Custom ruleset PHPMD</description>
    <rule ref="rulesets/codesize.xml" />
    <rule ref="rulesets/controversial.xml">
        <!-- 判定から除外: 変数名がキャメルケースかどうか -->
        <exclude name="CamelCasePropertyName" />
        <exclude name="CamelCaseParameterName" />
        <exclude name="CamelCaseVariableName" />
    </rule>
    <rule ref="rulesets/design.xml" />
    <rule ref="rulesets/unusedcode.xml" />
    <rule ref="rulesets/naming.xml">
        <!-- 判定から除外: 変数名の長さ -->
        <exclude name="LongVariable" />
    </rule>
</ruleset>
$ php vendor/phpmd/phpmd/src/bin/phpmd ファイル名 text phpmd.xml

とやれば実行できます

毎回このコマンドを書くのは面倒なので
まとめてartisanコマンドに追加しました。

artisanコマンド作成

$ php artisan make:command PhpmdCommand

app/Console/Commands/PhpmdCommand.php
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class PhpmdCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'phpmd {file_path}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'phpmd';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $phpmd = base_path('vendor/phpmd/phpmd/src/bin/phpmd');
        echo shell_exec('php '.$phpmd.' '.$this->argument('file_path').' text 
 phpmd.xml');
    }
}

$ php artisan phpmd ファイル名
で毎回チェックできるようになりました。

でも修正ファイルを毎回手動で確認するのも面倒なので、
commitする際にチェックさせて、エラーがあったらcommitさせないようにしようと思います。
けっこうチェック厳しいですが、これなら絶対複雑度は下がりますよね。

git hookの設定

.git/hooks/pre-commit

.git/hooks/pre-commit
IS_ERROR=0
for file in `git diff --cached --name-only && git diff --name-only`
do
    echo $file
    ERROR_MSG=`php artisan phpmd $file`
    if  [ "$ERROR_MSG" != "" ]; then
        echo $ERROR_MSG
        IS_ERROR=1
    fi
done

if [ $IS_ERROR -eq 1 ]; then
    echo ""
    echo "Please resolve the error"
fi
exit $IS_ERROR

git commit するたびにエラーを指摘されて大変ですが、
命名規則の徹底や複雑度改善がされていい感じですね。
今後ほかのサイトにも導入してみようと思います

以下を参照して修正予定
phpmdのルール一覧
githooksのpre-pushを共有してレポジトリを健全に保つ

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

Laravelのリソースコントローラ

laravelのリソースコントローラについてのメモです。

公式リファレンス
https://readouble.com/laravel/5.8/ja/controllers.html?header=%25E3%2583%25AA%25E3%2582%25BD%25E3%2583%25BC%25E3%2582%25B9%25E3%2582%25B3%25E3%2583%25B3%25E3%2583%2588%25E3%2583%25AD%25E3%2583%25BC%25E3%2583%25A9

リソースコントローラ

リソースコントローラを使うとアプリの基本的な操作であるCRUD(作成、一覧表示、編集、削除)などのアクションやそのルーティングが自動的にされます。

例えばusersのリソースコントローラだと下のようなアクションが自動で作られます。

HTTPメソッド URI アクション ルート名
GET /users index users.index
GET /users/create create users.create
POST /users store users.store
GET /users/{user} show users.show
GET /users/{user}/edit edit users.edit
PUT/PATCH /users/{user} update users.update
DELETE /users/{user} destroy users.destroy

作成

コントローラをつくるartisanコマンドに--resourceをつけます。

php artisan make:controller UsersController --resource

すると自動的にコントローラ内にこれらのアクションが用意されます。

UsersController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UsersController 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  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
    }

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

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

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

ルーティング

web.php
Route::resource('users', 'UsersController');

これだけですべてのアクションの紐づけができます。

また使うアクションを限定することもできます。作成、一覧表示のみを行う場合↓

web.php
//作成、一覧表示のみを行う場合
Route::resource('users', 'UsersController', ['only' => ['index', 'create', 'store', 'show']]);
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravelのリソースコントローラを使ってCRUDアクション作成

laravelのリソースコントローラについてのメモです。

公式リファレンス
https://readouble.com/laravel/5.8/ja/controllers.html?header=%25E3%2583%25AA%25E3%2582%25BD%25E3%2583%25BC%25E3%2582%25B9%25E3%2582%25B3%25E3%2583%25B3%25E3%2583%2588%25E3%2583%25AD%25E3%2583%25BC%25E3%2583%25A9

リソースコントローラ

リソースコントローラを使うとアプリの基本的な操作であるCRUD(作成、一覧表示、編集、削除)などのアクションやそのルーティングが自動的にされます。

例えばusersのリソースコントローラだと下のようなアクションが自動で作られます。

HTTPメソッド URI アクション ルート名
GET /users index users.index
GET /users/create create users.create
POST /users store users.store
GET /users/{user} show users.show
GET /users/{user}/edit edit users.edit
PUT/PATCH /users/{user} update users.update
DELETE /users/{user} destroy users.destroy

作成

コントローラをつくるartisanコマンドに--resourceをつけます。

php artisan make:controller UsersController --resource

すると自動的にコントローラ内にこれらのアクションが用意されます。

UsersController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UsersController 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  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
    }

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

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

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

ルーティング

web.php
Route::resource('users', 'UsersController');

これだけですべてのアクションの紐づけができます。

また使うアクションを限定することもできます。作成、一覧表示のみを行う場合↓

web.php
//作成、一覧表示のみを行う場合
Route::resource('users', 'UsersController', ['only' => ['index', 'create', 'store', 'show']]);
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む