要件の確認について

手戻りを最小限にするために重要

はっきりとわからないことがあるときはそれが明確になるまで別の言い方で質問して確認するようにする。自分の理解を自分の言葉で伝えて間違いを指摘してもらえるようにする。当然ながら自分がどういう風に理解しているかは相手はわからない。

 分かっているつもりでも質問する

はっきり分かっているつもりでも質問する。分かっているつもりで分かっていないことがよくあるから。自分が何も分かっていないことを前提にする。

 知ったかぶり

無意識のうちに知ったかぶりをしている場合もある。していないつもりでも。

また、相手も前提としている知識を共有していると思い込んでいる場合がある。当たり前のように話している中に少しでも引っかかるところがあれば積極的に質問して教えてもらうようにすべき。

デバッグについて

ブラウザ

var_dump();die();

  • viewを返す場合。
  • ()内の値を確認できる
  • dd()でも可。
  • laravelというよりもphp

{{var_dump()}} {{die()}}

  • blade内の値を確認する場合

die('ok');

  • プログラムがどこまで進んでいるかを確認することができる。

    • エラーが出ずにokが出力されれば、エラーの出る場所を特定しやすくなり、問題の切り分けがしやすくなる。

chrome 検証ツール

  • option + command + i
  • どんな通信が走っているか確認できる。
  • Network→XHRでapi一覧表示
  • あるいはelementsでonclickイベントの対象となるid等を取得して走るapiを追うこともできる。
  • Preserve log にチェックを入れるとすぐにリダイレクトされるviewのapiも消えずに残るので確認がしやすい
  • 逆にチェックを入れておけば、apiの叩かれるタイミングがわかりやすくなる。
  • clearで溜まったlogを削除することができる
  • Nameにカーソル合わせてURL確認
  • 選択して詳細表示
  • Previewでレスポンス値確認
  • Responseでjsonが返る場合JSONきれい ~JSON整形ツール~で整形できる
    • apiでvar_dumpの値を直接表示することができない場合でもこのpreviewから確認することができる。
    • 500エラーなどの場合は何も表示されない。

Restlet Client - REST API Testing

  • apiの通信を確認する

  • response

    • previewからvar_dumpを確認することもできる

Laravel Debugbar

下記のそれぞれは右側のフォルダのアイコンからリクエストごとに確認することができる。 - messages - \Debugbar::info(); - info()の引数に変数などを入れて値を確認することができる。 - 役割的にはvar_dump();と同じ。 - exceptions - エラーメッセージが表示される。 - Queries - 走ったクエリが確認できる。 - クエリはSequel Pro で実行し値の確認ができる

Logging

/storage/logsに出力する

これでもブラウザを介さず値の確認ができる。 出力の方法

use Illuminate\Support\Facades\Log;
Log::info('ok');

もしくは

logger('ok');

結果は同じ

[2019-02-18 23:30:51] local.DEBUG: ok

use Illuminate\Support\Facades\Log; が必要ない分logger();の方が楽かもしれない。

/storage/logs以下の出力の粒度についてはconfig/app.phpで設定できる。

'log' => 'daily'

gitまとめ

参考:git--local-branching-on-the-cheap

  • gitとは?

    • ソースコードのバージョン管理のためのソフトウェア。
    • コマンドでソースコードの状態を以前の状態に戻したり、同じソースコードを異なるバージョンとして管理することができる。
    • リモートレポジトリへgit管理下のソースコードをpushすることでそれを他の人と共有することもできる。
  • リモートレポジトリとは?

    • クラウド上にあるソースコードを管理するための領域
    • ローカルのgitと同期して管理することができる。
    • ソースコードがおいてあるのでローカルの状態と関係なくpullすればそのソースコードをローカルで再現することができる。この仕組みを利用してチームでの開発をスムーズに行うことができる。リモートレポジトリを経由してソースコードの改変を他者と共有することができる。また、gitのブランチ機能を利用して開発を並行して行うこともできる。
  • pullとは?

    • pullとはoriginからソースコードを引っ張ってきてローカルレポジトリのソースコードと差異がある場合にその差分をローカルレポジトリに反映させること。
    • pullはローカルリポジトリのワーキングツリーやステージにファイルのある状態では実行することができない。
    • gitにはワーキングツリー・インデックス・HEADの三つの領域がある。
    • git pull origin ブランチ名
  • ワーキングツリーとは?

    • 人間が直接触って編集することのできる領域。
    • ここでファイルを編集して動きを確認することができる。
    • gitではファイルの集まりのことをツリーと表現する。ツリーとはデータの構造のことではない。
  • ステージとは?

    • HEADに移行する前段階のこと。
    • インデックスとも呼ばれる。
    • git add
    • addされるとインデックスの状態が変化する。
  • HEADとは?

    • HEADとは最新のコミット状態を指し示すポインタのようなものである。
    • ステージからgit commit することでHEADを変更することができる。
    • HEADのソースコードはpushすることでリモートレポジトリに反映させることができる。
  • スタッシュとは

    • 前述ようにステージやワーキングツリーにファイルがあるとgit pullすることができない。
    • git checkout して他のブランチでの作業を行うと現在のワーキングツリーの情報が失われてしまう。
    • 作業途中の状態でcommitしたくない。
    • 上記のような時にスタッシュを行うことで作業中のファイルやステージのファイルを隠して取っておくことができる。
  • ブランチとは?

    • git管理下の領域のファイルに並行して別の変化を加え、そのバージョン管理を行うための仕組み。
    • 異なるブランチ同士は同じ名前でもとは同じ一つのファイルであっても、別のファイルであるかのように扱うことができる。
    • リモートリポジトリでもそれぞれ対応するブランチを作成し、それぞれが同期するように扱うことができる。
    • 枝分かれさせて開発しているブランチはそのブランチでの開発が完了した時に別のブランチにマージして、終了することができる。
    • pushやpullもブランチ単位で行う。
    • pullした時にコンフリクトが起こることがある。
  • コンフリクトとは?

    • pullしたリモートのブランチのHEADがローカルのHEADの同一箇所で異なる状態であること。
  • pushとは?

    • ワーキングツリーのソースコードはまずaddすることでステージに移行できる。
    • ステージにあるファイルはcommitすることでローカルレポジトリに移行することができる。
    • commitされローカルリポジトリに移行したファイルはその時点の状態がgitのバージョン管理の対象となる。
  • gitのバージョン管理とは?

    • 最新のバージョンのことをHEADと呼ぶ。
    • HEAD以前のバージョンにはハッシュ値が付与されている。
    • git resetやrevertで過去の状態に戻すことができる。
  • resetとは?

    • git reset soft

      • HEADの位置を指定の位置まで戻す。
    • git rese mixed

      • HEADの位置とステージの状態を指定の位置まで戻す。
    • git reset hard

      • HEADの位置とステージの状態とワーキングツリーの状態(変更)を指定の位置まで戻す。
      • hardを使う時には注意が必要。
      • 他のオプションと異なり、ワーキングツリーの状態まで変化するためやり直しがきかない。
    • resetの対象のファイルの指定

      • ファイルを指定する場合にはHEADの位置の変更はできない。(reset hardはできない)
      • インデックスのファイルをHEADの状態に戻したりすることができる。
    • 戻る位置の指定方法

      • 最新のコミット

        • HEAD
        • 現在のHEADの位置
      • 一つ前のHEADの位置

        • HEAD^
        • HEAD~
      • 二つ以上前のHEADの位置

        • HEAD^^
        • HEAD~~
        • HEAD~2

Doctrine\DBAL\DBALException : Unknown database type enum requested.

概要

Doctrine\DBALを インストールしてカラムに変更を加えるマイグレーションを実行しようとすると発生するエラーとその回避の方法についてです。

参考

エラーの内容

migrationでテーブルに変更を加えるときには Doctrine\DBAL をインストールする必要がある。

enum型のあるテーブルでカラムの変更を加えようとすると下記のエラーがでる。

Doctrine\DBAL\DBALException  : Unknown database type enum requested, Doctrine\DBAL\Platforms\MySqlPlatform may not support it.

Doctrine\DBALがenumをサポートしてないから。

Note: Renaming columns in a table with a enum column is not currently supported.

このエラーは変更を加えようとしているカラムがenumでなくても同じテーブルにenum型があれば発生する。

回避の方法

Doctrine\DBALがenumに引っかからないようにすれば解決するようだ。

対象のマイグレーションファイルに初期化のメソッドを追加してDoctrine\DBALがenumをstringにマップするようにする。

public function __construct()
{
    DB::getDoctrineSchemaManager()->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string');
}

これでenum型を持ったままカラム変更のマイグレーションが成功した。

Laravel Migration(カラム属性変更)

概要

Laravelでカラムに属性を変更したい時のマイグレーション

参考

Laravel 5.6 データベース:マイグレーション

ファイル生成コマンド

$ php artisan make:migration ファイル名(create_users_table) オプション(--create=users)
  • オプション
    • 生成するテーブル名を宣言(--create)。
    • 変更を加えるテーブルを宣言(--table)。
    • ファイルのパスを指定(--path)。

ファイルの構造

upとdownの二種類のメソッドがある。

  • up
    • 新しいテーブル、カラム、インデックスをdbに追加するために使用する(カラム属性の変更もupメソッド)。
  • down
    • upが行った操作を元に戻す。

実行

$ php artisan migrate

カラム変更

laravelはデフォルトではカラムの変更を行うことができない。composerでdoctrine/dbalを追加する必要がある。

$ composer require doctrine/dbal

無いと下のエラーが出る。上のコマンドはappのホームディレクトリで実行する。

[RuntimeException]                                                                   
  Changing columns for table "books" requires Doctrine DBAL; install "doctrine/dbal".  

カラムの属性変更

$ php artisan make:migration change_books_table --table books
<?php

public function up()
{
    Schema::table('books', function (Blueprint $table) {
        $table->datetime('published')->change();
    });
}

確認

mysql> desc books;

パーフェクトPHPで学習中(chapter5)

参考

パーフェクトPHP

chapter5

クラス

継承

PHPでは継承は下記のように行う。

class クラス名 extends 親クラス名{
}

また多重継承は許されておらず、一つのクラスしか継承することができない。

オーバーライド

親クラスで定義されたプロパティやメソッドを子クラスで同じ名前で定義すると子クラスでそれを上書きすることができる。これをオーバーライドと呼ぶ。オーバーライドしたメソッドは親クラスと異なる数の引数を持ってはいけない。ただし、デフォルト値をもつ引数を追加することは許されている。また、コンストラクタも例外的に異なる引数を持つことができる。

parentキーワード

クラスコンテキストの中ではparentは親クラスを意味するキーワードになる。 使い方はselfと同じ。 キーワードは変数ではないので$thisのように$はつけない。 下記のようにすると親のメソッドを呼び出すことができる。 これによって子クラスで重複する定義をなくすことができる。

parent::メソッド(引数)

インスタンスの生成

phpではnew演算子を使ってオブジェクトをインスタンス化する。 それを変数に代入するとオブジェクトへの参照が変数に渡されるようになる。 オブジェクトにラベルが貼られるようなイメージ。 なので下記のようにすると同じ一つのインスタンスを二つの変数が参照するようになる。

$test = new Test();
$test1 = $test;

もしも別のインスタンスを複製したい場合は下記のようにする。 これでインスタンスが二つ作られてそれぞれが別の変数に参照されるようになる。

$test1 = clone $test;

phpではメソッドの呼び出しに->(アロー演算子)が使われる。

アクセス修飾子

オブジェクトのアクセス修飾子とはメソッドやプロパティがどこからアクセス可能かを定義するのに使用する。3つのアクセス修飾子がある。

  • public
    • どこからでも参照・呼び出しが可能。
  • private
    • クラス内でのみ参照・呼び出しが可能。
  • protected
    • クラス内とそのクラスを継承したクラス内でのみ参照・呼び出しが可能。

protectedを宣言すると継承した先でプロパティやメソッドを使い回すことができる。

this

オブジェクトがインスタンス化されると$thisという変数が自動的に定義される。 $thisは自分自身のオブジェクトへの参照である。 オブジェクトは自分自身のプロパティやメソッドへは$thisを経由してアクセスするようになる。

staticプロパティ

staticプロパティはクラスの持っているプロパティ。 クラス定義の際下記のように定義する。 これで初期値'static property'の設定も行われている。

private static $property = 'static property'

staticメソッド

staticメソッドはクラスメソッドのようなもの。 インスタンスに対しては使えない。 クラス定義の際下記のように定義する。

<?php
public static function getStaticProperty(){
  return self::$staticProperty;
}

selfキーワードはクラスコンテキストの内部でクラス自体にアクセスする時に利用する。 self::で自分のクラス自体にアクセスすることができるようになる。 selfは変数ではなくキーワードなのでそれ自体に$をつけず::の後のプロパティには$をつける。

名前空間

概要

名前空間とはクラスや関数の使える名前の集合を限定することで名前の衝突を防ぎ、意味を明瞭にするための機能。 名前空間ディレクトリシステムに似ている。

定義

名前空間の区切りには\を使う。 同じ名前空間の中では名前空間の指定を省略することができる。 別の別の名前空間から他の名前空間のクラスや関数を呼び出すときは常に完全修飾名(絶対パスのようなもの)を指定しないといけない。 同じ理由から名前空間を定義しグローバルなクラスや関数を用いる際にはその頭に\をつけないといけない。 グローバルな空間にいる場合は装飾名(相対パスのようなもの)からの呼び出しが可能。

namespace 名前空間\サブ名前空間;

上記のように宣言する。 名前空間の宣言よりも前に出力や文が存在してはいけない。 名前空間の影響を受けるのは下記の3種類。

  • クラス
  • 関数
  • 定数(constで定義したもの。define()では影響を受けない。)

一つのファイルに複数の名前空間を作る時は下記のように宣言する。

<?php

namespace Project\Module {
  class Directory{}
}

namespace Project\Module2 {
  class Directory{}
}

この場合、namespaceのブロックの外に文や出力があってはいけない。 一つのときと同じようにnamespaceの外に文や出力があってはいけない。

インポート

useを使って別の名前空間のクラスをインポートすることができるが関数や定数を使うことはできない。

<?php
use \クラス名;
use 名前空間;
use 名前空間 as 別名;
use 名前空間\クラス名;

asを使った場合別名でインポートすることができる。 使わなかった場合は最後の被修飾名でインポートされる。

<?php
use Foo\Bar\Baz;
$baz = new Baz();

パーフェクトPHPで学習中(chapter4)

参考

パーフェクトPHP

chapter4

制御構造

制御構造はプログラムの実行の流れを制御する役割をもつ構文のこと。 繰り返しや条件分岐のこと。

文(statement)とグループ文

phpスクリプトは一連の文の集まり。 文は;で終了する。 複数の文を{}で囲むことによってグループ化しグループ文(ブロック文)を作ることができる。 文をグループ化することでグループ文は一つの文として扱われる。 制御構造・括弧・文からなるphpスクリプトで文が実行される箇所はグループ文に置き換え可能。 また、制御構造自体も一つの文とみなされている。制御構造である文に対して制御構造を用いることも可能。つまり例えばif文をネストしたりすることができるということ。

式(expression)

phpにおける式は値を持つ全てのもののこと。評価されうる全てのものと言い換えることもできる。rubyでの式は返り値を持つ全てのものだった。またphpでは式と文は異なる。正解にいうと式は文の一部で文の全てが式ではない。例えば下記は文だけど評価はできないので式ではない。なので制御構文の条件式などには適応できない。

 echo $test;

これに対して下記は式であり文でもある。

$var = 1;

上記の文には三つの式が含まれている。=は右辺の式の返り値を(評価して)左辺に代入する演算子である。=の値は右辺の値になる。この場合=の値は1。

($var = 1);

そして上記のように複数の式を()で囲むと一つの式とみなされ最後に評価された値が()内全体の値とみなされるようになる。 なのでこの式の値は1になる。

制御構文に関する別の構文

phpphpブロック内のみをphpスクリプトとして認識し実行するが一つのファイル内であれば、複数のphpブロックをまたぐブロック文を定義することができる。これによって制御構文内に例えばhtmlが入る場合でもブロック文を継続することができるようになる。 このような使い方をする場合は可読性のためブロックの始まりの{を:で表し終わりの}を(例えばif構文であれば)endifと表すことができる。

do-while

<?php
$i = 0;
do {
  echo $i, PHP_EOL;
  $i++;
}while($i < 10);

上記のようにするとwhile構文内の条件式に入る前に一度ブロック文を実行する。その後条件式を評価するので初期値が条件にあったものではない場合にも0周目だけはブロック文が実行されることになる。

for

<?php
for(初期化式; 条件式; 反復式;)

上記のような構文で繰り返しができる。jsのfor文と同じ。下記の順番で処理する。

  1. 初期化式を評価。
  2. 条件式を評価し、trueなら文に入る。falseならfor構文を終了。
  3. 文を実行。
  4. 反復式を評価。
  5. 2に戻る。

評価対象のそれぞれの式は下記のようにカンマで区切って複数の式を指定することもできる。ただし条件式と反復式での複数の式の指定は一般的には行われない。

<?php
$ary = [1, 2, 3, 4, 5];
for($i = 0, $end = count($ary); $i < $end; ++$i){
  echo $ary[$i], PHP_EOL;
}

関数

関数の呼び出し

関数を呼び出すときは基本的に関数名に()をつけて呼び出す。

コールバック関数

PHPでも引数に関数を指定することができ、対象となる関数のことをコールバック関数と呼ぶ。

無名関数

無名関数とは名前をつけて定義する関数ではなく、コールバックの対象にしたり、変数に代入したりするときに使う関数のこと。