最近、ちまちまとPHP を書くことがあって、 ちょっとしたWebアプリ等作るときに
CakePHP などのある程度規模のあるフレームワークを使うまでもないかなって思うことが多々あり、
そういった用途に 小規模向けなフレームワーク (マイクロフレームワーク) PunyApp というのを作りました。
以前から自分だけで使ってて少しずつ更新して温めていたもので、 ある程度形になったので公開しました。
軽量で中小規模向けなもので、 おおまかな設計は CakePHP を参考にしてて、使い方も似てます。
PunyApp は MVC モデルで他のPHP拡張等は必要ありません。
ダウンロード
要件
- PHP 5.2.0 +
- mod_rewrite が有効 (Apache Server)
ライセンス
- MIT
機能/特徴
- MySQL, PostgreSQL, SQLite, Posql に対応
- Controller, Model, Viewアクション
- フォームのValidation
- Viewテンプレート変数はデフォルトでHTMLエスケープされる
- Session (データベース)
- Cookie (デフォルトで暗号化)
- データベースエラー時などのEvent
- サンプルのログインフォームが入ってる
追記
以下の情報はバージョンアップに伴い古くなっているので https://github.com/polygonplanet/PunyApp を参照ください
レイアウト
- ファイル構成
/application → アプリケーションディレクトリ /controllers → コントローラ /models → モデル /views → ビュー /libraries → 共通ライブラリやヘルパー等 /storage → SQLiteなどのファイルベースデータベースやログを保管 /logs → /storage配下を書き込み可にしておく /databases → 同様 /settings → 設定 app-settings.php → アプリケーション設定ファイル app-scheme.php → データベーススキーマ /public → 公開ディレクトリ /css /js index.php /lib → PunyApp内部ライブラリ /vendors → 外部ライブラリ等を入れるディレクトリ index.php
Controllers
コントローラのアクションは、GET や POST などのリクエストメソッドで切り分けができます。class SampleController extends PunyApp_Controller { public $models = array('sample'); /** * GET /login */ public function getLogin($params) { $this->view->render('sample/login'); } /** * POST /login */ public function postLogin($params) { $has = $this->sample->hasUser($params['id'], $params['pass']); if ($has) { $this->session->userid = $params['id']; $this->redirect('home'); } // ... $this->view->render('sample/login'); } /** * Any /login (あらゆるリクエストメソッドに対応) */ public function anyLogin($params) { // ... } /** * Before /login (前処理) */ public function beforeLogin($params) { if (!empty($this->session->userId)) { $this->redirect('home'); } } /** * After /login (後処理) */ public function afterLogin($params) { // ... } /** * GET /home */ public function getHome($params) { // ... } }before や after で前処理などが設定できます。
any は、すべてのリクエストメソッドに対応します。
メソッド名を any だけ
(function any() {})
にすると、404 にならずに any が実行されます。
引数 $params はリクエストパラメータが渡されます。
コントローラのメソッド名の命名規則は、
リクエストメソッド名
+ アクション名
になります。
GET に対応する hoge だったら、
getHoge
になります。
URL は、
http://www.example.com/コントローラ名/アクション名
となります。
アクション名は、リクエストメソッド名を外した名前です。
SampleController で getHoge の場合は、
http://www.example.com/sample/hoge
という感じになります。 ファイル名は sample.php です
AnyController (any.php) という名前にすると、すべてのリクエストに対応します。
Models
モデルは、PDO を使っているのもあり 基本的にプリペアドステートメントを使って実行します (プレースホルダ)。class SampleModel extends PunyApp_Model { public function addUser($userid, $email, $pass) { // Insert $sample = $this->newInstance(); $sample->userid = $userid; $sample->email = $email; $sample->pass = sha1($pass); return $sample->save(); } public function deleteUser($userid) { return $this->delete( array('userid' => '?'), array($userid) ); } public function getUser($userid) { return $this->findOne( array( 'fields' => array('id', 'userid', 'email'), 'where' => array('userid' => '?') ), array($userid) ); } public function hasUser($userid, $pass) { return $this->has( array( 'where' => array( 'userid' => ':userid', 'pass' => ':pass' ) ), array( ':userid' => $userid, ':pass' => sha1($pass) ) ); } }
- array find ( array $query = array(), array $params = array())
find() の引数 $query は、 'distinct', 'fields', 'from', 'as', 'joins', 'where', 'group', 'having', 'order', 'limit', 'offset' が使えます。
public function getUserByName($name) { return $this->find( array( 'distinct' => false, 'fields' => array( 'U.id AS id', 'U.name AS name', 'U.category AS cat', 'P.url AS url' ), 'as' => 'U', 'joins' => array( 'type' => 'LEFT', 'table' => 'profile', 'as' => 'P', 'on' => array('U.id' => 'P.id') ), 'where' => array( 'name' => ':name' ), 'group' => 'cat', 'order' => 'id DESC', 'limit' => 10, 'offset' => 5 ), array( ':name' => $name ) ); }ある程度のクエリは扱えます。
モデル内では
$this->getDatabase()
が PDO として使えるので、
public function getName($id) { $sql = 'SELECT name FROM foo WHERE id = ?'; $stmt = $this->getDatabase()->prepare($sql); $stmt->execute(array($id)); return $stmt->fetchAll(PDO::FETCH_ASSOC); }上のように直接クエリを書いてもいいですが、
直接クエリを書かずにモデルの find() や delete() 等を使うメリットとしては、
'created' と 'modified' というフィールドが自動てセットされることが大きいです。 テーブル定義にあらかじめ created もしくは modified を定義しておくと、 insert (save), update のタイミングでそれぞれ現在時刻を設定します。
integer や int(11) で定義すると 現在の time() が設定されます。
datetime は Y-m-d H:i:s になります。
varchar(255) で定義すると現在時刻をミリ秒で設定します。
- created : 作成された日時
- modified : 更新された日時
コントローラでのモデル定義は $models に使うモデル名(テーブル名)を記述します。
class SampleController extends PunyApp_Controller { public $models = array('sample'); public function getLogin($id) { $user = $this->sample->getUser( ... ); } }
Views
$this->view->text = 'Hello!'; $this->view->render('index');ビューでは PHP本来が持ってるテンプレートを使います。
<html> <body> <h1>Sample</h1> <?php echo $text; ?> </body> </html>テンプレート変数はデフォルトでHTMLエスケープされます。
$this->view->text = '<script>alert(1)</script>';
<p><?php echo $text ?></p> // <script>alert(1)</script>
Validation
リクエストパラメータのバリデーションはコントローラ内で行います。class SampleController extends PunyApp_Controller { public $validationRules = array( 'id' => array( 'required' => true, 'rule' => array('regex', '/^[a-z0-9]{1,10}$/i'), 'message' => 'Only letters and integers, max 10 characters' ), 'email' => array( 'required' => true, 'rule' => array('email'), 'message' => 'Invalid email address' ), 'pass' => array( 'required' => true, 'rule' => array( array('minLength', 4), array('maxLength', 20) ), 'message' => 'Min 4 characters, max 20 characters' ) ); // ... }バリデーションのルールは
email, url, ip, between, minLength, maxLength, regex
等が定義されています。または自分で定義します。
その他、コールバックが使えます。
$this->validationRules['nickname'] = array( 'required' => true, 'rule' => array('callback', function ($value) { return preg_match('/^[ぁ-ん]/u', $value) && preg_match('/[!]$/u', $value); }), 'message' => 'ひらがなではじまって「!」で終わらないとダメです' );$this->validate() で実行します。 任意のルールを引数に渡すこともできます。
引数を省略すると $validationRules に対して実行します。
class SampleController extends PunyApp_Controller { // ... public function postLogin($params) { if ($this->validate()) { // ... } } }以下のViewメソッドからメッセージを取得できます。
追記
以下の情報はバージョンアップに伴い互換性があるかわかりません
詳細は https://github.com/polygonplanet/PunyApp を参照ください
詳細は https://github.com/polygonplanet/PunyApp を参照ください
- 名前を指定して取得 : string getValidationError( string $name );
- 最後のメッセージを取得 : string getLastValidationError( );
- 全部取得 : array getValidationErrors( );
- HTML<li>で全部取得 : string getValidationErrorMessages( array $attributes = array('style' => 'color:red') );
$this->view->getValidationError('hoge')
のように取得できます。
ビュー内では以下のようにして表示できます。
<div class="error"> <?php echo $this->getValidationError('param_name') ?> </div>
インストールと設定
1. 展開したファイルをサーバーの任意のディレクトリに置きます2. application/settings/app-settings.php を開いて設定します
$settings = array( /** * System settings */ 'system' => array( /** * Debug mode * * true = show errors * false = hide errors */ 'debug' => true, // デバッグモードだとエラーが起きたとき表示される /** * Timezone * * e.g., 'America/Chicago', 'Asia/Tokyo' etc. */ 'timezone' => '', // 日本の場合はここを 'Asia/Tokyo' に設定しておく ... ), /** * Database settings */ 'database' => array( /** * Database engine * * Available engines: "mysql", "sqlite" and "posql". */ 'engine' => '', // 使用するデータベース ... ), /** * Session settings */ 'session' => array( /** * Session engine * * Available engines: "php", "file" and "database". */ 'engine' => '', // セッションエンジンを設定 ... ) );3. データベーススキーマを作成します、または application/settings/app-schema.php に記述します
4. application/storage 配下のファイル、ディレクトリのパーミッションを「書き込み可」に設定します
5. 1 で展開したディレクトリにブラウザでアクセスしてみて、PunyApp ~と表示されたら成功です
6. 実際に作ってみましょう
サンプル
/sample/
にサンプルのログインフォームが入っています。
/sample/
にアクセスして確認できます。
なにかあれば以下のレポジトリのIssues, または @polygon_planet へお願いします。
0 件のコメント:
コメントを投稿