記事・メモ一覧

default eye-catch image.

Laravel Mutator Accessor

たぶん Delphi/C# が起源だと思うんだが、データに紐づく規則や処理をモデルに寄せるパターン(Microsoft:The Repository Pattern)と同等の機能がPHP FrameworkであるLaravelのORM(Eloquent)にあり、流石に超便利だったのでメモっておく。 setter側をMutator、getter側をAccessorという。Mutator, Accessorを簡単にまとめると以下のような感じ。 Eloquentインスタンスに対して値をセットする際に必ずあるメソッド(Mutator)を経由する機能 Eloquentインスタンスから値をゲットする際に必ずあるメソッド(Accessor)を経由する機能 本家のドキュメントは以下のように続く。 Accessors and mutators allow you to format Eloquent attribute values when you retrieve or set them on model instances. For example, you may want to use the Laravel encrypter to encrypt a value while it is stored in the database, and then automatically decrypt the attribute when you access it on an Eloquent model. データに紐づくルールや処理をモデルに寄せることでコントローラの肥大化を防ぐ機能の一つだが、コントローラとモデルの間の取り決めを規約によって定めることで、コントローラからもモデルからも扱いやすくなる。 例えば、usersテーブルにfirst_nameという名前のフィールドがあったとする。 フィールドには小文字で入力し、使うときは必ず先頭1文字を大文字として使う、というルールがある場合Userモデル側を以下のような規約に従って書く。 <?php namespace App; use IlluminateDatabaseEloquentModel; class User extends Model { /* * Get the user\'s first name. * * @param string $value * @return string */ public function getFirstNameAttribute($value) { return ucfirst($value); } /* * Set the user\'s first name. * * @param string $value * @return void */ public function setFirstNameAttribute($value) { $this->attributes[\'first_name\'] = strtolower($value); } } コントローラからfirst_nameフィールドの値を取るコードは以下の通りだが、必ずAccessorを経由し値が返る。フィールドの値が何であれ先頭は必ず大文字になる。ブラウザ等に表示する際に加工する必要がない。 <?php $user = AppUser::find(1); $firstname = $user->first_name; ブラウザ等からデータが入って来たとき、それをusers.first_nameフィールドに格納する処理を書く際、必ずMutatorを経由する。 「小文字にする」という処理を一切意識しないで良い。 <?php $user = AppUser::find(1); $user->first_name = \'Sally\'; コントローラより上は涼しい顔をして重い処理の記述を省略できる。データに紐づくルールが重ければ重いほどモデルに寄せる効果が大きくなる。 例えば、データを暗号化して格納するケースにおいては、暗号化/復号処理をModelに隠蔽しControllerより上からは透過的に平文として扱うなど。 Eloquentは流石に雄弁だ。

default eye-catch image.

計量テンソルの物理的な意味

はじめに Tensor Flowを理解するために計量テンソルの物理的な意味の理解が不可欠なので数式を追ってみた。ちょっと時間かかったけど、計量テンソルまではOK。スカラー、ベクトルを説明するまではまだ理解できてない。しかし、Ad-HocなIT技術ばかり触っていると、数式の美しさは格が違うな。 計量テンソルが直感的に何を表しているのかは最後だけでOK 変換係数αik=gijって何?を理解するために共変ベクトル、反変ベクトルの定義を遡る必要がある ベクトルと変換 ある座標系の基底ベクトル(e1,e2,e3)を、別の座標系のベクトル(e1\',e2\',e3\')に変換することを考える。適当な係数αijを使って線形結合で表現すると、 e1\'=α11e1+α12e2+α13e3 e2\'=α21e1+α22e2+α23e3 e3\'=α31e1+α32e2+α33e3 αikを変換係数と呼ぶ。変換係数により基底ベクトルeから別の規定ベクトルe\'への座標変換を決定している。 まとめると以下のように表現できる。(HTMLじゃ厳しいです...) ei\'=Σk=13αiikek ダッシュ付きベクトルとダッシュ無しベクトルを入れ替えると ek=Σl\'=13αkl\'el\' 上の式に下の式を代入する。これはダッシュ無しベクトルをダッシュ付きベクトルに変換する式に、ダッシュ付ベクトルをダッシュ無しベクトルに変換する式を代入することを表す。もっと言えば、変換と逆変換を同時に行ってみる。 ei\'=Σk=13Σl=13αi\'kαkl\'el\' この右辺はeiiにならないといけないので、 Σk=l3αi\'kαkl\'=0 (i\'≠l\') Σk=l3αi\'kαkl\'=1 (i\'=l\') ダッシュ付きベクトルとダッシュ無しベクトルを入れ替えても同様に、 Σk\'=13αk\'lαk\'l=0 (i≠l) Σk\'=13αk\'lαk\'l=1 (i=l) 見事な感じで、Σk=13Σl=13αi\'kαkl\'は単位行列ということになる。話を戻すと変換、逆変換を同時におこなうと元に戻る、ということになる。 なお、クロネッカーのデルタを使うと、 Σk=l3αi\'kαkl\'=0 (i\'≠l\') Σk=l3αi\'kαkl\'=1 (i\'=l\') は、以下のように1つにまとめられる。 αi\'kαkl\'=δi\'l\' 同様に、 Σk\'=13αk\'lαk\'l=0 (i≠l) Σk\'=13αk\'lαk\'l=1 (i=l) は、以下のように1つにまとめられる。 αk\'lαk\'l=δk\'l 共変ベクトルと反変ベクトル ある基底ベクトルe=(e1,e2,e3)を別の基底ベクトルe\'=(e1\',e2\',e3\')ベクトルに変換する際の座標変換は以下のように表される。 ei\'=αi\'kek この時、変換係数αi\'kを用いて、基底ベクトルの変換式と同一の変換式に従うベクトルA=A1e1+A22+A33を共変ベクトルと呼ぶ。 Ai\'=αi\'kAk 一方、添字を上下逆にした変換係数αki\'ckに従うベクトルC=C1e1+C2e2+C3e3を反変ベクトルという。 C\'i=αki\'Ck ここで、eiを共変基底、eiを反変基底とよぶ。 共変基底、反変基底には次式が成り立つ。 ei・ej=δij 計量テンソル 共変基底ek,ekを用いたベクトルA=Akek=Akek。 それぞれに添字を上下反転させた基底ei,eiとの内積を取る。 ei・A=Akek・ei=Ak(ei・ek) ei・A=Akek・ei=Ak(ei・ek) 共変基底、反変基底の積 ei・ek=gikとする。 ei・A=Akgik ei・A=Akgik A=Aiei=Aieiであるから、 ei・Aiei=Akgik ei・Aiei=Akgik 整理すると、 ei・ei Ai=Ai=gikAk ei・ei Ai=Ai=gikAk つまり以下。 Ai\'=gikAk Ai\'=gikAk これは、ベクトルの共変成分、反変成分の変換式である。 共変成分、反変成分を相互変換する変換係数gij(=αij)の意味 ベクトルrの長さが微小に変化したとする。その微小変化をベクトルdr=dxiei=dxieiとする。 ds2 =dr・dr =dxiei・dxjej=gijdxidxj =dxiei・dxjej=gijdxidxj =dxiei・dxjej=gujdxidxj =dxidxi ei-ejを座標系として取ったとき、dxi、dxjを成分とすることを表す。 また、ei-ejを座標系として取ったとき、dxi、dxjを成分とすることを表す。 これらの座標系で各座標軸に沿った変化分の単純な積dxidxj、dxidxjと、本当の変化分の2乗ds2の比がgij、gijであることを表す。 gij、gijを計量テンソルと呼ぶ。

default eye-catch image.

詐欺サイトを発見したので独自調査してみる

ある商品を探していたのだが、迂闊にも詐欺サイトのカートをポチってしまった。 届いた確認メールが突っ込みどころ満載だったのでそのサイトの模倣元に確認して事なきを得たが、住所と電話番号と氏名を抜かれてしまった。 あれ、自分はITで食ってるんじゃなかったか?詐欺サイトにハマるなんて...。 と疑心暗鬼になった。せっかくなのでブログのネタにしてみる。 実は技術的にこのサイトの秘密を暴いてみようと思ったのだが、 それ自体が不正アクセス禁止法に触れるため載せられないことが判明した。 詐欺サイト自体のセキュリティは緩かった。 サイトの特徴 アパレルのECサイトです。模倣元の子サービスという設定。 リテラシが比較的高くない女性向けだと思います。 市場価格から適度に格安。明らかにパチもんという設定ではない、 楽天との関係を装っています。 かなり精巧に模倣されているが、致命的な抜けがあります。例えば... ドメインが怪しい 特定商取引法の掲示がない 模倣サイトの子サービスの扱いなのに模倣サイトの電話番号がない スマホからだとポチるかも... 誤解を恐れずに言うならば詰めが甘い。もっとできるはず。 なお、情報の少ないスマホ経由だとかなりキワドい。 実質的にはスマホから流入して軽くポチッた人が被害にあっていそうだ。 確認メール おそらくチャイナだろう。日本語がメチャクチャ。詰めが甘いんだよな。 大多数の日本人はここで止まると思う。実質的には個人情報を抜く目的なのかもしれない。 ゆうちょ銀行の口座番号に振り込めと来た。 偽サイトを見つけたら 金銭的な被害がないので警察も動かないでしょう。 100円とか振り込んで相手方の様子を見て遊ぶのも面白いかもしれません。 七面倒臭い展開が待っていると思うのでやりませんがw 出来ることなんて以下ぐらい。 模倣元に偽サイトか否かの確認と事実の報告 振込先金融機関に口座番号が詐欺サイトに使われていることの報告 どういう仕組みで実行犯は金融機関の口座を取得し利用できているのだろうか。 恐らく善良な市民の口座がハックされ犯罪に使われているのだろうが、 そのあたりは知らない方が身のためだと思うので詮索は終わります。 もし実被害が出た場合、警察は指定口座から実行犯を割り出すことができるのだろうか。 公権力はどこまで力を持っているのか興味はあります。興味だけです。 実はもっと技術的に解析を試みたのだが、いくら相手が犯罪者とはいえ、 不正アクセス防止法を犯す行為をネットに晒すことは社会人として許されることはないから書かない。 セキュリティ的に無防備なサーバが存在し、どういう訳がそこで今回のような模倣サイトが運営されていた。 やり得な世界が広がっている事実に寒気がした。

default eye-catch image.

Q-Lerningを試してみる(座学編)

そういえばQ熱って感染症があったな。不明の(Query)熱という意味だそうな。関係ないがQというパズルゲームがあって名作らしい。 食わず嫌いをしていても仕方がないのでちょっと調べてみた。割と単純な探索アルゴリズムの一種だった。自然界の~とか、脳内の~とか言うから胡散臭くなるだけで、コンピュータ上で動作させる他の探索アルゴリズムの一種だと思います。 結論は、枝コスト選択の難しさの解決を後回しにしたところで避けられない。というより、枝コスト選択を先にやらなくて良い、という事実が唯一にして最大のメリット。 アルゴリズムの概要 探索の際に選ぶ枝のコストを確率として予め求めておくのではなく、探索しながら更新していく。 前提は以下。 stは時刻tにおける状態。 atは時刻tにおける行動。 Q(st,at)は状態stにおいて行動atを選択する価値。 rt+1は環境の変化によって貰える報酬。 maxaQ(st+1,a)は 状態st+1のもとで最もQ値が高い行動aを選んだ場合のQ値。 γ(0<γ<1)は割引率。 α(0<α<1)は学習係数。 Q(st,at)を更新しQ(st+1,at+1)にする式は以下。 Q(st+1,at+1) := Q(st,at) + α(rt+1+γ maxaQ(st+1,a)-Q(st,at)) γ、rt+1の値によるが、Q(st+1,at+1)>Q(st,at)となるためには、Q(st,at)よりも、次の状態における最良の行動aを選択した価値Q(st+1,a)の方が大きい必要がある。 一般的にγ=0.9~0.99のように1に近い値を設定することが多いようなので、概ね最良の行動の選択maxaQ(st+1,a)による価値の増加分に報酬rt+1を加えたものがQ(st+1,at+1)となる。 アルゴリズムの設計 全ての状態とその時に取りえる行動の組(s,a)についてQ(s,a)の値をランダムに設定する。 t=0、s0にセットする。 状態stから行動atを選択し状態st+1とする。 状態の更新を一定回数行ったらt=0,s0に戻す。 グルグル回し、何回か終わったら終了。 状態の更新にはε-greedyアルゴリズムを用いる。状態stから状態st+1に遷移する際、常に最大のQ値となる行動を取るということは、最初にランダムで与えたQ(s,a)を教師として枝コストに確率を与えているのと同じになるからN.G.。定数ε(0<ε<1)を用い(1-ε)の確率で最大のQ値となる行動を選ぶようにする。 胡散臭くなってきた!結局枝コストの求め方の難しさに帰着する。たぶん確率密度とかの話ではなくエイヤっとεを決めるんだろう。

default eye-catch image.

重回帰分析と教師あり機械学習

機械学習と多変量解析は本質的に同じ。 重回帰分析 観測された事象から目的変数と説明変数の関係をモデル化する。 目的変数 = a×説明変数1+b×説明変数2+c×説明変数3+d 機械学習 大量のデータを読み込ませることで、人が教えることなくデータの特徴量を導き出す。 機械学習により求められる特徴量は本質的に重回帰分析の係数に相当する。 時期的に、多変量解析(統計) << データマイニング < 機械学習。 要は多変量解析(統計)の理解がなければデータマイニング・機械学習の理解はおぼつかない。 多変量解析はExcelを使ったサンプルが多い。 Excelを使った重回帰分析のサンプル Excelを使うと簡単に重回帰分析の実行結果を得られる。試しに実行してみる。 SNS広告(Seg.1)、Web広告(Seg.2)、口コミ広告(Seg.3)と売上実績(Sales)の関係が以下のようになっているとする。単位は無し。各広告手段の売上実績に対する寄与度をモデル化する。 つまり、Sales=a×Seg.1+b×Seg.2+c×Seg.3+d の係数(a,b,c,d) を求める。 Seg.1Seg.2Seg.3Sales 4.93.11.50.1 5.43.71.50.2 4.831.40.1 4.331.10.1 5.841.20.2 5.74.41.50.4 5.43.91.30.4 5.13.51.40.3 5.73.81.70.3 5.13.81.50.3 回帰統計量 重回帰式 Sales=a×Seg.1+b×(Seg.2)+c×(Seg.3)+d の当てはまりの良さを表す統計量。 通常、重相関係数Rと重決定係数R2は説明変数の数が多いほど大きくなる傾向がある。 補正R2は説明変数の数を考慮した当てはまりの良さを表す。 そのため一般的に当てはまりの良さを見るためには補正R2を参照する。 重相関 R0.874912 重決定 R20.765472 補正 R20.648207 標準誤差0.06962 観測数10 分散分析表 回帰式の全ての係数が同時に0であることの分析。有意F値が0.05未満ならば、統計的に全ての係数が0でないといえる。 有意F値が0に近ければ近いほど重回帰式の信頼度は高いことを表す。 自由度変動分散観測された分散比有意F 回帰30.0949180.0316396.5277516380.025607 残差60.0290820.004847 合計90.124 以下より、a=-0.133596092、b=0.315699216、c=0.14050611、d=-0.403573178。係数の符号が正の場合、説明変数と目的変数に正の相関があることがわかる。係数の符号が負の場合は負の相関。絶対値は相関の強さ。 係数標準誤差 tP-値 切片-0.4035731780.281209521-1.4351334080.201255935 Seg.1-0.1335960920.110652276-1.2073506010.27272798 Seg.20.3156992160.1056493012.9881808270.024377448 Seg.30.140506110.1522815480.9226732460.391770244 下限 95%上限 95%下限 95.0%上限 95.0% 切片-1.0916680890.284521732-1.0916680890.284521732 Seg.1-0.4043524570.137160273-0.4043524570.137160273 Seg.20.0571846890.5742137430.0571846890.574213743 Seg.3-0.2321134140.513125635-0.2321134140.513125635

default eye-catch image.

PythonでAES EncryptしてPHPでAES Decryptできなかった話

標題の通りなのですが。AESなんて枯れてるんだから鍵長と暗号モードを合わせれば出来るだろうと、軽く見積もってました。結果、無茶苦茶頑張ってみましたが出来ませんでした! 結論から先に書くと、以下の方法で逃げました。 PythonでEncrypt/Decrypt Classを書く Python側からは上記のClassをそのまま使う 上記のClassを叩くPythonスクリプトを書き、PHPからシェル経由でそのスクリプトを実行する。 もっと頑張れば道が見つかったかもしれませんが、本当にPython/PHPをクロスして暗号化/復号の対ができるのか心配になって、これに落ち着きました。 出来ない理由.. 正直出来ない理由もハッキリしません。 だいたいどちらでも以下ぐらいは設定できるものなのですが、以下を合わせたぐらいでは片方で暗号化したものを復号することができません。 鍵長=256bit Cypher Algorythm=Rijndael 暗号モード=ECB orCBC まともな暗号処理をするには暗号モードにECBは使えずInitialVector(IV)を与える必要があるのですが、乱数からIVを生成する箇所の共通性が怪しかったり、Python側では共通鍵の鍵長にAPIで制限がかかるものの、PHPでは任意に指定できたり、本当に実装すると突っ込みどころ満載になります。 Pythonのコードはだいたい以下のような感じになります(IVを共有するためにダイジェストにIVを含んでいるのは本質的でないので除いてみてください)。 PythonのCrypto.Cipherは Encryptした結果を自力でPaddingしてBase64エンコードしてますが、PHPのmdecryptはいきなりPrintableな文字列を要求します。普通に考えて、PHPのmdecryptがBase64デコードして同じようにPaddingを取り除くのを期待するのはナンセンスでしょ。 import base64 from Crypto import Random from Crypto.Cipher import AES class AESCipher(object): def __init__(self, key, block_size=32): self.bs = block_size if len(key) >= len(str(block_size)): self.key = key[:block_size] else: self.key = self._pad(key) def encrypt(self, raw): raw = self._pad(raw) iv = Random.new().read(AES.block_size) cipher = AES.new(self.key, AES.MODE_CBC, iv) return base64.b64encode(iv + cipher.encrypt(raw)) def decrypt(self, enc): enc = base64.b64decode(enc) iv = enc[:AES.block_size] cipher = AES.new(self.key, AES.MODE_CBC, iv) return self._unpad(cipher.decrypt(enc[AES.block_size:])) def _pad(self, s): return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs) def _unpad(self, s): return s[:-ord(s[len(s)-1:])] 気付いたこと 何か勘違いしているかもしれませんが、早々に別の道に進みました。

default eye-catch image.

実践 PSR-4 クラスをspl_autoloaderを使ってautoloadしてみる最も簡単なサンプル

PSR-4の一次情報を読んだことだし、現在の理解でPSR-4 Autoloadに対応したクラスを作成し実際にAutoloadしてみる。composerもPSR-4に対応しているが、まずはPHP-Figがサンプルとして公開しているspl_autoloaderを使った例を試すことにする。 仕様は以下の通り。 Fully qualified class name ikutyexamplePsr4HelloWorld Namespace Prefix ikutyexamplePsr4 Base Directory ./src/ikuty/example/Psr4 Resulting file path ./src/ikuty/example/Psr4/helloworld.php サンプルクラスの作成 ./src/ikuty/example/Psr4/helloworld.phpを以下の通り作成する。 $ pwd ./src/ikuty/example/Psr4 vi helloworld.php <?php namespace ikutyexamplePsr4; class HelloWorld { public function __construct() { echo \"Hello World!\"; } public function say() { echo \"Hello World!\"; } } 呼出側の作成(PSR-0的) PHP Figにあるクロージャ版spl_autoloaderを使った実装例を試してみる。 ikutyexamplePsr4HelloWorldをnew()すると、spl_autoload_registerで登録したクロージャが評価される。 なお、名前空間の深さとBaseDirectoryの深さ等しくしている意味でPSR-0的なサンプル。 [sample.php] <?php 2 spl_autoload_register(function ($class){ 3 4 //project-specific namespace prefix 5 $prefix = \'ikuty\\example\\Psr4\\\'; 6 7 //base directory for the namespace prefix 8 $base_dir = __DIR__ . \'/src/ikuty/example/Psr4/\'; 9 10 //does the class use the namespace prefix? 11 $len = strlen($prefix); 12 if (strncmp($prefix, $class, $len) !== 0){ 13 // no, move to the next registerd autoloader 14 return; 15 } 16 17 //get the relative class name 18 $relative_class = substr($class, $len); 19 20 //replace the namespace prefix with the base directory, replace namespace 21 //separators with directory separators in the relative class name, append 22 //with .php 23 $file = $base_dir . str_replace(\'\\\',\'/\', $relative_class).\'.php\'; 24 25 //if the file exists, require it 26 if (file_exists($file)) { 27 require $file; 28 } 29 30 }); 31 32 $example = new ikutyexamplePsr4HelloWorld(); 33 $example->say(); 名前空間プレフィックスとBaseDirectoryの紐づけは結局人力でやっている。「名前空間プレフィックス」と「クラス名」の間にある「サブ名前空間」を読み飛ばしている。名前空間プレフィックスに続く「サブ名前空間」分をクラス側が自由に使えるところが興味深い。 実行結果 実行してみる。実行結果から分かりにくくて恐縮だが、new()してもHello World!は出力されず、say()メソッドを実行したときにHello World!が2回表示された。late-binding的な感じ。 $ php sample.php Hello World!Hello World! 名前空間の深さと関係なくBaseDirectoryを設定する(PSR-4的) 例えば、ikutyexamplePsr4HelloWorldの名前空間プレフィックスikutyexamplePsr4をBaseDirectory ./ikuty-example-psr4 に紐づければ、名前空間がどれだけ深くてもデプロイは影響を受けない。 Fully qualified class name ikutyexamplePsr4HelloWorld Namespace Prefix ikutyexamplePsr4 Base Directory ./src/ikuty-example-Psr4 Resulting file path ./src/ikuty-example-Psr4/helloworld.php <?php 2 spl_autoload_register(function ($class){ 3 4 //project-specific namespace prefix 5 $prefix = \'ikuty\\example\\Psr4\\\'; 6 7 //base directory for the namespace prefix 8 //$base_dir = __DIR__ . \'/src/ikuty/example/Psr4/\'; 9 $base_dir = __DIR__ . \'/src-ikuty-example-psr4/\'; 10 11 12 //does the class use the namespace prefix? 13 $len = strlen($prefix); 14 if (strncmp($prefix, $class, $len) !== 0){ 15 // no, move to the next registerd autoloader 16 return; 17 } 18 19 //get the relative class name 20 $relative_class = substr($class, $len); 21 22 //replace the namespace prefix with the base directory, replace namespace 23 //separators with directory separators in the relative class name, append 24 //with .php 25 $file = $base_dir . str_replace(\'\\\',\'/\', $relative_class).\'.php\'; 26 27 //if the file exists, require it 28 if (file_exists($file)) { 29 require $file; 30 } 31 32 }); 33 34 $example = new ikutyexamplePsr4HelloWorld(); 35 $example->say(); 結論 PHP-Figがサンプルとして提供しているspl_autoloader(クロージャ版)をお試し実装してみた。 PSR-4は名前空間プレフィックスのベースディレクトリの関連を記述する仕様であり、ベースディレクトリの物理的な配置が名前空間プレフィックスに直接影響を受けない。 ベースディレクトリが深くならなくて良い

default eye-catch image.

Laravel5 Form Request Validationによるコントローラの軽量化

フォームのビジネスロジック(検証や保存)をコントローラに書くと、どうでも良いコードでコントローラが重くなってくる。フォームが複数ある場合、だいたい似たり寄ったりのコードが量産されていく。本エントリでは、Laravel5 の Form Request Validation によってコントローラからバリデーションロジックを完全分離する方法について記述する。 Form Request Validation - バリデーションの分離 流れは以下の通り。 AppHttpRequestsRequestクラスを派生し、ContactRequestクラスを作成する。 コントローラメソッドにて、AppHttpRequestsRequestクラスのインスタンスではなく ContractRequestクラスのインスタンスを受けるようにする。 コントローラメソッドに入ったときには既にContactRequestクラスによるバリデーションが完了していて、データが正しい前提で処理できる。 ContactRequestクラス、ContactRequestTraitクラスの例を以下に示す。 <?php namespace AppHttpRequests; class ContactRequest extends Request { use ConfirmRequestTrait; /** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return true; } /** * Get the validation rules that apply to the request. * * @return array */ public function rules() { return [ \'name\' => \'required\', \'email\' => \'required|email\', \'subject\' => \'required\', \'content\' => \'required\', ]; } /** * Set custom messages for validator errors. * * @return array */ public function messages() { return [ // ]; } /** * Set custom attributes for validator errors. * * @return array */ public function attributes() { return [ \'name\' => \'お名前\', \'email\' => \'メールアドレス\', \'subject\' => \'件名\', \'content\' => \'内容\', ]; } } <?php namespace AppHttpRequests; use IlluminateContractsValidationValidator; trait ConfirmRequestTrait { /** * Set custom messages for validator errors. * * @param IlluminateContractsValidationFactory $factory * * @return IlluminateContractsValidationValidator */ public function validator($factory) { // 値検証前の処理 if (method_exists($this, \'beforeValidate\')) { $this->beforeValidate(); } $validator = $factory->make( $this->all(), $rules, $this->messages(), $this->attributes() ); $validator->after(function ($validator) { $failed = $validator->failed(); // 値検証後の処理 if (method_exists($this, \'afterValidate\')) { $this->afterValidate($validator); } }); return $validator; } /** * Format the errors from the given Validator instance. * * @param IlluminateContractsValidationValidator $validator * * @return array */ protected function formatErrors(Validator $validator) { $errors = parent::formatErrors($validator); return $errors; } } Form Request Validation - コントローラ側 ポイントは、storeメソッドの引数に ContactRequestヒントが渡されていること。sotreメソッドに入る前にContactRequestによりバリデーションが実行され、バリデーションに成功した時に限り、sotre()メソッドに入る。バリデーションが失敗すると、その前のアドレスにリダイレクトされる。コントローラから一切のバリデーションロジックを排除できた。 <?php namespace App¥Http¥Controllers; use App¥Http¥Requests¥ContactRequest; use App¥Repositories¥ContactRepository; class ContactController extends Controller { /** /* @var ContactRepository */ protected $repository; /** /* @constructor /* param ContactRepository $repository */ public function __construct(ContactRepository $repository) { $this->repository = $repository; } /* * */ public function index() { ... } /** * @var ContactRequest $request * */ public function store(ContactRequest $request) { } }

default eye-catch image.

PSR-4 の理解

What\'s PSR-4 ? そもそもPSRって何の略だろうと調べたがそこから出てこなかった。 ↓なんじゃないか、という意見あり。 PHP Standard Recommendation PHP Specification Request カテゴリ毎に数字が割り当てられており他にも以下が存在する。 PSR-0 Autoloading PSR-1 Basic Coding Standard PSR-2 Coding Style Guide PSR-3 Logger Interface PSR-4 Improved Autoloading PSR-6 Chaching Interface PSR-7 HTTP Message Interface PHP-FIGという団体で取りまとめられている。http://www.php-fig.org/ PSR-4 それでは早速一次情報から漁ってみる。どのパスにどのクラスを配置するのか仕様を決めたいというのが根っこにある。決まりがあればクラスを使う側が楽だから。楽に使ってもらえるよう配布手段に規約を設ける。PSR-0(等?)と互換性がある。(PSR-0以外にもこういう決まりがあるのか?) This PSR describes a specification for autoloading classes from file paths. It is fully interoperable, and can be used in addition to any other autoloading specification, including PSR-0. This PSR also describes where to place files that will be autoloaded according to the specification. 仕様 言葉遊び ドキュメント内では\"class\"は class,interfaces,traits,それに似た構造を指すそうだ。あくまでも外部から使用する対象と配置に関する仕様だよ、ということだ。対象は何でも良い。 The term \"class\" refers to classes, interfaces, traits, and other similar structures. 完全修飾クラス名 完全修飾クラス名は次のような形式となるそうだ。 A fully qualified class name has the following form: \<NamespaceName>(<SubNamespaceNames>)*<ClassName> いくつか決まり事がある。 The fully qualified class name MUST have a top-level namespace name, also known as a \"vendor namespace\". 完全修飾クラス名にはベンダーを表すユニークな名前空間が入っていないといけない。 NamespaceNameが一意なのか、NamespaceNameとSubNamespaceNamesの合わせ技で一意なのか不明。 GitHubに上がってるのを見るとNamespaceNameだけで表現しているようだ。「トップレベル」って「一番最初=NamespaceName」のことか?? The fully qualified class name MAY have one or more sub-namespace names. 補助的に名前空間を複数追加しても良い。 階層構造を持った複雑な名前空間も定義できるということ。 The fully qualified class name MUST have a terminating class name. 完全修飾クラス名の最後はクラス名でなければならない。 Underscores have no special meaning in any portion of the fully qualified class name. アンスコは特別な意味を持たない。 アンスコを前後の識別子の接続子のように使うフレームワークが多いからね。 アンスコは単なる文字。 Alphabetic characters in the fully qualified class name MAY be any combination of lower case and upper case. 大文字小文字の任意の組み合わせで良い。 大文字小文字に意味を持たせるフレームワークが多いからね。 All class names MUST be referenced in a case-sensitive fashion. 大文字小文字を区別する。 ファイルをロードする側の決まりごと A contiguous series of one or more leading namespace and sub-namespace names, not including the leading namespace separator, in the fully qualified class name (a \"namespace prefix\") corresponds to at least one \"base directory\". NamespaceNameといくつかのSubNamespaceNameを「名前空間プレフィックス」と呼ぶ SubNamespaceNameが複数個あった場合その全てが「名前空間プレフィックス」になるとは読めない。 完全修飾クラス名とは「名前空間プレフィックス」+(「サブ名前空間」)+「クラス名」となる。 「名前空間プレフィックス」がディレクトリ名と対応している必要がある。と書いてあるがサンプルの「BaseDirectory」が名前空間プレフィックスと全然違う。意味不明。 The contiguous sub-namespace names after the \"namespace prefix\" correspond to a subdirectory within a \"base directory\", in which the namespace separators represent directory separators. The subdirectory name MUST match the case of the sub-namespace names. 名前空間プレフィックスに続くサブ名前空間が、BaseDirectoryに続くサブディレクトリに対応する。 サブ名前空間とサブディレクトリの大文字小文字は一致している必要がある。 The terminating class name corresponds to a file name ending in .php. The file name MUST match the case of the terminating class name. 終端のクラス名は、大文字小文字が一致するphpファイルと対応する。 例 PSR-4の例。やはり、どうも規則性が見えない。 FULLY QUALIFIED CLASS NAME NAMESPACE PREFIX BASE DIRECTORY RESULTING FILE PATH AcmeLogWriterFile_Writer AcmeLogWriter ./acme-log-writer/lib/ ./acme-log-writer/lib/File_Writer.php AuraWebResponseStatus AuraWeb /path/to/aura-web/src/ /path/to/aura-web/src/Response/Status.php SymfonyCoreRequest SymfonyCore ./vendor/Symfony/Core/ ./vendor/Symfony/Core/Request.php ZendAcl Zend /usr/includes/Zend/ /usr/includes/Zend/Acl.php 全然規則性が見えないぞ? 全然しっくりこないのでさらに調べてみた。COMPOSERがだいぶ前にPSR-4に対応したらしいのでAUTOLOADの補完ルールを色分けした。を参考にさせて頂きました。 FULLY QUALIFIED CLASS NAME NAMESPACE PREFIX BASE DIRECTORY RESULTING FILE PATH AcmeLogWriterFile_Writer AcmeLogWriter ./acme-log-writer/lib/ ./acme-log-writer/lib/File_Writer.php AuraWebResponseStatus AuraWeb /path/to/aura-web/src/ /path/to/aura-web/src/Response/Status.php SymfonyCoreRequest SymfonyCore ./vendor/Symfony/Core/ ./vendor/Symfony/Core/Request.php ZendAcl Zend /usr/includes/Zend/ /usr/includes/Zend/Acl.php 訳にも書いたが、全てのサブ名前空間が名前空間プレフィックスに含まれる訳ではないことに注意。名前空間プレフィックスに含まれなかったサブ名前空間が突然ファイルパスに出現したりする。 サブ名前空間とBaseDirectoryの規則性について、サブ名前空間をハイフンで区切った一つのディレクトリと対応させる場合もあるし、階層構造まで一致させる場合もある。名前空間プレフィックスとBase Directoryの関係性は割と柔軟。

default eye-catch image.

筋トレ強度を上げて1週間、記録を振り返る

筋トレ強度を上げて1週間経過した 有酸素運動中心のシェイプアップに、強度の高い筋トレを追加した。 1週間経過し、早速、体重・体脂肪率グラフに変化があった。 順調に減少していた体重が68kgまで戻り、体脂肪率が減少しはじめた。15.5%から14.5%へ約1%の減少。こうやってレコーディングを続けていくと身体の変わり目の時、体重、体脂肪率の傾向が急激に変化する瞬間があることに気づく。身体の水分量とか様々なバランスが変化する瞬間なのかもしれない。 消費カロリーが減った? ちょっと気になって半年分の時系列消費カロリーをプロットしてみた。特に消費カロリーが落ちて体重が増えた、ということではないようだ。左端の異常値はtrackerの誤動作ではなくインフルエンザにかかったときの記録。1600付近の値は、Fitbit Charge HRを付けなかったときの記録。 とにかく炭水化物の摂取を避けているので、2500もあればカロリー収支はマイナスになっていると思う。3000消費するとフラフラする。5月から7月にかけて一気に体重を落とした範囲では2800カロリーを目安としていた。カロリー収支に問題はないはずなので、このまま2800を維持して体重、体脂肪率の変化を追ってみる。