ushumpei’s blog

生活で気になったことを随時調べて書いていきます。

Laravel ざっくり調べた

Laravel、急いで勉強する必要ができたので、概要まとめます。あくまでざっくり調べたまとめなので、コード書いたときに誤認に気がつくんだろうなと思います。

phpもしっかり勉強したことがないので、php 7 のインストールや基本的な文法からやり直します。Laravel に関しても完全に手探りなので、フレームワークの基本的な使い方やデファクトなパッケージについて調べます。

Laravel はバージョンごとにかなり差異があるという話を聞きます。なのでバージョンに関しては慎重に選ぶべきだとは思うのですが( LTS などを選択した方が合理的だと思うのですが )、大枠をつかめればいいかなと思っているので、せっかくだし現在最新の Laravel 5.6 についてここでは書きたいと思います。

php

php は対応しているサーバーにおけば動くスクリプト言語で、リクエストとかセッションとか変数にアクセスできて便利だなーくらいの認識です。言語の概要ってどう書けばいいのかわかりません。

とりあえず小さなコードを書きつつ、「インストール」、「基本的な文法」、「デバッグ」、を学びまず軽度な修正をできるようにし、「ファイルの取り扱い」、「外部パッケージの取り扱い」を学んで機能の追加ができるようになればいいなと思います。

インストール

php 7.1 以上をインストールしたいと思いましたが、私の環境では macOS を High Sierra にバージョンアップしたからなのか、すでに php 7.1 が入っていました。それ以前の macOS を使っている場合は php -v でバージョンを確認の上 7 以下が入っていたら、Homebrew などでインストールするといいかもです。

$ brew install php
$ vim ~/.bashrc
# 以下を追記
export PATH="$(brew --prefix php)/bin:$PATH"
$ source ~/.bashrc

基本的な文法

ここの抜粋です。自分が見直しやすいようにメモしておきます。

index.php ファイルを作って、以下を書き込みます。

<?php
echo 'hello';

php + ファイル名でコードの実行ができます。

$ php index.php
hello

このファイルを編集しながら文法練習していきます。行末のセミコロンは必須みたいです。また、 php -a で対話環境の起動ができるみたいです。

  • 変数: 基本的に $変数名 = 値 で宣言。型は色々ある。文字列、数値は他の言語とだいたい同じで困らなそう。
    • 論理型: TRUE とか True とか true とかありで不安。FALSEは同値な値がたくさんある。論理型を取り扱う際は注意する。
    • 配列: リテラルで書けるので基本的に気にしなくていいが、オブジェクトではない(?)ので length とか無い。配列操作に関しては色々関数があってややこしそう。
    • 辞書: $dic = [ 'h' => 'hoge', 'f' => 'fuga']; のようにアロー => でキー・バリューの組みを記述していく。要素の追加は $dic['p'] = 'piuo'; という想像通りの感じ。
    • $_REQUEST, $_POST などのスーパーグローバル変数は、そんなものがそういえばあるという感じで、存在を覚えておく。
  • 定数: ローカル定数がない!?グローバル定数はdefine(名前, 値)const 名前 = 値 で。const はトップレベルスコープなので関数内でイミュータブルな値が欲しいのなら define を使おうかと思ったが、関数外からアクセスできるようになってしまうので気持ちが悪い。なので再代入に関しては 定数に頼らず読みやすいコードを書く という当たり前の結論。多分使い方的には環境変数的なもの。
  • 関数: function 関数名(変数型 $変数名1, 変数型 $変数名2...): 戻り値型 で宣言。型情報かけるようになった(書かなくても動くは動く)。return で戻り値を返す。変数のスコープは基本的に関数内で閉じている。デフォルト引数、可変長引数ありだけど順番に気をつける。参照渡しもあるけど今はあまり気にしない。
    • 可変関数: function hoge() { … } があれば "hoge"() が実行できるらしい。リフレクションみたい、便利だと思う。
    • クロージャ: 無名関数。function () { ... }。親のスコープから値を引き継ぐには専用の構文がいるので、安心感ある。
  • 演算子: 参照代入 $a = &$b は読むとき気をつける。比較演算は等号も不等号も = の数が増えるほど厳密(型チェックが入るかどうか)と覚える。バッククォートでくくると実行演算子と呼ばれシェルコマンドの実行ができるらしいが、覚えておかなくて良さそう?どうなんだろう?加算子/減算子は使える。 文字列結合は .、配列結合は +
  • 制御構文: if について気にすべきところは else ifelseif 共に可ということ。ブラケットではなくコロンを使った記法も可能でその場合は elseif のみ。コロンの時は endif を書く。whileforforeachswitch もコロンによる記法に関して同様だが、switch はブロック <?php ... ?> を分割した時に case のインデントでエラーが出ることがある。また、switch== での比較を行う。break は制御構文の終了、continue はその回のループを終了。declare はディレクティブの宣言で、タイプヒントの厳密型チェックとか有効にできる。
    • ファイル読み込みに関して、 requireinclude と違ってエラーを投げる。_once つけると読み済みのファイルは読み込まない。
  • class: class ClassName { ... } で定義。__construct でコンストラクタ。 プロパティ、メソッド共にアクセス制御修飾子(public, protected, private)をサポートしているし、省略はできない(var では書けるけどその意味はあまりなさそう)。new ClassName()インスタンス化。フィールドへのアクセスは ->static で静的なメソッドを宣言でき、アクセスは ClassName::メソッド名 のように書く。静的なプロパティはconst で定義できる。 クラス内での静的フィールドは self から、非静的フィールドは this からアクセス。クラスパスを解決させることができる、オートロードという仕組みもあるらしい。繼承は extends でできるのは単一繼承。メソッドのオーバーライド可能、parent::メソッド名 で呼び出し。抽象メソッド abstruct、インターフェース interface もある。トレイトは静的、非静的メソッドもプロパティも持てる、宣言は traitトレイト名 で、使用する際は use トレイト名。無名クラスも使える。オーバーロード が他の言語と異なる意味で使われているので注意。オブジェクトはフィールドに対して反復処理 foreach ($obj as $k => $v) が書ける。
  • 名前空間: namespace 名前空間名 で宣言。
  • 例外: try, catch, finnaly で対応。catch (ExceptionA | ExceptionB e) のように複数例外をキャッチできる。

デバッグ

ちょっとまだわかっていないです。var_dump 引数の中身を見せてくれます。配列とかはエコーしても Array だけなので必要だと思います。詳細度は落ちますが print_r もなかなかいいみたいです。

$arr = [
  'hoge',
  'fuga',
  [
    'hoge',
    'fuga'
  ]
];

という配列に対してそれぞれの関数を適応して見ます。

print_r

Array
(
    [0] => hoge
    [1] => fuga
    [2] => Array
        (
            [0] => hoge
            [1] => fuga
        )

)

var_dump

array(3) {
  [0]=>
  string(4) "hoge"
  [1]=>
  string(4) "fuga"
  [2]=>
  array(2) {
    [0]=>
    string(4) "hoge"
    [1]=>
    string(4) "fuga"
  }
}

print_r の方が人間的には読みやすそうですね。(読みやすさが大切かどうかは時と場合によりますが)

ファイルの取り扱い

php でコードを書くときは、とりあえず <?php とファイルの先頭に書き、拡張子を .php にすれば良さそうです。 <?php の閉じタグに関しては書くと予期せぬ挙動が起こることがあるため省略するのが流儀のようです。

ファイルの読み込みは include, include_once, require, require_once で行うことができます。 dirname(__FILE__)スクリプトファイルのディレクトリを参照してくれているため、つなげて相対パスrequire_once(dirname(__FILE__).'/hoge/fuga/piyo.php') のように書くことができるようです。現在位置を明示しないまま ../hoge などのパスを書いた場合、そのファイル自体が別の場所から読み込まれた際にパスがずれてしまうためしっかり書いたほうが良さそうです。

これらの理解も若干微妙ですが、それはさておき php のパッケージ管理システム Composer を使うとオートロードと呼ばれる、ファイルの自動読み込み機能を使うことができるみたいです。

外部パッケージの取り扱い

パッケージの依存性管理ツールに関して。ちょっと前に触ったときは pear を使ったような気がしたのですが、近年は Composer が主流なのでしょうか?確かに上で書いたオートロードなどの機能が魅力的です。パッケージの検索は、https://packagist.org を利用すると良さそうです。

インストールについては Laravel の説明の箇所に書きます。設定ファイルもcomposer.json だし、composer init でパッケージを作成できるみたいで、結構 npm っぽい気がします。パッケージの追加は composer require です、—dev フラグもあり、開発環境のみ依存しているパッケージを管理することができます。

Laravel

ここでは「インストール」、「フレームワークの構成」、「ツール」、「テスト」、「デファクトなパッケージ」を学んで Laravel でプログラミング始める基礎知識がわかればいいなと思います。

インストール

今のところバージョン 5.6 が最新のようなのでそれをインストールします。日本語版ドキュメントを参照しつつインストールをして行きます。 (若干英語版と日本語版のサイトのトップページが違ったり?)

Composer

Laravel はライブラリ管理ツール Composer を使って入れるようです。とりあえず Composer 入っていなかったのでインストールします。

こちらを参考にインストールします。Laravel のドキュメントではグローバルインストールが推奨のようです。

一応 Homebrew (brew install homebrew/php/composer) でもいけました。(が php の依存性がなくなったため必要なら自分で入れてくださいというメッセージが表示されました、という解釈であっている?)。最近の macphp 入っていると思うので気にしないで大丈夫そうです。(問題あったら是非教えてください)

Laravel インストーラ

$ composer global require "laravel/installer"

laravel コマンドを使用できるように、 .bashrc などにパス追記して、再読み込みします。

$ vim ~/.bashrc
# 以下の内容を追記
export PATH=$HOME/.composer/vendor/bin:$PATH
$ source ~/.bashrc
$ laravel -v
Laravel Installer 2.0.1

無事 Laravel コマンドが入りました。

laravel new apps_name

アプリの雛形を作成してみます。何にするか迷いますが、とりあえず、ユーザーがいてログインとか何かしらの投稿とかがあって、という感じがいいかなと思います。

$ laravel new i_bought_it

結構重いですね、このコマンド、Railsrails new 的な。

中身は以下の感じでした。

$ tree -L 1
.
├── app
├── artisan
├── bootstrap
├── composer.json
├── composer.lock
├── config
├── database
├── package.json
├── phpunit.xml
├── public
├── resources
├── routes
├── server.php
├── storage
├── tests
├── vendor
├── webpack.mix.js
└── yarn.lock

10 directories, 8 files

Node.js 関連のファイルが入っているんですね。この辺りは「フレームワークの構成」あたりで調べて行きます。

ローカルで起動

とりあえず起動してみます。

$ cd i_bought_it
$ php artisan serve

localhost:8000 でサーバーが立ち上がりました!

f:id:ushumpei:20180305235852p:plain

開発環境

2019/01/22 追記 Laradock が楽で良いです。

結論としてはビルトインサーバーと、 sqlite で頑張ることにします。

$ touch database/database.sqlite
$ vim .env
# 以下の内容に変更
DB_CONNECTION=sqlite
DB_DATABASE=database/database.sqlite

以下ざっとみた感じです。

Homestead: 開発環境としては、サーバーとかデータベースとか全部入りの Homestead という選択肢もあるそうです。 ただ Homestead は VagrantVirtualBox (またはその他仮想化ツール) が必要らしいので、若干面倒くさい気分になりました。

Valet: Valet というのも開発環境として選択肢に入るようです。 データベース は別途管理する必要がありますが、 ssl の動作確認も起動オプションだけだし、 Homebrew だけで完結するのが素敵です。ただし Mac オンリーなので Windows での開発に加わる場合ちょっとまごつく可能性もありそうです。

Docker: ノリノリで環境構築してたけど Composer から何から全部 docker でいけたんじゃないかということに気がつきました。例えば: Dockerでlaravelの開発環境構築をしてみた (php-pfm,nginx, mysql)

フレームワークの構成

Laravel の構成について整理してみます。

基本的には「サービスコンテナ #」を中心に考えて行けば良さそうです。サービスコンテナに対して様々なサービスを、「サービスプロバイダ #」によって組み立て、登録していきます。これによってアプリケーションの機能を柔軟に変更、管理していく感じのようです。

ファサード #」はサービスコンテナに登録されているサービスへの API を提供するようです。API の直接の使用のほかにも、「コントラクト #」を使用することでコンストラクタやアクションでタイプヒントを指定しておけばサービスコンテナによって DI される仕組みがあるようです。(コントラクトの登録方法がわかってないですが、、、また、自分の理解ではサービスプロバイダで登録したサービスもタイプヒントによって DI されるのかなと思います)

ORM としては 「Eloquent ORM」 が Laravel に含まれているようですが、使用必須というわけでもないようです。クエリビルダーのようなものであるという話です。ローカルスコープなども定義できるようなので、リポジトリーなどの抽象化がいるかどうかは少し悩みます。論理削除(ソフトデリート)を提供しているようで、論理削除自体の賛否は置いておくとして、実際家な思想に好感が持てます。

ルーティングは Route サービスを(ファサードを通して)使って登録していきます。ルートの登録時、またはコントローラーのコンストラクタで、ミドルウェアを適応することができます。ミドルウェアによってコントローラのアクションに対して認証などの機能を追加することもできるようです。ミドルウェアの登録に関しては App/Http/Kernel.php で記載されています。

(ルーティングに関してリフレクションを使っているのか、URI セグメントから自動的にクエリしてくれる「暗黙の結合 # 」のあたりで、変数名とURIセグメントの一致を要求している部分が面白いです。変数名が意味を持っているのは、気がつかないでハマりそう。)

コントローラーは通常のクラスか、 App/Http/Controllers/Controller.php を継承したクラスです。クラスが依存するサービスは、コントローラーのコンストラクタにおいて引数をタイプヒントで与えておけば、サービスコンテナの仕組みが解決してくれるようです。アクションに対しても同様に DI してくれるようです。(Request などが顕著)

フロントエンドに関しては、 Blade テンプレートエンジン、CSS (SASS、LESS)、Vue が Laravel 5.6 の標準のようです。NPM のエコシステムに乗って webpack によって各種コンパイルを行います。テンプレートの描画は view ヘルパーによってコントローラーから行います。

ツール

artisan が開発において基本的なツールになりそうです。必要そうなものとしては、以下のものかなと思います。

  • artisan list: コマンド一覧
  • artisan route: ルーティング関連、特に route:list
  • artisan make: コードの自動生成系
  • artisan tinker: 対話環境

パッケージに関しては composer を使ってインストールしていくのが無難そうです。 フロントに関しては yarn かと思います。

テスト

テストフレームワークとしては phpunit が初めから入っていました。標準的な Unit, Feature の他に Browser テストが行えるようで (Laravel Dusk)、 Selenium のインストールなしにブラウザ自動操作とテストができるようです。保守の場合は重宝しそうです。

ものすごく個人の感想ですが、とりあえず Unit テストは必須で書いていく、Feature はベストエフォートで、Browser は要件次第かなと思いました。

デファクトなパッケージ

色々探そうと思っていたのですが、 Laravel って標準で色々な機能が入っているようです。認証とかページネーションとか。パッケージ自体は github にたくさん上がっているようです。どこで探すのが正解かわかってないですが、ググると以下のサイトで検索できそうです。

感想

印象としてはフレームワークとしての自由度が、構造を容易に変えられるという意味で、めちゃくちゃ高いなと思いました。でも頑張ればしっかり管理できそうな感じです。バージョン間での差異が少し気になるところですが、逆にそれも自由度が高いが故の変更なのかと思います。どちらかといえばフレームワークの使い方を学ぶよりは、サービスコンテナ自体をしっかりコードを追うなり勉強しておけば、バージョン間の差異についていけるような気がします。