そして再びMVC

ハブロコミュニティにこんにちは。



かつて私はhabr リンクから記事に出会いました。 そのシステムを試してみたところ、多くの欠点があり、元の記事の翻訳が完全には存在しないという結論に達しました。 はい、この記事は時代遅れですが、同時に、シンプルで中規模のサイトを作成するための独自の小さなフレームワークを作成したかったのです。 私は2〜3メガバイトの名刺Webサイトを作成するための本格的なフレームワークを使用しているので、それを犠牲にすると考えています(常にではありませんが)。



一般に、目立った欠陥を修正し、結果をhabrozhitelamiと共有することにしました。



それで、何が改善されましたか?



1. Registryクラスの使用を取り除きます。 PHP5に__setや__getのような素晴らしいメソッドがあるのに、なぜ必要なのでしょうか?



2. PDOの代わりに、Active Recordsと呼ばれるクラスを作成しました。これにより、レイヤーを介してデータベースと通信できます。 コードの品質はそれほど高くなく、リファクタリングする必要があるため、ソースコードは提供しません。 ただし、必要に応じて追加します。



3. Templateクラスが少し書き直され、ネストされたテンプレートを作成する機能が追加されました。 これは次のようになります。



<?php



クラステンプレート{



private $ vars = array ( ) ;



関数 __set ( $ varname 、 $ value ) {

$ this- > vars [ $ varname ] = $ value ;

trueを 返し ます 。

}



function show ( $ name 、 $ data = false 、 $ display = true ) {

$ path = site_path 。 「ビュー」 。 DIRSEP $ name 。 '.php' ;



if ( ! file_exists ( $ path ) ) {

trigger_error ( 'Template `` 。 $ name 。 ' 'does not exist。' 、 E_USER_NOTICE ) ;

falseを 返し ます 。

}



if ( $ data ) {

//データを入力します

if ( is_array ( $ data ) ) {

foreach ( $ data as $ key => $ value ) {

$ this- > __set ( $ key 、 $ value ) ;

}

}

}



抽出 ( $ this- > vars ) ;



if ( $ display ) {

include ( $パス ) ;

} else {

if ( is_file ( $ path ) ) {

ob_start ( ) ;

インクルード $パス ;

$ contents = ob_get_contents ( ) ;

ob_end_clean ( ) ;

$コンテンツを 返し ます。

}

falseを 返し ます 。

}

}

}



?>





4.ルーターが変更され、URLのいくつかのパラメーターのサポートが登場しました。 ルーターにはまだ問題があると思われますが、これは時間の経過とともに解消されます。 しかし、それが動作している間:)



<?php



クラスルーター{



パブリック $パス ;

private $ args = array ( ) ;



関数 setPath ( $ path ) {

$ path = trim ( $ path 、 '/ \\' ) ;

$パス 。= DIRSEP ;



if ( ! is_dir ( $ path ) ) {

新しい例外をスロー( '無効なコントローラーパス: ``' 。 $ path 。 '' ' ) ;

}

$ this- > path = $ path ;

}



関数デリゲート( ) {

//パスを分析します

$ this- > getController ( $ file 、 $ controller 、 $ action 、 $ args ) ;

//ファイルは利用可能ですか?

if ( ! is_readable ( $ file ) ) {

trigger_error ( 'File `` 。 $ file 。 ' 'not found' 、 E_USER_ERROR ) ;

}

include ( $ファイル ) ;



//コントローラを作成します

$ class = 'Controller_' 。 $コントローラー ;

$コントローラー = 新しい $クラス ( ) ;



//アクションはオブジェクトで利用可能ですか?

if ( ! is_callable ( array ( $ controller 、 $ action ) ) )) {

trigger_error ( 'メソッドがありません `` 。 $ action 。 ' 'クラスで見つかりました' 、 E_USER_ERROR ) ;

}

//アクションを呼び出す

call_user_func_array ( array ( $ controller 、 $ action ) 、 $ args ) ;

}



private function getController ( & $ file 、 & $ controller 、 & $ action 、 & $ args ) {

$ route = ( empty ( $ _GET [ 'route' ] ) ) ? 'インデックス' : $ _GET [ 'route' ] ;

// urlと呼ばれる分割

$ route = trim ( $ route 、 '/ \\' ) ;

$ parts = explode ( '/' 、 $ route ) ;



//適切なコントローラーを見つける

$ cmd_path = $ this- > path ;



//デフォルトのコントローラー名を設定します(別のコントローラー名が見つかった場合は置き換えられます)

$コントローラー = 'インデックス' ;



foreach ( $ parts as $ part ) {

$ fullpath = $ cmd_path 。 $ part ;

// dirですか?

if ( is_dir ( $ fullpath ) ) {

$ cmd_path 。= $ part 。 DIRSEP ;

array_shift ( $パーツ ) ;

続ける ;

}



//ファイルですか?

if ( is_file ( $ fullpath 。 '.php' ) )) {

$コントローラー = $ part ;

array_shift ( $パーツ ) ;

休憩 ;

}

}



//コントローラのアクションメソッドを取得します

$ action = ( isset ( $ parts [ 0 ] ) && ! is_numeric ( $ parts [ 0 ] ) ) ? array_shift ( $ parts ) : 'インデックス' ;

$ file = $ cmd_path 。 $コントローラー 。 '.php' ;

$ args = $ parts ;

}

}

?>





5.モデル(実装済み)、ライブラリ(実装済み)がロードされるLoaderクラスが追加されました。 将来的には、そこにねじ込んで、ヘルパーをロードします。



<?php



クラスローダー{



パブリック $インスタンス ;

public $ vars = array ( ) ;



関数 __construct ( $ parent ) {

$ this- > instance = $ parent ;

}



関数モデル( $ model_name ) {

$ filename = strtolower ( $ model_name ) 。 '.php' ;

$ file = site_path 。 'models' 。 DIRSEP $ファイル名 ;

if ( ! file_exists ( $ file ) ) {

falseを 返し ます 。

}

include ( $ファイル ) ;

$ this- > instance- > $ model_name = new $ model_name ( new ActiveRecords ( ) ) ;

}



関数ライブラリ( $ name ) {

$ filename = strtolower ( $ name ) 。 '.php' ;

$ file = site_path 。 'ライブラリ' DIRSEP $ファイル名 ;

if ( ! file_exists ( $ file ) ) {

falseを 返し ます 。

}

include ( $ファイル ) ;

$ this- > instance- > $ name = new $ name ( new ActiveRecords ( ) ) ;

}

}



?>





ここで、ご覧のとおり、前述のActiveRecordsクラス(現在はシングルトーン)が任意のモデルまたはライブラリに渡されます。 このため、データベースとの連携はモデルとライブラリで利用可能になりつつあります(MVCコンセプトから期待されています)。 ただし、モデルとライブラリの名前には制限があります。たとえば、loadと呼ばれるモデルを使用することはできません。



モデル自体の基本クラスは、プロジェクトのすべての後続クラスの継承元であり、次のようになります。



<?php



クラス Model {



var $ db ;



関数 __construct ( $ db ) {

$ this- > db = $ db ;

}

}



?>





6.上記の変更を考慮すると、以降のすべてのコントローラーが継承されるコントローラーの基本クラスは、次のようになります。



<?php



class Controller_Base {



パブリック $テンプレート ;

パブリック $ロード ;



関数 __construct ( ) {

$ this- > template = new Template ( ) ;

$ this- > load = new loader ( $ this ) ;

}



関数 __set ( $ varname 、 $ value ) {

$ this- > $ varname = $ value ;

trueを 返し ます 。

}

}



?>





したがって、各コントローラーでは、LoaderクラスとTemplateクラスを使用できます。 そして、同様のことをコードで書くことができます:



$ this- > load- > model ( 'links' ) ;

$ this- > links- > add ( ' new ' ) ;




つまり、このタイプではモデルのすべてのメソッドが使用可能になります。



$ this- > [モデル名] -> [モデルのメソッド名]




7.また、小さな変更がスタートアップスクリプトに追加されました-セッションの初期化(将来、データベースからセッションを追加する予定です)、頻繁に使用されるリダイレクト関数が__autoload関数と共に追加されます。



関数リダイレクト( $ url )

{

ヘッダー ( "Location:" 。 $ Url ) ;

}




データベースに接続するだけでなく(ここではわかりませんが、Active Recordsクラスでデータベースに接続するのは理にかなっていますか?)



8.そして最も重要なことは、すべてのリクエストを処理するメインのindex.phpファイルです。 これは次のようになります。



<?php



require 'includes / start.php' ;

$ router = new Router ( ) ;

$ router- > setPath ( site_path 。 'controllers' ) ;

$ router- > delegate ( ) ;



?>




フレームワークのソースコードはこちらからダウンロードできます: link ここで、ソースコードがすぐに使用できるわけではないことに注意してください。 使用例として必要な、ベースカーネルに加えて、いくつかのコードのみを考えます。



あなたのコメント、発言、指示に喜んでいます。



PSそして、はい-最も重要なこと。 リソースを使用して作成された小さなリソースの実例はリンクです。 このサービスを使用すると、カテゴリへのリンクをオンラインで保存できます。 既存のリポジトリは多くの理由で適切ではないため、それ自体が記述されています。 さらに、何かでカーネルをテストする必要がありました。



All Articles