tanikoのぶろぐ

Laravelのクエリビルダでifとかを使う

はじめに

Laravelで特定のクエリパラメータを使ってクエリを組み立てたいときってありませんか? 例えば, 検索なので, since_idがあれば, セットされている値以降で絞り込んで検索とかです.

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Asset;
use App\Http\Requests\Asset\SearchRequest;

class AssetController extends Controller
{
    public function search(SearchRequest $request)
    {
        $query = Asset::query();
        if ($request->has('since_id')) {
            $query = $query->where('id', '>=', $request->input('since_id'));
        }
        if ($request->has('until_id')) {
            $query = $query->where('id', '<=', $request->input('until_id'));
        }
        return $query->get();
    }
}

こんな感じで書けますよね.
ただ, これだと何個もif文を書いていくことになります. メソッドチェーンでやってみたくなったので, やってみましょう.

やり方

マクロの登録

まず, クエリビルダでifwhereIfを使えるように登録します. app/Providers/AppServiceProvider.phpに以下のコードを加えます.

<?php
// app/Providers/AppServiceProvider.php
namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Facades\Schema;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Builder::macro('if', function (bool $condition, callable $func) {
            return $condition ? $func($this) : $this;
        });
        Builder::macro('whereIf', function (bool $condition, $column, $operator = null, $value = null, $boolean = 'and') {
            return $condition ? $this->where($column, $operator, $value, $boolean) : $this;
        });
    }
}

まず1つ目は, コールバック関数を与える方法です. これは, 複雑なクエリを付け加えたい時に使用します. 単純なwhere句を加えたいだけなら, この方法はおすすめしません.
2つ目はwhere句のみを付属させるものです. where()とほぼ同じ使い方なので, こちらがおすすめです. where()との違いは, 第1引数がtrueならばwhereが加えられるという点です.

使い方

ユーザの投稿一覧の取得のサンプルコードです.

<?php
// 1つ目 if
$posts = $user->posts()
    ->if($request->has('since_id'), function ($query) use ($request) {
        return $query->where('id', '>=', $request->input('since_id'));
    })->get();

// 2つ目 whereIf
$posts = $user->posts()
    ->whereIf($request->has('since_id'), 'id', '>=', $request->input('since_id'));

こんな感じでメソッドチェーンをつなげていくことができます.
どちらの方が見やすいのか. ブロックで分けるべきか, 1行でまとめるべきか. あと, 型宣言や関数呼び出しの速度も.

リンク

Laravel API - https://laravel.com/api/5.5/Illuminate/Database/Eloquent/Builder.html#method_where

マルチバイト周りに対応したローマ数字のパーサを作った

日本語とは厄介なのでしょうか? とても扱いやすい言語だとは思います. 特に数字周りに関しては素晴らしい思っています. 英語の数え方とか加減乗除とかは厄介だと思います.
では, 日本の厄介な部分はどこかというと, マルチバイト文字だということ. 文字数が多すぎる.
ということで, 今回はローマ数字周りのライブラリです.

まずは, マルチバイト周りのローマ数字について. 10を例に話します.

xX
説明半角小文字半角大文字全角小文字全角大文字ローマ数字(小文字)ローマ数字(大文字)
Unicode12088653686533685698553

11を表すには? xi? XI? xi? XI? ? ?

辛い.

そんなわけでtaniko/romansを作りました. インストールはcomposer require taniko/romansでできます.

<?php
require 'vendor/autoload.php';

// 全角大文字
var_dump(Taniko\Romans\Parser::toInt('MMXVII'));
// int(2017)

// ローマ数字(大文字)
var_dump(Taniko\Romans\Parser::toInt('MMⅩVII'));
// int(2017)

ちなみに, PHP 7.2からはmb_ord(), mb_chr()が使えるようになりました. symfony/polyfill-mbstringを使わなくてもいいようになりました.

最後に, PHPは最高ですね.

既存のライブラリにマルチバイト周りをASCIIに変換する部分だけのPRでも作る?

pixiv 2017 SUMMER BOOT CAMPに参加してきました

ピクシブさんのインターンに行ってきたのでそのお話です. 去年も参加したので, 1年ぶり2度めのピクシブさんでのインターンでした.

参加するまで

選考について

GitHub選考が今年もあったので, それを使って応募しました. GitHub選考は, 履歴書とか書かなくていいのでおすすめです.

1次選考が終わったらオンライン面接がありました. 内容は, なぜ(今年も)応募したのかや, 参加希望コースのこととか, コーディングテストとかです. コーディングテストに関しては, 好きな言語でやっていいとのことなので, もちろんPHPでやりました.

エントリーから面接含めて2週間弱で, 参加させていただけることが決まりました.

前日

去年同様に, 初日の朝に滋賀から東京に行って, 最終日の夜に帰ろうとしていたのですが, 東京に住んでいる友達にお願いして, 泊めてもらえることになりました. おかげさまで移動がだいぶ楽になりました. 感謝です.

やったこと

初日の午前中は, インターンの概要説明, 自己紹介, 機密保持契約とかをやっていました. 社員の方はもちろんなのですが, 参加しているインターンの人もすごい人ばっかりでした.

午後からは, 開発環境の構築から始まり, 実際に開発を行い始めました. 開発環境の構築なのですが, データが大きすぎるので, 開発用のサーバのコードを触って行うというものだったので, SSHとかの知識がほんの少し必要. セットアップの方法はまとめられているので, 基本的にはその通りにやっていけば行えました. SSHの公開鍵周りのことがあるので, GitHubに公開鍵を登録しておくと楽です.

開発なのですが, 今回, 私が参加したのは技術基盤コースというもので, pixivや他のサービスで利用されているライブラリやルーティングをリファクタリングなどが主な内容でした.

具体的には

  • PDOから独自のライブラリに移行
  • リファレンス渡しをなくす
  • ユーザが原因のエラーのログレベルを修正
  • とあるエラー時のログ用テーブルの設計とロギング用クラス作成

など. テストがないようなところはテストも作ったりしていました. 基本的にはPHPを触っていたのですが, エラーの再現をさせるためにフロント(TypeScript)のコードも読むことがありました.

GitHubにインターン生用のスナップショットがおいてあって, そこで開発していきました.

流れとしては,

  • コードを書く
  • PRを送る
  • コードレビューを受ける
  • 本体(実際に運用されているリポジトリ)にマージされる
  • デプロイ

といった感じです. 時々, 本体側で更新されたコードもまとめて降ってきました.
チーム開発なので, リーベースしたり, コミットをまとめたりなどをすることがありました. 一度, PRをクローズ, スカッシュ, リベースなどをやってしまって, PRを再オープンするのに手間取って大変でした.
インターン中にいくつかのPRがマージされました. 実際に本体でマージされてデプロイされる画面も見せていただきました.

最終日は, インターンの成果発表がありました. インターンはコース毎に分かれてやっていたので, 他のコースの人がどんなことをやっているのかは, その時まではよくわかっていなかったのですが, 皆さん機能追加やOSSへコントリビュートしたり楽しそうでした.
あと, すべてが終わったあとにオフィス見学をさせていただきました.

さいごに

開発業務以外にも, 全社ミーティング, インターン生向けの講義とかがあり, ピクシブさんの現状であったり, プロジェクトのこれからの方針とかも聞かせて頂きました.

一緒に働かせていただいて, 周りの方々はすごい人ばかりだなと感じました. メンターの方々に相談すれば一緒に考えてくださり, とても親切な方々でした.

大変勉強になった5日間でした. ピクシブさんには大変お世話になりました. このような機会をいただき, ありがとうございました.

Saori v3のリリース

Saoriのバージョン3をリリースしました. 実際にリリースしたのは5月とかなり前です.
v3での主な変更点は以下のとおりです.

  • github.io以外で使用可能
  • 設定ファイルをJSONからYAMLに変更
  • テーマを外部から追加可能

まず, github.io以外で使用可能になったので, 自分のVPSなどでブログを公開できるようになりました. config/env.ymlpublicにURLを記述します.

設定ファイルをYAMLに変えたのは, JSONの記述が辛かったからです. 括弧とかめんどくさかったのです.

テーマを外部から追加可能というのは, テーマを追加できるようにしたということ(?). コードを見たほうが早い.

<?php
require __DIR__.'/vendor/autoload.php';
$app = new Taniko\Saori\Application(__DIR__);
$app->addTheme('theme-name', __DIR__ . '/theme/append-theme');
$app->run();

今までだとtaniko/saoriに存在するテーマしか使用できなかったのですが, このような感じでテーマを追加して, それを使用できるようにしました.

やっぱり, PHPは最高ですね!

2016年のまとめ

もう年末です. 今までダラダラと過ごしていた私ですが, 今年は珍しく活動したのでそのまとめです.

大学のオープンキャンパス手伝い

4月頃, 3回生のときに授業の一環で作成した簡単な情報推薦のサイトをオープンキャンパスで紹介する事になりました. 簡単にコードを修正して終わりのつもりだったのですが, 「前のままだと地味なので推薦できるものを書籍だけでなくて浮世絵も追加してね」と先生に言われて新たにコードを書くことになりました.

PHPカンファレンス関西

2016年12月31日現在, GitHub Pagesを利用してブログをやっています. これですね. 4月ごろから, このようなブログを生成する静的サイトジェネレータ Saoriを作成していました. PHPカンファレンスに行ったことがなかったのですが, LTを応募したら通ったのでSaoriについて話してきました. 初めてのイベントです.
詳しくはPHPカンファレンス 関西2016でLTに書いてあるのでそちらを.

インターン

8月末~9月末にピクシブのインターンに参加してきました. これも初めてのインターンです. pixivのメンテナンスを行いました. バグ修正とかコードのリファクタリングとかです. 詳しくはpixiv 2016 SUMMER BOOT CAMPに参加に書いてあるのでそちらを.


こんな感じで初めての行動が多い1年でした. 3つともPHP関連ですね. PHPは楽しいです. みんなもPHPをやろう!
ついでに個人的な話以外を. 今年は百合姫が月刊誌になりましたね. あと早見沙織さんが1stアルバム「Live Love Laugh」と, コンサートの映像・音声が特典でついたミニアルバム「live for LIVE」をリリースしましたね. とってもいいものですので, みなさんもどうぞ.