2017 © Pedro Peláez
 

project min

Min - Minimam INter framework for PHP

image

zubapita/min

Min - Minimam INter framework for PHP

  • Tuesday, July 4, 2017
  • by zubapita
  • Repository
  • 1 Watchers
  • 0 Stars
  • 3 Installations
  • JavaScript
  • 0 Dependents
  • 0 Suggesters
  • 0 Forks
  • 0 Open issues
  • 1 Versions
  • 0 % Grown

The README.md

min

Minimam INter framework for PHP, (*1)

これは何?

PHP 5.5以上のための、Ajax Webアプリ開発のためのフレームワークです。 開発時の手間をミニマムにすることを目標に作られています。 * コーディングの手間を最小化:コードやテストを自動生成します。また開発者が書くコード量を最小化します。 * 学習の手間を最小化:既存の定番クラスライブラリやツールを組み合わせることで、新しいフレームワークやツールを覚える手間を減らします。 * 試行錯誤の最小化:テストツールやデバッグツールをフレームワークに組み込むことで、問題を把握しやすくします。 * AjaxなWebアプリを簡単に作れるように、JQueryとPHPの通信をシンプルかつ確実にできるメソッドを提供します.
* データベースのCRUDもすべてAjaxです。
* Google ChromeのPHP-Consoleと組み合わせることで、デバッグが面倒なAjaxアプリ作りが楽になります。
* デザインにはBootstrap 3を採用しています。Bootstrap 3用のテンプレートも簡単に適用できます。 * 独自の認証ライブラリを内蔵し、ログインフォームを安全・簡単に作れます。, (*2)

利用クラスライブラリ

minは以下のクラスライブラリを利用しています。, (*3)

  • "smarty/smarty":テンプレートクラス
  • "validator/livr":バリデータクラス
  • "php-console/php-console":Google Chromeのconsoleに出力できるデバッグクラス
  • "apache/log4php":ファイルに実行ログを記録するクラス
  • "hybridauth/hybridauth":Twitter、FacebookなどによるOAuth認証クラス
  • "verot/class.upload.php":アップロードされた画像をハンドリングするクラス
  • "phpoffice/phpexcel":Excelワークシートを操作するクラス
  • "nesbot/carbon":日付時間データ操作クラス

また開発時には以下を利用します。, (*4)

  • "phpunit/phpunit":テストフレームワーク
  • "phpunit/phpunit-selenium":Webブラウザ・テストフレームワーク
  • "fzaninotto/faker":ダミーデータ生成クラス

推奨環境

  • PHP 5.5+
  • Composer
  • OS:Mac OS X or Linux
  • Webブラウザ:Google Chrome
  • テキストエディタ:TextMate or Sublime Text

Windowsでの利用は検証されていません。, (*5)

インストール

1. composerによるインストール

$ composer create-project zubapita/min [プロジェクト名] -s dev, (*6)

2. ZIPをダウンロードしもしくは、リポリトジをclone

新しいminアプリ(プロジェクト)を作成する

$ ./makeNewApp.php -a testApp -r /Users/mydir/workspace, (*7)

make New Min Application., (*8)

make application : testApp. parentPath=/Users/mydir/workspace, (*9)

Please run 'composer install' at new app root., (*10)

「/Users/mydir/workspace/testApp」が作成され、その下に必要なファイル一式がコピーされます。 アプリのディレクトリに移動して、Composerで必要なライブラリをインストールします。, (*11)

$ cd /Users/mydir/workspace/testApp
$ composer install, (*12)

アプリ作成手順

ヒント

bin以下にアプリの作成、利用のためのコマンド群があります。
パラメータを付けないで実行すると、使い方の説明が表示されます。, (*13)

$ cd bin
$ ./makeNewApp.php, (*14)

make New Min Application., (*15)

usage: ./makeNewApp.php -a [app name] -r [root dir name(option)] ex)/Users/user/workspace, (*16)

データベースのモデルを作成する

MinではデフォルトではPDOをオーバーライドした独自のクラスでDBを利用します。 (もちろん自分の好みのDBクラスをインストールして使っても構いません) この独自のDBクラスを利用するためには、 * DBのクラス * 各テーブルのクラス * 各テーブルを操作するモデルクラス が必要で、それぞれコマンドで自動で生成できます。, (*17)

データベースのクラスを作成する

MySQLのデータベース「test」のクラスを作成し、 * ユーザー名:testuser * パスワード:gh67L*K0 の場合、, (*18)

$ ./makeDbClassFile.php -d test -s mysql -u testuser -p gh67L*K0, (*19)

クラスファイルが * model/_def/db/test.php に作成されます。, (*20)

テーブルのクラスを作成する

  • データベース「test」のすべてのテーブルのクラスを作成する。

./makeTableClassFiles.php -d test, (*21)

クラスファイルが * model/_def/db/test/ 以下に作成されます。, (*22)

  • データベース「test」のテーブル「users」のクラスを作成する。

./makeTableClassFiles.php -d test -t users, (*23)

クラスファイルが * model/_def/db/test/users.php に作成されます。, (*24)

テーブルのモデルを作成する

  • データベース「test」のテーブル「users」を操作するモデルクラスを作成する。

$ ./makeModelClassFiles.php -d test -t users, (*25)

クラスファイルが * model/test/UsersList.php * model/test/UsersRecord.php に作成されます。, (*26)

model/test/UsersList.php は、usersテーブルから一覧データを取得したり、検索結果を取得するためのクラスです。, (*27)

使用例:, (*28)

$UsersList = new UsersList(); $list = $UsersList->get(); var_dump($list);, (*29)

model/test/UsersRecord.php は、usersテーブルにデータを挿入、更新、削除するためのクラスです。, (*30)

使用例:, (*31)

$data['id'] = 1; $data['name'] = "Tom"; $data['birthday'] = "2001-10-15";, (*32)

$UsersRecord = new UsersRecord(); $UsersRecord->set($data);, (*33)

$data = $UsersRecord->get("id=1"); var_dump($data); $data['name'] = "Tom Cat"; $UsersRecord->set($data);, (*34)

クラスファイル model/_def/db/test/users.php にキーとなるカラムの定義があり、 デフォルトではidカラムがキーとなっています。idを変えずに他のカラムの値を変更してset()を実行すれば 行がupdateされます。idがテーブルに存在しない値なら行がinsertされます。, (*35)

バリデータを調整する

モデルを使ったデータの挿入がうまく行かない場合は、レコードモデル(model/test/UsersRecord.phpなど)のバリデータの設定を確認してください。 デフォルトでは、すべてのカラムに['required'](必須)が設定されています。, (*36)

バリデータの記述ルールは以下を参照してください。 https://github.com/koorchik/LIVR, (*37)

モデルのテスト

モデルクラスファイルを自動生成すると、同時にtest/modelディレクトリの下にphpunit用のテストファイルが作成されます。
booksテーブルの場合は、 * test/model/books/BooksListTest.php (BooksListクラスのテスト) * test/model/books/BooksRecordTest.php (BooksRecordクラスのテスト) の2つのファイルが作成されます。, (*38)

phpunitがインストール済みならば、以下の様にコマンドラインでテストが行えます(phpunitに実行パスを通しておく必要があります)。, (*39)

$ phpunit BooksListTest.php
$ phpunit BooksRecordTest.php, (*40)

ただし、BooksRecordTest.phpは、そのままのテストではエラーになります。
内部でテーブルに挿入するデータを設定する dataProvider() メソッドがあるので、適切な挿入用データを出力するように調整してください。, (*41)

Webのビューとコントローラーを作成する

前提:このWebアプリのURLをhttp://test.mysite.jp/だとします。, (*42)

なお、Webアプリとして動かすためには、etc/local_vh.conf を参考にVirtualHostを設定してください。
基本は、htdocsがDocumentRootになるようにして、etc/rewrite.conf をincludeすれば動くはずです。
また、var/compiledに apacheが書き込めるようにしてください。, (*43)

基本, (*44)

ビューとコントローラーを作成するには、 makeNewCtlAndView.php に -m でモデル名を、-p でページ名を指定します。, (*45)

テーブル内のデータ一覧表示や検索を目的としたビューとコントローラーを作成する, (*46)

$ ./makeCtlAndView.php -m UsersList -p users, (*47)

コントローラーのクラスファイルが * controller/users/usersCtl.php に作成されます。, (*48)

ビューのテンプレートが * view/users/index.html に作成されます。, (*49)

テンプレートはSmartyのルールで記述されています。
またテーブル表示のパーツが view/users/includes/ 内にあります。, (*50)

このページには * http://test.mysite.jp/users/ でアクセスできます。, (*51)

テーブルへのデータ挿入や更新を目的としたビューとコントローラーを作成する, (*52)

$ ./makeCtlAndView.php -m UsersRecord -p users/record, (*53)

コントローラーのクラスファイルが * controller/users/record/usersRecordCtl.php に作成されます。, (*54)

ビューのテンプレートが * view/users/record/index.html * view/users/record/add.html * view/users/record/edit.html に作成されます。, (*55)

テンプレートはSmartyのルールで記述されています。
またフォーム表示のパーツが view/users/record/includes/ 内にあります。, (*56)

これらのページには * http://test.mysite.jp/users/record/ * http://test.mysite.jp/users/record/add.html * http://test.mysite.jp/users/record/edit.html でアクセスできます。, (*57)

テーブルを使用しないビューとコントローラーを作成する, (*58)

$ ./makeCtlAndView.php -p about, (*59)

コントローラーのクラスファイルが * controller/about/aboutCtl.php に作成されます。, (*60)

ビューのテンプレートが * view/about/index.html に作成されます。, (*61)

テンプレートはSmartyのルールで記述されています。, (*62)

このページには * http://test.mysite.jp/about/ でアクセスできます。, (*63)

コントローラーのテスト

コントローラーを作成すると、自動的にPHPunit-selenium用のテストファイルがtest/controllerディレクトリの下に作成されます。
* UsersCtlの場合:test/controllerディレクトリの下に作成されます/users/UsersCtlTest.php * UsersRecordCtlの場合:test/controllerディレクトリの下に作成されます/users/UsersRecordCtlTest.php, (*64)

test/controller/usersに移動して, (*65)

$ phpunit UsersCtlTest.php, (*66)

でテストが行えます(phpunitに実行パスを通して、selenium-serverとchromedriverもインストールしておく必要があります)。 テストファイルの中身を書き替えてご利用ください。, (*67)

データベース操作

minは以下の特徴を持つ、独自のデータベース操作クラスを内蔵しています。 * PDOをベースにしているため、高速。 * テーブルの操作を記述すると、内部ではプレースホルダを使用したSQLを自動生成してPDOを使ってデータベースを操作する。SQLインジェクションに強くて安全。 * テーブル上のユニークキーを決めておけば、挿入と更新を自動判断。 * メソッドチェインによるスマートな記述法。, (*68)

テーブル操作の基本

前提:データベース「testDB」に以下の構造を持つテーブル「books」があるとします。
このbooksテーブルをインスタンス化して、テーブルの操作を行います。, (*69)

CREATE TABLE books (
id int(11) unsigned NOT NULL AUTO_INCREMENT,
title varchar(50) DEFAULT NULL,
author varchar(50) DEFAULT NULL,
isbn varchar(14) DEFAULT NULL,
price int(11) DEFAULT NULL,
releaseDate datetime DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;, (*70)

テーブル・インスタンスの取得

$_ = $this;
$->DB = $->getDB('testDB');
$->Books = $->getTable($_->DB, 'books');, (*71)

$_->Booksにbooksテーブルのインスタンスが格納されます。, (*72)

テーブルへの行挿入

$_ = $this;
$bookData = [
'title' = 'ハムレット',
'author = 'シェークスピア',
'isbn' = '978-4102020036',
'price' = 497 , 'releaseDate' = '1967/9/27' , ];
$result = $_->Books->saveSet($bookData);, (*73)

テーブルからの行取得と更新

titleが'ハムレット'の行を取得します。, (*74)

$_ = $this;
$columns = [
'id',
'title',
'author',
'price',
];
$condition = ['title'=>'ハムレット'];
$bookData = $_->Books->select($columns)->find($condition)->fetch();, (*75)

$bookDataに結果行が格納されます。, (*76)

$bookData['author'] = 'ウイリアム・シェークスピア';
$result = $_->Books->saveSet($bookData);, (*77)

取得した行のauthorカラムが書き替えられます。
デフォルトではidカラムがユニークラカムとなっているため、行を更新するにはidカラムを取得しておく必要があります。
ユニークカラムの設定は、model/_def/(DB名)/(テーブル名).php内に記述されているので、必要に応じて書き替えられます。, (*78)

テーブルからすべての行を取得

$_ = $this;
$columns = [
'id',
'title',
'author',
'price',
];
$condition = [];
$bookDataRows = $_->Books->select($columns)->find($condition)->fetchAll();, (*79)

1行ずつ取得したいときは、getRows()を利用します。, (*80)

$rows = $_->Books->select($columns)->find($condition)->getRows();
while ($row = $rows->fetch(PDO::FETCH_ASSOC)) {
var_dump($row);
}, (*81)

getRows()はPDOstatementを返すので、以後はPDOのメソッドによる操作が可能になります。, (*82)

検索条件の記述

検索の条件(Where句の条件)は、find()のパラメータとして指定します。, (*83)

$bookDataRows = $_->Books->select($columns)->find($condition)->fetchAll();, (*84)

パラメータ$conditionに記述するのですが、以下の様に文字列や配列で記述します。, (*85)

  1. 文字列 >$condition = "title='ハムレット'";

$condition = "price>300";, (*86)

  1. 配列 >$condition = ['title'=>'ハムレット'];

$condition = ['title'=>['opr'=>'=', 'val'=>'ハムレット']];, (*87)

$condition = ['price'=>['opr'=>'>', 'val'=>300]];, (*88)

複数カラムのAND検索(OR検索はサポートしていません), (*89)

$condition = [
'author'=>['opr'=>'=', 'val'=>'シェークスピア'],
'price'=>['opr'=>'<', 'val'=>1000]
];, (*90)

BETWEENも使えます。, (*91)

$condition = ['price'=>['opr'=>'BETWEEN', 'MIN'=>300, 'MAX'=>1000]];, (*92)

1.の文字列は記述が簡単ですが、SQLが生成されるときに、プレースホルダが生成されずに条件がそのままWhere句に使われます。危険なので使わないほうがいいでしょう。, (*93)

limit、offset、order by

$_ = $this;
$columns = [
'id',
'title',
'author',
'price',
];
$->Books->select($columns);
$
->Books->offset(0)->limit(10)->orderBy('price DESC');
$condition = [];
$_->Books->find($condition)->fetchAll();, (*94)

ORDER BYで複数のカラムを指定するときは、以下のように指定します。, (*95)

1.文字列, (*96)

$order = 'price DESC, title ASC';
$_->Books->orderBy($order);, (*97)

2.配列, (*98)

$order = ['price DESC', 'title ASC']; $_->Books->orderBy($order);, (*99)

group by

$_ = $this;
$columns = [
'id',
'title',
'author',
'price',
];
$->Books->select($columns);
$
->Books->->groupBy('author');
$condition = [];
$_->Books->find($condition)->fetchAll();, (*100)

GROUP BYで複数のカラムを指定するときは、以下のように指定します。, (*101)

1.文字列, (*102)

$group = 'author, price';
$_->Books->groupBy($group);, (*103)

2.配列, (*104)

$group = ['author', 'price'];
$_->Books->groupBy($group);, (*105)

join

$->Sales = $->getTable($->DB, 'sales');
$
->Books->join($_->Sales)->on('books.isbn=sales.isbn');, (*106)

INNER JOINの場合は, (*107)

$->Books->innerJoin($->Sales)->on('books.isbn=sales.isbn');, (*108)

モデルによるデータベース操作

makeModelClass.phpを使うと、テーブルを操作するための2つのモデルクラスが生成されます。, (*109)

  1. DataListクラス
  2. DataRecordクラス

DataListクラス

テーブル内の一覧の取得や検索結果の取得を行うクラスです。
テーブル名がbooksなら、BooksListクラスが、BooksList.php内に生成されます。
コントローラーから使用するときは, (*110)

$BookList = new BookList();
と記述します。必要に応じてクラスファイルがautoloadされます。, (*111)

  • get($conditions, $currentPage)

テーブルから一覧を取得し、配列で返します。取得結果がない場合は0を返します。
最大取得行数はデフォルトでは10になっています。, (*112)

@param (array|string) $conditions 文字列もしくは配列で検索条件を指定します。, (*113)

@param integer $currentPage テーブル内の全行数を最大取得行数で割った数字を指定します。
最大取得行数10のとき、11行〜20行を取得したいときは、$currentPage=2とします。, (*114)

  • setMaxItemsInPage($maxitems)

最大取得行数を設定します。, (*115)

@param integer $maxitems 最大取得行数, (*116)

  • getMaxItemsInPage()

現在の最大取得行数を返します。, (*117)

DataRecordクラス

テーブルへの行単位の手刀、挿入、更新を行うためのクラスです。挿入、更新時はバリデートも行います。
テーブル名がbooksなら、BooksRecordクラスが、BooksRecord.php内に生成されます。
コントローラーから使用するときは, (*118)

$BookList = new BookList();
と記述します。必要に応じてクラスファイルがautoloadされます。, (*119)

  • get($conditions)

テーブルから該当する行を取得して返します。, (*120)

@param (array|string) $conditions 文字列もしくは配列で検索条件を指定します。, (*121)

  • set($data)

テーブルに行を保存します。ユニークキーが指定されていないか、指定されていてもテーブル内に存在しない場合は、新規に行を挿入します。ユニークキーがテーブルに存在する場合は、更新します。, (*122)

組み込み機能を利用する

ログインフォームのインストール

etc/template/set/auth 以下にユーザー認証とTwitterやFacebookによるOAuth認証を行うための一式があります。
利用するには、まずユーザー認証を保存するデータベースを用意し、bin/install.phpを実行します。, (*123)

データベース名が「mindb」、ユーザー名「mindb」、パスワードなしでmysqlで作った場合, (*124)

$ cd bin
$ ./makeDbClassFile.php -d mindb -u mindb -s mysql
$ cd etc/template/set/auth/bin
$ chomod +x install.php
$ ./install.php -d mindb, (*125)

これで必要なモデル、ビュー、コントローラーの一式が保存され、デフォルトのヘッダにある「ログイン」メニューが使えるようになります。
ただし、OAuth認証を使うには、TwitterやFacebookのAPIキーを取得し、model/_def/api/以下のTwitterApiKey.phpなどにAPIキーを設定する必要があります。, (*126)

画像のAjaxアップロードのインストール

etc/template/set/uploadImg 以下に画像のAjaxアップロードを行うための一式があります。
利用するには、bin/install.phpを実行すると、画像アップロードを行うコントローラとビューのセットがインストールされます(モデルは使用していません)。
デフォルトのページ名はuploadImgですが、-p ページ名 でページ名を指定できます。
URLをhttp://mydomain/imageupload/ にしたいときは、以下の様に指定します。, (*127)

$ cd etc/template/set/uploadImg/bin
$ chomod +x install.php
$ ./install.php -p imageupload, (*128)

アップロードされた画像は、var/images/uploaded 以下に保存されます。
画像の表示はとなります。uploadedの部分を書き替えたいときはコントローラ内で変更してください。
但し、/img/は使えません。画像のパスに/img/が含まれていると自動的にhtdocs以下の画像ファイルが表示対象になります。これはetc/rewrite.confに設定されています。
var/imagesは固定ですが、変更したい場合はlib/Dispatch.php内のsendImage()を書き換えてください。 表示可能な画像の拡張子はjpeg、JPEG、jpg、JPG、png、PNG、gif、GIFです。変更したい場合はlib/Dispatch.php内のsetPathAndAction()を書き換えてください。, (*129)

ディレクトリ構造

  • bin
    アプリの作成使用する各種バッチコマンドの置き場所です。また自分でバッチコマンドを作成するための雛形もあります。
  • contoroler
    Webアプリのコントローラーの置き場所です。コントローラーはエンドポイントであるindex.phpから起動されます。
  • etc
    各種設定ファイルの置き場所です。
  • htdocs
    ドキュメントルートです。画像ファイルやfavicon、robots.txtなど静的ファイルの置き場所です。
    htdocs/index.php がWebアプリの起点(エンドポイント)となり、URLに応じて各コントローラーを起動します。
    画像ファイルはhtdocs/img/* や htdocs//img/ の下に置きます。このルールはetc/rewrite.confで設定できます。
  • lib
    minの動作に必要なクラスライブラリが置かれています。
  • model
    データベースを操作するモデルクラスの置き場所です。データベース以外のapi操作やExcel操作もモデル化してここに置きます。 モデル内のデータベースの操作は独自のデータベース操作クラスにより、SQLを書かずにシンプルに操作を記述できます。
  • test
    テストファイルの置き場所です。
  • var
    一時ファイルの置き場所です。
    var/compiledにビューのテンプレートがコンパイルされたphpが置かれます。var/compiledはapacheから書き込み可能に設定しておく必要があります。
  • vendor
    composerによってインストールされる各種クラスライブラリの置き場所です。
  • view
    HTMLファイルの置き場所です。
    view/index.html がトップページのHTMLです。
    HTMLはSmartyのテンプレートファイルになっています。Smartyはif〜else文による条件分岐やforeachなどのループ、変数の計算や代入などをサポートした高機能なテンプレートクラスです。
    minでは、表示部分のプログラミングはSmartyとJQueryでほとんど行います。

セキュリティ対策

フレームワークレベルで以下のセキュリティ対策を施してあります。, (*130)

クロスサイトスクリプティング(XSS)対策

Samrtyのescape_htmlフィルタを各コントローラのコンストラクタにデフォルトで設定してあります。, (*131)

$_->view->escape_html = true;, (*132)

これによって、すべてのSmarty変数の出力がHTMLエスケープされます。
エスケープを無効にしたいときは、変数を出力する際にnofilterを指定します。, (*133)

{$変数名 nofilter}, (*134)

SQLインジェクション対策

内蔵データベース操作クラスは、PDOのプレースホルダを使用しています。
これによって、マルチステートメントの実行などが無効化されます。, (*135)

入力文字列のエスケープ

外部からの入力を受け取るために$_GETと$_POSTの代わりに、次の5つのメソッドが用意されています。 * getGETNumValue('変数名', [デフォルト値]) // 数値を$_GET['変数名']から取得。数値でないか存在しない場合はデフォルト値を返す。 * getGETStrValue('変数名', [デフォルト値]) // 文字列を$_GET['変数名']から取得。文字列はHTMLエスケープされる。存在しない場合はデフォルト値を返す。 * getPOSTNumValue('変数名', [デフォルト値]) // 数値を$_POST['変数名']から取得。数値でないか存在しない場合はデフォルト値を返す。 * getPOSTtrValue('変数名', [デフォルト値]) // 文字列を$_POST['変数名']から取得。文字列はHTMLエスケープされる。存在しない場合はデフォルト値を返す。 * getPostedData(boolean $raw=false) // $_POSTをまとめて配列で返す。$rawをtrueに指定しなければ、値はHTMLエスケープされる。また、本番運用以外(=開発時)はデバッグしやすくするため、$_POSTではなく、$_REQUESTを返す(=POSTだけでなく、GETでテストできる)。, (*136)

クロスサイトリクエストフォージェリ(CSRF)対策

デフォルトで生成されるAjaxによるPOSTは、毎回トークンを埋め込んで接続元を判定しています。
トークンの生成にはopenssl_random_pseudo_bytes()を使用しています。, (*137)

セッションハイジャック対策

内蔵ログイン認証クラスは、ログイン時にsession_regenerate_id()を実行してセッションIDを再生成しています。, (*138)

安全なパスワード保存

内蔵ログイン認証クラスは、パスワードのハッシュ化にpassword_hash()を使用しています。, (*139)

安全なファイルアップロード

内蔵のAjaxファイルアップロードは、アップロードされたファイルを公開ディレクトリに置きません。, (*140)

以下、更新予定, (*141)

Ajaxによるデータベース操作

Google Maps連動

Twitter連動

The Versions