JavaScriptではじめるプログラミング入門

JavaScriptではじめるプログラミング入門

とある場所で、プログラミング初心者向けのハンズオンセミナーを開催しました。初心者に教えるというのは、やはり難しい。今回は知識レベルもまちまちで、人によってはHTMLも知らなかったので、スライドには無いけどHTML基礎講座をやったりしました。

また、受講者の方にはあらかじめChromeのインストールをお願いしたのですが、PCにインストールされているソフトウェアの影響で、こちらの想定した動作とは異なる動作をするPCがあったりして、なかなかに悩ましい。

環境構築が簡単なJavaScriptでさえこれなのだから、他の言語は推して知るべし、ですね。

内容としては、結構詳細に(ある程度本気でプログラミングを覚えたい人向けに)説明してしまったのですが、もっとプログラミングの楽しさをダイジェスト的に感じられるような課題だと良かったかな、と思いました。

ちなみに、今回はreveal.jsでスライドを作成し、GitHub Pagesにアップロードして公開しました。reveal.jsは簡単にスライドが作れるし、GitHubにgh-pagesブランチを切ってpushすればGitHub Pagesとして公開できるので、とても楽。この組み合わせは今後も使っていきたいですね。

Phalconドキュメントの日本語翻訳チームにJOINしました

ここしばらくの間、「Phalconまとめ」シリーズで、Phalconのドキュメントを自分なりに翻訳する試みをやってきました。結果、難易度・作業量の面でいけそうだという感触を得ることができたので、Phalconドキュメントの日本語翻訳チームにJOINしました(Transifexでのアカウント名はryo511です)。

Phalconのドキュメントの翻訳は、以前はGitHubで進められていましたが、現在はTransifexという翻訳サービスに移行しています。

If you want to translate English documentation into your native language, please request join a translation team
at Transifex.

https://github.com/phalcon/docs/blob/master/CONTRIBUTING.md

翻訳チームへの参加方法は以下のとおり。
(1) Transifexにアカウントを作成する
(2) Phalconドキュメントのプロジェクトに参加申請をする
(3) 参加申請が受諾されたら、翻訳作業を開始できる

今後はPhalconドキュメントの翻訳作業はTransifexで行うことになるため、このブログにはドキュメントの翻訳は掲載しなくなると思います。

Phalcon Model まとめ(5) ビヘイビア

「最速」PHPフレームワークPhalconのモデルについて、基本事項をまとめます(公式ドキュメントの翻訳+αです)。記事執筆時のPhalconのバージョンは1.3.1です。

ビヘイビア

ビヘイビアとは、複数のモデルに共有される振る舞いのことです。PhalconのORマッパーは、モデルでビヘイビアを実装するためのAPIを提供しています。また、イベントとコールバックを使用して、より自由度の高いビヘイビアを実装することもできます。

ビヘイビアは、モデルの初期化処理に加えなければなりません。モデルは複数のビヘイビアをもつことができます。

フレームワークは、以下の組み込みビヘイビアを提供しています。

名前 説明
Timestampable レコードが作成・更新される際に、自動的にモデルのフィールドを更新する
SoftDelete 永続的な削除(物理削除)の代わりに、削除フラグを付与する(論理削除)

Timestampable

このビヘイビアは、配列をオプションとして受け取ります。最初のキーが、カラムへの代入が行われるイベント名になります。

それぞれのイベントには独自のオプションがあり、fieldは更新されるカラム名になります。formatが文字列なら、PHPのdate()関数の引数として渡されます。formatには無名関数を使うこともでき、お好みの形式でタイムスタンプを作ることができます。

formatがオプションの配列に含まれない場合は、タイムスタンプはPHPのtime()関数を使用し、タイムスタンプの数値が代入されます。

SoftDelete

このビヘイビアは、以下のように使います。

このビヘイビアは、2つのオプションを受け取ります。fieldは更新されるフィールド名を、valueは削除フラグの値を指定します。以下のようなデータをもつusersテーブルについて考えてみます。

もし、いずれかのレコードを削除したら、レコードが削除される代わりに、statusが更新されます。

上記コードが実行されると、テーブルの中のデータは以下のようになります。

削除済みか否かのフラグをクエリで明示的に指定してやる必要がある点に注意してください。テーブルが上の状態の時、以下のコードを実行すると、削除されたはずのBrandonも取得されてしまいます。

論理削除済みのレコードを除外するには、以下のようにします。

独自のビヘイビアを作る

ORマッパーは、独自のビヘイビアのためのAPIを提供しています。ビヘイビアは、Phalcon\Mvc\Model\BehaviorInterfaceを実装したクラスでなければなりません。また、Phacon\Mvc\Model\Behaviorが、ビヘイビアの実装に必要なほとんどのメソッドを提供しています。

以下のビヘイビアは、1つの実装例です。Blamableビヘイビアは、ユーザーがモデルに行った操作を特定します。

次に、このビヘイビアをモデルに追加してみます。

ビヘイビアは、不明なメソッド呼び出しに対して割り込みができます。

Sluggableを実装しているモデルにgetSlug()メソッドの呼び出しを行うと、SEO対策のされたtitleが返ります。

トレイトをビヘイビアとして使う

PHP5.4以降では、トレイトを使うことでクラスのコードの再利用ができます。この機能を使って、独自のビヘイビアを実装することもできます。以下のトレイトは、TimeStampableビヘイビアのシンプルな実装例です。

モデルでは、以下のようにして利用します。

今回はここまで

今回は、Phalconのモデルで利用可能なビヘイビアについて紹介しました。次回は、Transactionsから先をみていきます。

Phalconモデルまとめ(4) バリデーションとイベント

「最速」PHPフレームワークPhalconのモデルについて、基本事項をまとめます(公式ドキュメントの翻訳+αです)。記事執筆時のPhalconのバージョンは1.3.1です。

バリデーションメッセージ

Phalcon\Mvc\Modelには、INSERT/UPDATE時のバリデーションメッセージの保持・出力を柔軟に行えるサブシステムがあります。

それぞれのメッセージは、Phalcon\Mvc\Model\Messageクラスのインスタンスになります。生成されたメッセージの集合は、getMessages()メソッドで取得することができます。それぞれのメッセージは、フィールド名やメッセージの種類のような、幅広い情報を提供します。

Phalcon\Mvc\Modelが生成可能なメッセージの一覧は以下です。

種類 説明
PresenceOf フィールドにNOT NULL制約が付与されているときに、null値をINSERT/UPDATEしようとした際に発生
ConstrainvViolation 仮想外部キー制約を設定しているフィールドに、参照しているモデルに存在しない値をINSERT/UPDATEしようとした際に発生
InvalidValue 無効な値によってバリデーションが失敗した際に発生
InvalidCreateAttempt 既に存在するレコードを新規作成しようとした際に発生
InvalidUpdateAttempt 更新しようとしたレコードがまだ存在しない際に発生

getMessages()メソッドをオーバーライドすることで、モデルが自動で生成するメッセージを置き換えることができます。

イベントとイベントマネージャ

モデルには、INSERT/UPDATE/DELETE時に実行されるイベントを実装することができるようになっています。これらは、モデルのビジネスルールを定義する助けになります。Phalcon\Mvc\Modelがサポートしているイベントの一覧は以下です(実行順)。

処理 イベント名 処理の中断可否 説明
INSERT/UPDATE beforeValidation フィールドのNOT NULL・空文字列・外部キー制約のバリデーション前に実行される
INSERT beforeValidationOnCreate INSERTの場合で、フィールドのNOT NULL・空文字列・外部キー制約のバリデーション前に実行される
UPDATE beforeValidationOnUpdate UPDATEの場合で、フィールドのNOT NULL・空文字列・外部キー制約のバリデーション前に実行される
INSERT/UPDATE onValidationFails ○(既に停止済み) バリデーションが失敗した際に実行される
INSERT afterValidationOnCreate INSERTの場合で、フィールドのバリデーション後に実行される
UPDATE afterValidationOnUpdate UPDATEの場合で、フィールドのバリデーション後に実行される
INSERT/UPDATE afterValidation フィールドのバリデーション後に実行される
INSERT/UPDATE beforeSave INSERT又はUPDATEの実行前に実行される
UPDATE beforeUpdate UPDATEの実行前に実行される
INSERT beforeCreate INSERTの実行前に実行される
UPDATE afterUpdate × UPDATEの実行後に実行される
INSERT afterCreate × INSERTの実行後に実行される
INSERT/UPDATE afterSave × INSERT/UPDATEの実行後に実行される

モデルのクラスにイベントを実装する

モデルをイベントに対応させるための最も簡単な方法は、イベント名と同じ名前のメソッドをモデルのクラスに実装することです。

イベントは、処理の実行前に値を代入するのに便利です。

イベントマネージャのカスタマイズ

モデルのイベントコンポーネントは、Phalcon\Events\Managerと統合されています。そのため、イベントが実行される際のリスナーを作ることもできます。

上記サンプルコードでは、イベントマネージャはオブジェクトとリスナーの橋渡しを行います。イベントは、Robotsモデルのsave時に発火します。

全てのオブジェクトに共通のEventsManagerを実装したい場合、EventsManagerをModelsManagerに登録します。

リスナーがfalseを返すと、その処理の実行は中断されます。

ビジネスルールを実装する

INSERT/UPDATE/DELETEの実行時に、モデルはイベント一覧に挙げられた名前のメソッドが無いか確認します。

以下のコード例では、INSERT/UPDATE時のイベントを実装し、yearの値が0未満でないかバリデーションしています。

イベントがfalseを返すと、処理は中断されます。イベントが何も返さない場合、Phalcon\Mvc\Modelはtrueが返されたとみなします。

データの完全性バリデーション

Phalcon\Mvc\Modelは、データをバリデーションし、ビジネスルールを実装するためのイベントを提供しています。「validation」イベントによって、組み込みのバリデーターを呼び出すことができます。Phalconは、いくつかの組み込みバリデーターを提供しています。

上記コード例では、組み込みの「InclusionIn」バリデーターを使用しています。このバリデーターは、「type」フィールドの値がdomainのリストに含まれているかチェックしています。値が含まれていなかった場合は、バリデーションに失敗し、バリデーターはfalseを返します。

組み込みのバリデーターの一覧は以下です。

名前 説明 実装例
PresenceOf フィールドの値がnullではなく、空文字列でもないことをバリデーションする。NOT NULL制約が設定されているフィールドに対しては、このバリデーターが自動的に追加される。
Email フィールドの値が有効なEメールアドレスであるかバリデーションする
ExclusionIn フィールドの値が禁止リストに含まれないことをバリデーションする
InclusionIn フィールドの値が許可リストに含まれることをバリデーションする
Numericality フィールドの値が数値形式かバリデーションする
Regex フィールドの値が正規表現にマッチするかバリデーションする
Uniqueness フィールドの値が既存のレコードと重複しないかバリデーションする
StringLength 文字列の長さをバリデーションする
Url フィールドの値が有効なURLの形式化バリデーションする

組み込みのバリデーターに加えて、独自のバリデーターを作成することもできます。

バリデーターをモデルに追加するには、以下のようにします。

バリデーターを作成することで、バリデーションのロジックを複数のモデルで使い回すことができます。1箇所でしか使わないバリデーションであれば、以下のようにシンプルに実装することもできます。

SQLインジェクションを避ける

モデルのプロパティに代入された値は全て、そのデータ型に応じたエスケープが施されます。開発者が、DBに入れる値のエスケープを実装する必要はありません。Phalconは内部でPDOのバインド機構を使用して、自動エスケープを行っています。

上記テーブルへのINSERTをする際、PDOを使用すると、以下のようなコードになります。

Phalconのモデルを使用すると、以下のように書けます(エスケープは全て自動で行われます)。

カラムをスキップする

何らかのトリガーや、デフォルト値の代入を行いたいため、バリデーションを行いたくない場合があります。モデルによるバリデーションを行わないようにするには、以下のように書きます。

これによって、アプリケーション全体で、INSERT/UPDATE時のバリデーションが実行されなくなります。デフォルト値の代入は以下のように行えます。

イベントのコールバックによって、特定条件の場合にデフォルト値を設定することもできます。

注意:Phalcon\Db\RawValueは、ユーザー入力のような外部データや変数の値の代入に使用してはいけません。RawValueにはバインド機構が使用されないため、SQLインジェクション脆弱性を引き起こす危険性があります。

ダイナミックアップデート

SQLのUPDATE文は、デフォルトでは全てのカラムをUPDATEするように作成されます。ダイナミックアップデートを有効化すると、変更されたフィールドだけが更新されるUPDATE文が生成されます。

これによって、アプリケーションサーバ・DBサーバ間のトラフィックが減少し、パフォーマンスが改善されることがあります。特に、BLOB/TEXT型のような大きなデータを取り扱うカラムがある場合、ダイナミックアップデートは大きな助けになります。

レコードの削除

Phalcon\Mvc\Model::delete()メソッドに寄って、レコードを削除できます。

結果セットをforeachでまわすことで、複数のレコードを削除できます。

以下のイベントを使用することで、削除処理の際に実行されるビジネスルールを定義することができます。

処理 名前 処理の中断可否 説明
DELETE beforeDelete 削除処理の実行前に実行
DELETE afterDelete × 削除処理の実行後に実行

上記イベントを使用すると、以下のようにビジネス・ルールを定義できます。

バリデーション失敗時のイベント

バリデーション失敗時のイベントもあります。

処理 名前 説明
INSERT/UPDATE notSave INSERT/UPDATEが何からの理由で失敗した際に発生
INSERT/UPDATE/DELETE onValidationFails データ処理が失敗した際に発生

今回はここまで

ここまで、Phalconのモデルを利用したバリデーションの実装方法をみてきました。次回は、Behaviorsから先をみていきます。

Phalconモデルまとめ(3) 計量・ハイドレーションモード・新規作成と更新

「最速」PHPフレームワークPhalconのモデルについて、基本事項をまとめます(公式ドキュメントの翻訳+αです)。記事執筆時のPhalconのバージョンは1.3.1です。

モデルの計量

計量(集約)はデータベースの操作を助ける機能で、COUNT/SUM/MAX/MIN/AVGなどがあります。Phalcon\Mvc\Modelでもこれらの機能を利用できます。

COUNTの例:

SUMの例:

AVERAGEの例:

MAX/MINの例:

ハイドレーションモード

Phalconのモデルの結果セットは、全てがオブジェクトです。DBの各行が単一のオブジェクトになっています。これらのオブジェクトに変更を加え、保存して永続化することができます。

結果セットの形式を変更するモードのことを、「ハイドレーションモード」といいます。

ハイドレーションモードは、find()のパラメーターとして渡すこともできます。

レコードの作成・更新

Phalcon\Mvc\Model::save() メソッドによって、レコードの作成・更新ができます。save()メソッドは内部でPhalcon\Mvc\Modelのcreate()又はupdate()を呼びます。いずれのメソッドを呼ぶかは、エンティティの主キーが定義済みか否かによって決まります。

また、このメソッドは、同時にバリデーションも実行します。

全てのカラムに手動で代入する代わりに、save()に配列を渡すことができます。Phalcon\Mvc\Model は各カラムに定義済みのsetterが無いか確認します。

確実に作成・更新する

アプリケーションが同時に多くの利用者に利用されている時、レコードを新規作成すると予想していたのに実際には更新がされてしまうことがあります。Phalcon\Mvc\Model::save()を使用してDBへの永続化を行うと、このような現象が発生する可能性があります。もし、絶対にレコードが新規作成又は更新されるようにしたい場合、save()の代わりにcreate()又はupdate()を呼びます。

これらのメソッドには、save()と同様、配列をパラメータとして渡すことができます。

自動採番されるid

モデルがidを示すカラムをもつことがあります。これらのカラムはふつう、テーブルの主キーとして使用されます。Phalcon\Mvc\Modelはidのカラムを認識することができます。そのため、Phalcon\Mvc\Modelが生成するSQLのINSERT文には、idが含まれません(DBMSが自動採番できるようにするため)。レコードを新規作成した際には、DBMSによって採番されたidがモデルに登録されます。

Phalcon\Mvc\Modelはidのカラムを認識することができます。DBMSの種類によりますが、PostgreSQLのようなSERIAL型のカラムであることもあれば、MySQLのようにauto_incrementが設定されたカラムである場合もあります。

関連テーブルの一括保存

マジックプロパティによって、あるレコードとその関連するプロパティを一度に保存することができます。

保存するレコードと、その関連レコードには、has-manyの関係があります。

アルバムとアーティストを同時に保存すると、暗黙的にトランザクションが使用されます。そのため、何らかの原因で関連レコードの保存に失敗した場合、親となるレコードも保存されません(内部的にエラーが発生します)。

注意点:以下のメソッドのオーバーロードによって関連するエンティティを追加しても、効果はありません。

  • Phalcon\Mvc\Model::beforeSave()
  • Phalcon\Mvc\Model::beforeCreate()
  • Phalcon\Mvc\Model::beforeUpdate()

もし、保存時の挙動を変更したいなら、Phalcon\Mvc\Model::save()をオーバーロード(※)する必要があります。

※:原文では「You need to overload PhalconMvcModel::save()」なのでそのまま訳しました。overrideの間違い?

今回はここまで

次回は、Validation Messagesから先、Phalconのモデルによるバリデーションの方法を紹介します。