- 投稿日:2020-02-19T19:44:39+09:00
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が使いたかったので回避
- 投稿日:2020-02-19T19:22:55+09:00
【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)以上です!!!
ここまで読んでいただきありがとうございました!!
疑問、気になるところがございましたら、質問、コメントよろしくお願いします!!!
- 投稿日:2020-02-19T16:01:15+09:00
【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-commitIS_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_ERRORgit commit するたびにエラーを指摘されて大変ですが、
命名規則の徹底や複雑度改善がされていい感じですね。
今後ほかのサイトにも導入してみようと思います以下を参照して修正予定
phpmdのルール一覧
githooksのpre-pushを共有してレポジトリを健全に保つ
- 投稿日:2020-02-19T14:27:46+09:00
Laravelのリソースコントローラ
laravelのリソースコントローラについてのメモです。
リソースコントローラ
リソースコントローラを使うとアプリの基本的な操作である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.phpRoute::resource('users', 'UsersController');これだけですべてのアクションの紐づけができます。
また使うアクションを限定することもできます。作成、一覧表示のみを行う場合↓
web.php//作成、一覧表示のみを行う場合 Route::resource('users', 'UsersController', ['only' => ['index', 'create', 'store', 'show']]);
- 投稿日:2020-02-19T14:27:46+09:00
Laravelのリソースコントローラを使ってCRUDアクション作成
laravelのリソースコントローラについてのメモです。
リソースコントローラ
リソースコントローラを使うとアプリの基本的な操作である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.phpRoute::resource('users', 'UsersController');これだけですべてのアクションの紐づけができます。
また使うアクションを限定することもできます。作成、一覧表示のみを行う場合↓
web.php//作成、一覧表示のみを行う場合 Route::resource('users', 'UsersController', ['only' => ['index', 'create', 'store', 'show']]);