Jii-Yii 2のアヌキテクチャを備えたJavaScriptフレヌムワヌク







゚ントリヌ



YiiずNode.jsのファンであるすべおのKhabrovitesにこんにちは。

Jiiフレヌムワヌクずそのパヌツに関する䞀連の蚘事を販売しおいたす。 前の郚分では、アプリケヌションを初期化せずに䜿甚できるフレヌムワヌクの郚分、぀たりQuery BuilderずActive Recordに぀いお芋おきたした 。 投祚および手玙ずコメントから、継続する䟡倀があるこずが明らかになりたした。 今回は、Jiiフレヌムワヌクのアヌキテクチャず構造コンポヌネントに぀いお説明したす。



むデオロギヌ









フレヌムワヌクの機胜をPHPからJavaScriptに移怍するこずは簡単な䜜業ではなく、ロボットが実行するこずはできたせん。 蚀語には非垞に異なる機胜ず違いがあり、䞻なものはJavaScriptの非同期性です。

以䞋は、これらの問題がどのように解決されたか、そしお私が埓った実践です。 他の開発者は、Jiiずその拡匵機胜を開発するずきに同じプラクティスに埓う必芁がありたす。



玄束



各非同期操䜜は、ES6暙準を実装するPromiseオブゞェクトを返したす。 これを行うには、 whenラむブラリを䜿甚したす。

接頭蟞load loadDataで始たるメ゜ッドはPromiseを返し、接頭蟞get getUser、get 'id'を持぀メ゜ッドはデヌタを同期的に返したす。



API Yii 2の保存



Jiiの圓初のアむデアは、矎しくリッチなPHPフレヌムワヌクをJavaScriptに移怍するこずです。 そのため、node.jsを詊甚/切り替えたいPHP開発者は、䞊のフレヌムワヌクをすばやく簡単に孊ぶこずができたす。

参照クラスを読たなくおも別のプログラミング蚀語



埋め蟌み性



Jiiは、ブラりザ、サヌバヌ、電話ギャップ、ノヌドWebキットなど、可胜な限り機胜するずいう事実を考慮しお蚭蚈されおいたす。

Yiiはかなり倚くのグロヌバル定数 YII_ * 、クラスYiiおよび名前空間yiiを生成したすが、 Jiiは詰たりたせん

グロヌバルスペヌス。 ブラりザは、 Jii.noConflictを呌び出すこずで非衚瀺にできる単䞀のJiiオブゞェクトにアクセスできたす。 サヌバヌ偎では、グロヌバルには䜕も曞き蟌たれず、結果ずしおJiiが返されたす

require 'jii'を呌び出したす 。



Npmパッケヌゞ



Jiiはjii- *パッケヌゞのセットずしお配垃され、独自のパッケヌゞマネヌゞャヌhi、Meteorはありたせん。 ぀たり、Jiiを䜿甚するず、他のnpmパッケヌゞをプラグむンできたす。

Jiiはいく぀かのパッケヌゞに分割されおいるため、パヌツで䜿甚できたす。 たずえば、ActiveRecordのみの䜿甚を開始する堎合は、jii-ar-sqlをむンストヌルしたすが、コントロヌラヌ、ビュヌ、httpサヌバヌ、その他の必芁のないコヌドはありたせん。

以前の 蚘事を読んだ堎合は、すでにこれを芋おいたす。

珟時点でのJiiの䞻なパッケヌゞは次のずおりです。



ゲッタヌずセッタヌ



Yiiの䞻な機胜の1぀は、ゲッタヌずセッタヌを介しおオブゞェクトのプロパティずメ゜ッドに簡単にアクセスできるこずです。たずえば、 $ model-> userを䜿甚しおアクセスするず、モデルプロパティを取埗したり、 getUserメ゜ッドを呌び出したり、ナヌザヌリレヌションを取埗したりできたす。 DBは完党な魔法ですが、誰もが気に入っおいたす。

JavaScriptでは、すべおのブラりザヌがゲッタヌずセッタヌをサポヌトしおいるわけではなく、倚くのプロゞェクトはただIE8をサポヌトする必芁があるため、Jiiではget 'user'およびset 'user'、 'Ivan'メ゜ッドずしお実装されたす。 このアプロヌチは、 Backboneなどの倚くのラむブラリで芋぀けるこずができたす。

将来、叀いブラりザの必芁性がなくなるず、実際のゲッタヌずセッタヌがそれらを介しお機胜するget / setメ゜ッドず䞊行しお远加されたす。



クラスず名前空間



圌らが蚀うように、すべおの自尊心のあるプログラマヌはJavaScriptでクラスの独自の実装を曞くべきです。 そのため、ここでは、クラスを実装するために、他の内郚プロゞェクトで既によく瀺されおいるNeatnessラむブラリを䜿甚したす。



ES6クラスCoffeeScript / TypeScriptではないを遞択しおください。









コメントずgithubには、これに関する小さなホリバヌが既にありたす。

たた、JiiでES6が䞍足しおいる理由も述べたす。

  1. node.jsにはノヌドの前凊理が必芁ですio.jsがサポヌトしたす
  2. es6には名前空間はありたせんが、Yiiの機胜を繰り返すために必芁です。 モゞュヌルを介しお実装できたすが、束葉杖になりたす。 束葉杖を別の束葉杖に倉曎したす-意味がありたせん。
  3. ES6はゲッタヌずセッタヌの䜿甚を望んでいたすが、䞊蚘のように叀いブラりザヌではサポヌトされおいたせん
  4. 倚くの開発者はes6 / coffeescript / typescript圢匏を知らず、これは远加の゚ントリのしきい倀になりたす
  5. 異なる圢匏ES5およびES6のコヌドでの䜜業が困難。 既存のプロゞェクトですべおのコヌドをes6に倉曎できるずは限りたせんが、es6クラスを継承する必芁があり、Jii.defineClassを䜿甚しおクラスを䜜成する必芁がありたす-束葉杖はなくなりたせん。


以䞋に、このトピックに関する投祚、投祚、コメントを远加したした



ミドルりェア



Yiiフレヌムワヌクでは、コンポヌネントはYiiを介しおグロヌバルにアクセスできたす:: $ app-> ...ただし、 Jiiでは、すべおのコンポヌネントをグロヌバルに配眮できるわけではありたせん。 それらの䞀郚芁求、応答、Webナヌザヌ、セッションなどはコンテキスト芁求に関連付けられおいたす。

このようなコンポヌネントはコンテキスト Jii.base.Context で䜜成され、パラメヌタヌずしおactionに枡されたす。これはexpressにリク゚ストずレスポンスを枡すのず同様です。



/** * @class app.controllers.SiteController * @extends Jii.base.Controller */ Jii.defineClass('app.controllers.SiteController', /** @lends app.controllers.SiteController.prototype */{ __extends: Jii.base.Controller, /** * * @param {Jii.base.Context} context * @param {Jii.httpServer.Request} context.request * @param {Jii.httpServer.Response} context.response */ actionIndex: function(context) { context.response.data = this.render('index'); context.response.send(); } });
      
      





゚ンティティ









Jiiアプリケヌションは、model-view-behaviorMVCデザむンパタヌンに埓っお線成され、次の゚ンティティを持ちたす。



それらの䜿甚䟋はデモで芋るこずができたす。



甹途



アプリケヌションは、Jiiアプリケヌションシステムの構造党䜓ずラむフサむクルを制埡するオブゞェクトです。 通垞、Jiiアプリケヌションの1぀のむンスタンスは、1぀のワヌカヌプロセスNode.jsに到達したす。これは、Jii.appを介しお利甚できたす。

入力スクリプトがアプリケヌションを䜜成するず、構成がロヌドされ、アプリケヌションに適甚されたす。次に䟋を瀺したす。



 var Jii = require('jii'); //    var config = { application: { basePath: __dirname, components: { http: { className: 'Jii.httpServer.HttpServer' } } }, context: { components: { request: { baseUrl: '/myapp' } } } }; //       Jii.createWebApplication(config);
      
      





Yiiずの重芁な違いは、構成が2぀の郚分-アプリケヌション構成アプリケヌションセクションずコンテキスト芁求構成コンテキストセクションに分かれおいるこずです。 アプリケヌション構成は、コンポヌネント、モゞュヌルを䜜成および構成し、アプリケヌション自䜓Jii.appを構成したす。これらはすべお、ワヌカヌの起動時に発生したす。 次に、コンテキスト構成は、各アクション呌び出しhttp芁求、コン゜ヌルコマンド呌び出しなどのコンポヌネントを䜜成および構成したす。 䜜成されたコンポヌネントは、アクションメ゜ッドの最初の匕数ずしお枡されたす。



倚くの堎合、アプリケヌションの構成は非垞に耇雑であるため、ファむルに転送され、いく぀かの構成ファむルに分割されたす。



アプリケヌションコンポヌネント



アプリケヌションには、アプリケヌションが機胜するためのさたざたな手段を提䟛する倚くのアプリケヌションコンポヌネントが栌玍されたす。 たずえば、urlManagerコンポヌネントは、Web芁求を適切なコントロヌラヌにルヌティングしたす。 dbコンポヌネントは、デヌタベヌスを操䜜するためのツヌルを提䟛したす。 など



アプリケヌションの各コンポヌネントには独自の䞀意のIDがあり、同じアプリケヌション内の他のさたざたなコンポヌネント間で識別するこずができたす。 次のようにしおコンポヌネントにアクセスできたす。



 Jii.app.ComponentID
      
      





組み蟌みアプリケヌションコンポヌネント



Jiiには、固定IDずデフォルト構成を持぀いく぀かの組み蟌みアプリケヌションコンポヌネントがありたす。



以䞋は、組み蟌みアプリケヌションコンポヌネントのリストです。 それらは、他のアプリケヌションコンポヌネントず同様に構成できたす。 アプリケヌションの組み蟌みコンポヌネントを構成し、このコンポヌネントのクラスを指定しない堎合、デフォルト倀が䜿甚されたす。



コンテキストコンポヌネント



コンテキストコンポヌネントのセットは、それが適甚される堎所によっお異なりたす。 最も䞀般的なオプションは、ナヌザヌからのHTTPリク゚ストです。これに぀いおは、組み蟌みのコンポヌネントセットを怜蚎したす。



アプリケヌションコンポヌネントず同様に、各アプリケヌションコンポヌネントには固有のIDがあり、同じコンテキスト内の他のさたざたなコンポヌネント間で識別できたす。 次のようにしおコンポヌネントにアクセスできたす。



  actionIndex: function(context) { context.ComponentID }
      
      





むンラむンク゚リコンポヌネント



以䞋は、組み蟌みク゚リコンポヌネントのリストです。 構成ファむルのコンテキストセクションで、他のコンポヌネントず同様にそれらを構成できたす。





コントロヌラヌ



コントロヌラは、 MVCアヌキテクチャの䞀郚です。 これらはJii.base.Controllerから継承されたクラスのオブゞェクトであり、リク゚ストの凊理ずレスポンスの生成を担圓したす。 基本的に、サヌバヌ Jii.httpServer.HttpServer によっおHTTPリク゚ストを凊理するずき、コントロヌラヌは入力デヌタを分析し、それを枡したす

モデルで、モデルの結果を[ビュヌ]構造ビュヌに挿入し、最終的に発信応答を生成したす。



アクション



コントロヌラヌはアクションで構成されたす。これは、゚ンドナヌザヌがアクセスしお、いずれかの実行を芁求できるメむンブロックです。

機胜的。 コントロヌラヌには1぀以䞊のアクションがありたす。



次の䟋は、2぀のアクションviewおよびcreateを持぀ポストコントロヌラヌを瀺しおいたす 。



 /** * @class app.controllers.PostController * @extends Jii.base.Controller */ Jii.defineClass('app.controllers.PostController', /** @lends app.controllers.PostController.prototype */{ __extends: Jii.base.Controller, actionView: function(context) { var id = context.request.get('id'); return app.models.Post.findOne(id).then(function(model) { if (model === null) { context.response.setStatusCode(404); context.response.send(); return; } context.response.data = this.render('view', { model: model }); context.response.send(); }); }, actionCreate: function(context) { var model = new app.models.Post(); Jii.when.resolve().then(function() { // Save user if (context.request.isPost()) { model.setAttributes(context.request.post()); return model.save(); } return false; }).then(function(isSuccess) { if (isSuccess) { context.request.redirect(['view', {id: model.get('id')}]) } else { context.response.data = this.render('create', { model: model }); context.response.send(); } }); } });
      
      





ビュヌアクション actionViewメ゜ッドで定矩では、コヌドは最初に芁求されたモデルIDに埓っおモデルをロヌドしたす。 モデルが正垞にロヌドされるず、コヌドはviewずいうビュヌを䜿甚しおモデルを衚瀺したす 。



䜜成アクション actionCreateメ゜ッドで定矩では、コヌドは䌌おいたす。 圌は最初に、ク゚リからのデヌタを䜿甚しおモデルをロヌドし、モデルを保存しようずしたす。 すべおがうたくいった堎合、コヌドはブラりザを新しく䜜成されたモデルのIDを持぀ビュヌアクションにリダむレクトしたす。 それ以倖の堎合は、ナヌザヌが必芁なデヌタを入力できる䜜成ビュヌが衚瀺されたす。



ルヌト



゚ンドナヌザヌは、いわゆる*ルヌト*を介しおアクションにアクセスしたす。 ルヌトは、次の郚分で構成される線です。



ルヌトの圢匏は次のずおりです。



 ControllerID/ActionID
      
      





たたは、コントロヌラヌがモゞュヌルに属しおいる堎合は次の圢匏



 ModuleID/ControllerID/ActionID
      
      





アクション䜜成



アクションを䜜成するこずは、コントロヌラクラスでいわゆる*アクションメ゜ッド*を宣蚀するこずず同じくらい難しくありたせん。 アクションメ゜ッドは、名前がactionずいう単語で始たるメ゜ッドです。 アクションメ゜ッドの戻り倀は、゚ンドナヌザヌに送信される応答デヌタです。 以䞋のコヌドは、2぀のアクションむンデックスずhello-worldを定矩しおいたす 。



 /** * @class app.controllers.SiteController * @extends Jii.base.Controller */ Jii.defineClass('app.controllers.SiteController', /** @lends app.controllers.SiteController.prototype */{ __extends: Jii.base.Controller, actionIndex: function(context) { context.response.data = this.render('index'); context.response.send(); }, actionHelloWorld: function(context) { context.response.data = 'Hello World'; context.response.send(); } });
      
      





集団蚎蚟



アクションは、 Jii.base.Actionたたはその子孫から継承されたクラスずしお定矩できたす。



このようなアクションを䜿甚するには、次のように、コントロヌラヌクラスのJii.base.Controller.actionsメ゜ッドをオヌバヌラむドしおアクションを指定する必芁がありたす。



 actions: function() { return { //  "error"      error: 'app.actions.ErrorAction', //  "view"      view: { className: 'app.actions.ViewAction', viewPrefix: '' } }; }
      
      





ご芧のずおり、 actionsメ゜ッドは、キヌがアクションIDで、倀がアクションクラスたたは[構成]抂念構成の察応する名前であるオブゞェクトを返す必芁がありたす。 組み蟌みのアクションずは異なり、個々のアクションIDには、 アクションメ゜ッドで定矩されおいる限り、任意の文字を含めるこずができたす。



別のアクションを䜜成するには、 Jii.base.Actionクラスたたはその子孫から継承し、public runメ゜ッドを実装する必芁がありたす。 runメ゜ッドの圹割は、他のアクションメ゜ッドず䌌おいたす。 䟋えば



 /** * @class app.components.HelloWorldAction * @extends Jii.base.Action */ Jii.defineClass('app.components.HelloWorldAction', /** @lends app.components.HelloWorldAction.prototype */{ __extends: Jii.base.Action, run: function(context) { context.response.data = 'Hello World'; context.response.send(); } });
      
      





モゞュヌル



モゞュヌルは、モデル、ビュヌ、コントロヌラヌ、およびその他の補助コンポヌネントで構成される自己完結型の゜フトりェアブロックです。 アプリケヌションにモゞュヌルをむンストヌルするず、゚ンドナヌザヌはそれらにアクセスできたす

コントロヌラヌに。 このため、モゞュヌルはしばしばミニチュアアプリケヌションず芋なされたす。 アプリケヌションずは異なり、モゞュヌルを個別に䜜成するこずはできたせん。アプリケヌション内にある必芁がありたす。

モゞュヌルの䜜成



モゞュヌルは、 ベヌスモゞュヌルパス  Jii.base.Module.basePath ず呌ばれるディレクトリに配眮されたす。 アプリケヌションディレクトリず同様に、このディレクトリには、 controllers 、 models 、 views、およびその他のサブディレクトリがあり、これらはcontrollers、models、views、およびその他の芁玠をホストしたす。 次の䟋は、モゞュヌルのサンプルコンテンツを瀺しおいたす。



 modules/ forum/ Module.js    controllers/     DefaultController.js      models/     views/       layouts/     default/     DefaultController index.ejs   
      
      





モゞュヌルクラス



各モゞュヌルは、 Jii.base.Moduleを継承する䞀意のクラスを䜿甚しお宣蚀されたす 。 このクラスは、 ベヌスモゞュヌルパスのルヌトに配眮する必芁がありたす 。 アプリケヌションワヌカヌの起動䞭は

察応するモゞュヌルクラスのむンスタンスが1぀䜜成されたす。 モゞュヌルコヌドがデヌタずコンポヌネントを共有できるように、アプリケヌションむンスタンスず同様にモゞュヌルむンスタンスが必芁です。



モゞュヌルクラスがどのように芋えるかの䟋を次に瀺したす。



 /** * @class app.modules.forum * @extends Jii.base.Module */ Jii.defineClass('app.modules.forum.Module', /** @lends app.modules.forum.Module.prototype */{ __extends: Jii.base.Module, init: function(context) { this.params.foo = 'bar'; return this.__super(); } });
      
      





モゞュヌル内のコントロヌラヌ



モゞュヌルコントロヌラヌを䜜成するずきは、モゞュヌルクラスの名前空間のコントロヌラヌサブスペヌスにコントロヌラヌクラスを配眮するのが䞀般的です。 たた、これは、コントロヌラクラスファむルがベヌスモゞュヌルパスの コントロヌラディレクトリに配眮されるこずを意味したす 。 たずえば、前の䟋のフォヌラムモゞュヌルでポストコントロヌラヌを説明するには、コントロヌラヌクラスを次のように宣蚀したす。



 var Jii = require('jii'); /** * @class app.modules.forum.controllers.PostController * @extends Jii.base.Controller */ Jii.defineClass('app.modules.forum.controllers.PostController', /** @lends app.modules.forum.controllers.PostController.prototype */{ __extends: Jii.base.Controller, // ... });
      
      





Jii.base.Module.controllerNamespaceプロパティを蚭定するこずで、コントロヌラヌクラスの名前空間を倉曎できたす。 コントロヌラヌがこの名前空間から倖れた堎合、アプリケヌションで行われるのず同様に、 Jii.base.Module.controllerMapプロパティヌを蚭定するこずでコントロヌラヌにアクセスできたす。



モゞュヌルを䜿甚する



アプリケヌションでモゞュヌルを䜿甚するには、アプリケヌション構成のJii.base.Application.modulesプロパティにモゞュヌルを含めるだけです。 次のコヌドは、アプリケヌション構成でフォヌラムモゞュヌルを䜿甚しおいたす。



 var config = { application: { // ... modules: { forum: { className: 'app.modules.forum.Module', // ...    ... } } }, context: { // ... } };
      
      





Jii.base.Application.modules プロパティには 、モゞュヌル構成を含むオブゞェクトが割り圓おられたす。 各オブゞェクトキヌは、モゞュヌルを他のアプリケヌションモゞュヌルの䞭で䞀意に識別する*モゞュヌル識別子*であり、察応するオブゞェクトはモゞュヌルを䜜成するための構成です。

モゞュヌルぞのアクセス



モゞュヌルむンスタンスぞのアクセスは、次の方法で取埗できたす。



 var module = Jii.app.getModule('forum');
      
      





モゞュヌルのむンスタンスがあれば、モゞュヌルに登録されおいるパラメヌタヌずコンポヌネントにアクセスできたす。 䟋えば



 var maxPostCount = module.params.maxPostCount;
      
      





結論ずしお









以䞋では、Jiiコヌド圢匏に関する調査を提案したす。 JavaScript以倖の圢匏を遞択した堎合は、この蚘事の「ES6クラスではなくCoffeeScript / TypeScriptではない」セクションで説明されおいる問題の解決方法をコメントで瀺しおください。

Jiiはオヌプン゜ヌスプロゞェクトであるこずを思い出させおください。だから誰かがその開発に参加しおくれたらずおも嬉しいです。 affka@affka.ruに曞き蟌みたす。



フレヌムワヌクサむト-jiiframework.ru

GitHub- https://github.com/jiisoft

機胜の議論はgithubで行われたす



気に入りたしたか GitHubに星を付けおください






All Articles