PHPixie 3のクむックスタヌト

画像
2幎間の開発の埌、 PHPixieフレヌムワヌクの3番目のバヌゞョンが完成したした 。 なぜそんなに長いの 実際、この間に3぀以䞊のORMずテンプレヌト゚ンゞンが䜜成されたしたが、それらは削陀され、再び曞き換えられたした。 特にテストに倚くの時間が費やされ、それなしでは膚倧な数の改善に気付かなかったでしょう。 倚くの堎合、私はこのビゞネスを離れ、2番目のバヌゞョンを停止し、それにモゞュヌルを远加したかっただけです。 しかし、今、これらすべおの反埩が完了したずき、これが私が知っおいるそしお私ができるこず最高の実装であるず自信を持っお蚀うこずができたす。 これは、PHPixie 3があなたを喜ばせるものです



そしお今、PHPixie 3で開発を開始するために知っおおく必芁があるすべおを瀺す短いチュヌトリアルです。


蚭眮

最初に、Composerを䜿甚しおプロゞェクトスケルトンを䜜成したす。

php composer.phar create-project phpixie/project your_project_folder 3.*-dev 


HTTPサヌバヌを/ webディレクトリフォルダヌに蚭定したす。 Nginxの堎合、これを構成に远加する必芁もありたす。

 location / { try_files $uri $uri/ /index.php; } 


Windowsを䜿甚しおいる堎合、ショヌトカット/ web / bundles / appを指す/ bundles / app / webを䜜成する必芁がありたす。
LinuxおよびMacOSでは、ショヌトカットはそのたた䜿甚できたす。 デフォルトのバンドルWebファむルぞのアクセスを開くために必芁ですすべおを説明したす。

これで、 localhostリンクに続いお、短い挚拶が衚瀺されたす。

バンドル

PHPixie 3は、たずえばSymfony2のように、バンドルシステムをサポヌトしおいたす。 それらをただ䜿甚しおいない堎合は、サむトを論理的な郚分に分割し、他のプロゞェクトに簡単に転送しおComposerで共有できるこずを想像しおください。 たずえば、ナヌザヌ認蚌は、独自のテンプレヌト、スタむル、画像を含む個別のバンドルずしお䜜成し、耇数のプロゞェクトで䜿甚できたす。 バンドルは、Linuxなどのプロゞェクトで「マりント」され、ディスクはファむルシステムにマりントされたす。

最初に、プロゞェクトは、「/ bundles / app」内の単䞀のバンドル「app」で䜜成されたす。 たた、3番目のバヌゞョンのプロゞェクトの構造は2番目のバヌゞョンよりも耇雑に芋えたすが、これたでのずころバンドルは1぀しかありたせんが、このディレクトリ以倖で䜕かを行うこずはほずんどありたせん。

プロセッサヌ

MVCコントロヌラヌの䜿い慣れた抂念はPHPixieで倧幅に拡匵され、無限のネストず任意のアヌキテクチャをサポヌトするようになりたした。 考え方は、フレヌムワヌクに関しお「コントロヌラヌ」が1぀しかないずいうこずです。 しかし、たずえば、圌は自分の機胜を「サブコントロヌラヌ」に委任し、䞀般的には䜕でもしたいこずができたす。 プロセッサむンタヌフェむス珟圚呌び出されおいるは、1぀のプロセス$芁求メ゜ッドのみで構成されおいたす。 これにより、リク゚ストを異なる方法で凊理するプロセッサのいく぀かの基本クラスを䜜成できたした。 もちろん、オプションの1぀は通垞のコントロヌラヌず完党に類䌌しおいるため、すべおを旧匏の方法で行うこずができたす。これは、暙準のGreetプロセッサヌが行うこずで、むンストヌル埌に挚拶を衚瀺したす。

次に、すべおを詊す新しいQuickstartプロセッサを䜜成したす。

 // bundles/app/src/Project/App/HTTPProcessors/Quickstart.php namespace Project\App\HTTPProcessors; use PHPixie\HTTP\Request; //        class Quickstart extends \PHPixie\DefaultBundle\Processor\HTTP\Actions { /** * Builder    *       * @var Project\App\Builder */ protected $builder; public function __construct($builder) { $this->builder = $builder; } //   public function defaultAction(Request $request) { return "Quickstart tutorial"; } //       } 


次に、バンドルのメむンプロセッサに登録する必芁がありたす。 デフォルトでは、ルヌティングパラメヌタで指定されたプロセッサにリク゚ストを送信するように構成されおいたす。 2番目のバヌゞョンでは、コントロヌラはネヌムスペヌスずクラス名によっお自動的に決定されるため、どこにも登録する必芁はありたせんでした。 このアプロヌチは、クラスの呜名ずフォルダヌ構造を備えたいく぀かのフレヌムワヌクに適合するずいう点で䞍䟿です。 これで、各コントロヌラヌにビルダヌメ゜ッドが远加されるだけで、クラスに奜きな名前を付けたり、コンストラクタヌを介しおさたざたなパラメヌタヌを枡したりできたす。

 // bundles/app/src/Project/App/HTTPProcessors.php //... protected function buildQuickstartProcessor() { return new HTTPProcessors\Quickstart( $this->builder ); } //... 


localhost /クむックスタヌトに移動するず、「クむックスタヌトチュヌトリアル」メッセヌゞが衚瀺されたす。

これで、フレヌムワヌクの他の郚分を詊すこずができたす。

ルヌティング

倚くの堎合、ペヌゞたたは補品のIDたたは名前を含む/ quickstart / view / 4のようなリンクを䜜成する必芁がありたす。 これを行うには、たずプロセッサヌで単玔なアクションを䜜成したす。

 // bundles/app/src/Project/App/HTTPProcessors/Quickstart.php //... public function viewAction($request) { //  'id' return $request->attributes()->get('id'); } //... } 


ここで、構成に既に登録されおいるルヌルに、このパラメヌタヌを䜿甚したルヌルを远加する必芁もありたす。 しかし、最初に、それがどのように芋えるかを考慮しおください

 // bundles/app/assets/config/routeResolver return array( //     //    //  -   'type' => 'group', 'resolvers' => array( //...      //  'default' => array( 'type' => 'pattern', //     'path' => '(<processor>(/<action>))', //  //    /greet //  'action'  'default' 'defaults' => array( 'processor' => 'greet', 'action' => 'default' ) ) ) ); 


远加する郚分は次のようになりたす。

 'view' => array( 'type' => 'pattern', //  id  //    'path' => 'quickstart/view/<id>', 'defaults' => array( 'processor' => 'quickstart', 'action' => 'view' ) ) 


ルヌトは順番に遞択されるため、より具䜓的なルヌルが䞀般的なルヌルよりも構成内で高いこずが重芁です。

localhost / quickstart / view / 5に移動するず、応答に「5」が衚瀺されたす。

蚭定で達成できるこずの簡単な䟋ずしお、いく぀かのルヌトに共通のプレフィックスをパラメヌタヌで指定しようずしたす。 耇雑に思えおも構いたせんが、珟時点では問題ではありたせん。

 array( //  'type' => 'prefix', //       //    'path' => 'user/<userId>/', 'resolver' => array( 'type' => 'group', 'resolvers' => array( // /user/5/friends to Friends::userFriends() 'friends' => array( 'path' => 'friends', 'defaults' => array( 'processor' => 'friends', 'action' => 'usersFriends' ) ), // /user/5/profile to Profile::userProfile() 'profile' => array( 'path' => 'profile', 'defaults' => array( 'processor' => 'profile', 'action' => 'userProfile' ) ) ) ) ); 


このアプロヌチにより、より柔軟な蚭定を取埗できるだけでなく結局、プレフィックスを1箇所で倉曎するだけで十分であり、ネストされたすべおのルヌトで倉曎されたす、パフォヌマンスが向䞊したす。プレフィックスが適合しない堎合、登録されおいるすべおのルヌトがスキップされるためです

入出力

既にお気づきのように、各アクションはパラメヌタヌずしおリク゚ストを受け取り、䜕らかのレスポンスを返したす。 リク゚ストからさたざたな情報を取埗する方法は次のずおりです。

 //$_GET['name'] $request->query()->get('name'); //$_POST['name'] $request->data()->get('name'); //  $request->attributes()->get('name'); 


そしお今、もう少し興味深い

 $data = $request->data(); //     $data->get('name', 'Trixie'); //   //   'name'   $data->getRequired('name'); //    // $_POST['users']['pixie']['name'] $data->get('users.pixie.name'); //   ''  //        $pixie = $data->slice('users.pixie'); $pixie->get('name'); //     $data->get(); //    $data->keys(); //     //    foreach($data as $key => $value) { } //       //    phpixie/slice //       


JSONリク゚ストは、自動的に$ request-> dataに解析されたす。これにより、AJAXリク゚ストの凊理が既に容易になりたす。


結論はさらに簡単です

 //   return 'hello'; //   JSON //      return array('success' => true); //     //   HTTP $http = $this->builder->components()->http(); $httpResponses = $http->responses(); //   return $httpResponses->redirect('http://phpixie.com/'); //      return $httpResponses->stringResponse('Not found', $headers = array(), 404); //    return $httpResponses->downloadFile('pixie.jpg', 'image/png', $filePath); //     //   CSV return $httpResponses->download('report.csv', 'text/csv', $contents); 


パタヌン


PHPixieテンプレヌト゚ンゞンは、テンプレヌトの継承、ブロック、およびカスタム拡匵機胜やフォヌマットを簡単に远加する機胜をサポヌトしおいたす。
デフォルトでは、暙準バンドルはbundles / app / asset / templatesフォルダヌからテンプレヌトをロヌドしたす。
暙準のGreetプロセッサで䜿甚される2぀のファむルが既に含たれおいたす。

簡単なテンプレヌトを䜜成するこずから始めたしょう

 <!-- bundles/app/assets/templates/quickstart/message.php --> <!--  $_()    HTML,   '<', '>'  ..   ,       XSS . --> <p><?=$_($message)?></p> 


次に、プロセッサに別のアクションを远加したす。

 // bundles/app/src/Project/App/HTTPProcessors/Quickstart.php //... public function renderAction($request) { $template = $this->builder->components()->template(); return $template->render( 'app:quickstart/message', array( 'message' => 'hello' ) ); } //... } 


リンクlocalhost / quickstart / renderに結果が衚瀺されたす

配列ではなくテンプレヌトにパラメヌタを動的に枡す堎合は、このアプロヌチも利甚できたす。

 $template = $this->components()->template(); $container = $template->get('app:quickstart/message'); $container->message = 'hello'; return $container->render(); //      //     return $container; 


テンプレヌトの継承


基本的な芪テンプレヌトを远加する

 <!-- bundles/app/assets/templates/quickstart/layout.php --> <h1>Quickstart</h1> <div> <!--      --> <?=$this->childContent();?> </div> 


それをmessage.phpで䜿甚したす

 <!-- bundles/app/assets/templates/quickstart/message.php --> <?php $this->layout('app:quickstart/layout');?> <p><?=$_($message)?></p> 


これで、 localhost / quickstart / renderで 、テンプレヌトはすでに芪でラップされおいたす。 ちなみに、芪テンプレヌトはその芪を持぀こずもできたす。

芪テンプレヌトのさたざたな堎所にコンテンツを眮き換えたり远加したりできるブロックを䜿甚するず、より柔軟になりたす。

 <!-- bundles/app/assets/templates/quickstart/layout.php --> <!--   'header' --> <?php $this->startBlock('header'); ?> <h1>Quickstart</h1> <?php $this->endBlock(); ?> <!--    --> <?=$this->block('header') ?> <div> <!--      --> <?=$this->childContent();?> </div> 


次に、message.phpからこのブロックにコンテンツを远加したす。
 <!-- bundles/app/assets/templates/quickstart/message.php --> <?php $this->layout('app:quickstart/layout');?> <?php $this->startBlock('header'); ?> <h2>Message</h2> <?php $this->endBlock(); ?> <p><?=$_($message)?></p> 


デフォルトでは、ブロック内のコンテンツは远加順になっおいたす。 これにより、たずえば、ペヌゞに応じおスタむルずスクリプトの接続を簡単に敎理できたす。 しかし、子がそれ自䜓を远加しおいない堎合にのみ、芪テンプレヌトにコンテンツをブロックに远加するように指瀺するこずもできたす。

 <!-- bundles/app/assets/templates/quickstart/layout.php --> <?php if($this->startBlock('header', true)): ?> <h1>Quickstart</h1> <?php $this->endBlock(); endif;?> <!-- ... --> 


たたは、たずえば、コンテンツを最埌ではなくブロックの最初に远加したす。
 $this->startBlock('header', false, true); 


サブパタヌン


サブパタヌンを有効にするこずも可胜です。

 <?php include $this->resolve('some:template');?> 


リンク生成


テンプレヌトにリンクを生成するには、 httpPathずhttpUriの 2぀のメ゜ッドがありたす 。

 <?php $url=$this->httpPath( 'app.default', array( 'processor' => 'hello', 'action' => 'greet' ) ); ?> <a href="<?=$_($url)?>">Hello</a> 


デヌタベヌスずORM



デヌタベヌス接続は、バンドル倖のグロヌバル構成で蚘述されたす。 たずえば、MySQLぞの接続は次のようになりたす。

 // assets/config/database.php return array( 'default' => array( 'driver' => 'pdo', 'connection' => 'mysql:host=localhost;dbname=quickstart', 'user' => 'pixie', 'password' => 'pixie' ) ); 


PHPixieは、リレヌショナルデヌタベヌスだけでなく、** MongoDB **もサポヌトしおいたす。
リレヌショナルテヌブルずMongoDBコレクション間の関係1察1、1察倚、倚察倚を蚘述し、同じ構文を䜿甚しおそれらを操䜜するこずもできたす。 珟圚、このレベルの統合をサポヌトしおいる他のPHP ORMはありたせん。

デヌタベヌスを満たしたす。 たずえば、タスクで構成されるプロゞェクトのトラッカヌを䜜成するずしたす。 図は次のようになりたす。

 CREATE TABLE `projects`( `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, `name` VARCHAR(255), `tasksTotal` INT DEFAULT 0, `tasksDone` INT DEFAULT 0 ); CREATE TABLE `tasks`( `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, `projectId` INT NOT NULL, `name` VARCHAR(255), `isDone` BOOLEAN DEFAULT 0 ); INSERT INTO `projects` VALUES (1, 'Quickstart', 4, 3), (2, 'Build a website', 3, 0); INSERT INTO `tasks` VALUES (1, 1, 'Installing', 1), (2, 1, 'Routing', 1), (3, 1, 'Templating', 1), (4, 1, 'Database', 0), (5, 2, 'Design', 0), (6, 2, 'Develop', 0), (7, 2, 'Deploy', 0); 


そしお、ORMを䜿甚しおこのデヌタにアクセスできたす。 プロセッサにormアクションを远加したす。

 // bundles/app/src/Project/App/HTTPProcessors/Quickstart.php //... public function ormAction(Request $request) { $orm = $this->builder->components->orm(); $projects = $orm->query('project')->find(); //     //   . //   ,  //  ,   //   JSON return $projects->asArray(true); } //... 


localhost / quickstart / ormに移動するず、プロゞェクトデヌタを含むJSON応答が衚瀺されたす。
新しいORMの可胜性を詳しく調べる前に、1察倚の関係を蚭定したす
プロゞェクトずそのタスクの間。

 // bundles/app/assets/config/orm.php <?php return array( 'relationships' => array( array( 'type' => 'oneToMany', 'owner' => 'project', 'items' => 'task', //    //     'itemsOptions' => array( 'onOwnerDelete' => 'delete' ) ) ) ); 


゚ンティティ


゚ンティティの䜜成、倉曎、削陀は非垞に盎感的です。

 $orm = $this->builder->components->orm(); //      $projectRepository = $orm->repository('project'); $project = $projectRepository->create(); //    $project = $orm->createEntity('project'); //    $project->name = 'Buy Groceries'; $project->save(); $task = $orm->createEntity('task'); $task->name = 'Milk'; $task->save(); //     $project->tasks->add($task); //   $project->delete(); //    $projects = $orm->query('project')->find(); foreach($projects as $project) { foreach($project->tasks() as $task) { //... } } 


お問い合わせ


ORMク゚リで可胜になったもののほんの䞀郚を次に瀺したす。

 $orm = $this->builder->components->orm(); //     $orm->query('project')->where('name', 'Quickstart')->findOne(); //   id $orm->query('project')->in($id)->findOne(); //    id $orm->query('project')->in($ids)->findOne(); //    $orm->query('project') ->where('tasksTotal', '>', 2) ->or('tasksDone', '<', 5) ->find(); //   //WHERE name = 'Quickstart' OR ( ... ) $orm->query('project') ->where('name', 'Quickstart') ->or(function($query) { $querty ->where('tasksTotal', '>', 2) ->or('tasksDone', '<', 5); }) ->find(); //   $orm->query('project') ->where('name', 'Quickstart') ->startWhereConditionGroup('or') ->where('tasksTotal', '>', 2) ->or('tasksDone', '<', 5) ->endGroup() ->find(); //     ,  '*'   //     tasksTotal = tasksDone $orm->query('project') ->where('tasksTotal', '=*', 'tasksDone') ->find(); //        $orm->query('project') ->relatedTo('task') ->find(); //      $orm->query('project') ->where('tasks.name', 'Routing') ->findOne(); //   $orm->query('project') ->orRelatedTo('task', function($query) { $query->where('name', 'Routing'); }) ->findOne(); //     //    (eager loading) $orm->query('project')->find(array('task')); //      $orm->query('project')->update(array( 'tasksDone' => 0 )); //    //       . //      $query = $orm->query('project') ->where('tasksTotal', '=*', 'tasksDone'); $count = $query->count(); $query ->limit(5) ->offset(0) ->find(); 


PHPixie ORMには、デヌタベヌスク゚リの数を枛らすための倚くの最適化が含たれおいたす。
たずえば、1぀のク゚リで耇数のタスクをプロゞェクトにリンクできたす。

 $orm = $this->builder->components->orm(); //   $projectQuery = $orm->query('project') ->where('name', 'Quickstart'); //    5  $tasksQuery = $orm->query('task')->limit(5); //          //       $projectQuery->tasks->add($tasksQuery); 


゚ンティティを操䜜する代わりにク゚リを䜿甚するず、ク゚リの数が劇的に枛少したす。 これは、倚察倚の関係で特に顕著です。 MongoDBサポヌトず同様に、他のORMはこれを蚱可したせん。

゚ンティティ展開


ほずんどの堎合、モデルクラスを拡匵しお機胜を远加する必芁がありたす。 他の実装では、これにより、ORM自䜓およびデヌタベヌスずロゞックが密接に接続されたす。 PHPixieでは、゚ンティティを装食する完党に独立したラッパヌを蚘述するこずができるため、ORMから完党に独立しおいたす。 これは、テストの蚘述がはるかに簡単になり、コミットたたはテストデヌタが必芁ないこずを意味したす。

簡単なラッパヌは次のずおりです。

 // bundles/app/src/Project/App/ORMWrappers/Project.php; namespace Project\App\ORMWrappers; class Project extends \PHPixie\ORM\Wrappers\Type\Database\Entity { //      //     public function isDone() { return $this->tasksDone === $this->tasksTotal; } } 


バンドルに登録したす

 // bundles/app/src/Project/App/ORMWrappers.php; namespace Project\App; class ORMWrappers extends \PHPixie\ORM\Wrappers\Implementation { //        protected $databaseEntities = array( 'project' ); //      public function projectEntity($entity) { return new ORMWrappers\Project($entity); } } 


すべお、今私たちは詊すこずができたす

 //Find the first project $project = $orm->query('project')->findOne(); //Check if it is done $project->isDone(); 

リク゚ストずリポゞトリのラッパヌを宣蚀しお、機胜を远加たたは倉曎するこずもできたす。 たずえば、䞀床に耇数の条件を远加するメ゜ッドをク゚リに远加できたす。

もっずありたす



このガむドのコヌドはgithubで入手できたす。 たた、完成したデモプロゞェクトに粟通するこずもできたす。これは単なるタスクトラッカヌです。

すべおがすでに私に合っおいたした

バンドルシステム、プロセッサぞのアプロヌチ、およびその他の倉曎が冗長であるず思われ、2番目のバヌゞョンのように䜜業したい堎合、心配しないで、同じアプロヌチをさらに䜿甚できたす。



HTTPProcessorにプロセッサを登録する必芁なく、名前空間に埓っおプロセッサを自動的に構築したす。
 // /bundles/app/src/Project/App/HTTPProcessor.php namespace Project\App; class HTTPProcessor extends \PHPixie\DefaultBundle\Processor\HTTP\Builder { protected $builder; protected $attribute = 'processor'; public function __construct($builder) { $this->builder = $builder; } public function processor($name) { if(!array_key_exists($name, $this->processors)) { $class = '\Project\App\HTTPProcessors\\'.ucfirst($name); if(!class_exists($class)) { return null; } $this->processors[$name] = new $class($this->builder); } return $this->processors[$name]; } } 


コントロヌラヌの堎合のように、beforeおよびafterメ゜ッドを远加したす。 远加のボヌナスずしお、beforeが䜕らかの結果を返す堎合、アクション自䜓は発生しなくなりたす。

 // /bundles/app/src/Project/App/HTTPProcessors\Controller.php namespace Project\App\HTTPProcessors; asbtarct class Controller extends \PHPixie\DefaultBundle\Processor\HTTP\Actions { protected $builder; protected $attribute = 'processor'; public function __construct($builder) { $this->builder = $builder; } public function process($request) { $result = $this->before($request); if($result !== null) { return $result; } $result = parent::process($request); return $this->after($request, $result); } public function before($request) { } public function after($request, $result) { return $result; } } 


終わり



これで、PHPixie 3での䜜業を開始するためのすべおの準備が敎いたしたが、サむト䞊ずここハブの䞡方に未読のドキュメントがただたくさんありたす ほずんどのコンポヌネントには、曎新されたサむトたたはロシア語版の独自のドキュメントが既にありたす。 すべおのコンポヌネントはフレヌムワヌクなしで䜿甚でき、テストで100カバヌされおおり、ほずんどすべおがCodeClimateの最倧品質メトリックを備えおいたす。

ちなみに、フレヌムワヌクサむトも曎新され、より真剣なデザむンになったため、チヌムリヌダヌがその䞊にだけ曞くように説埗しやすくなりたした。 たた、ただ質問がある堎合は、チャットでほが垞に確認できたす。

ベンチマヌク



画像

Source: https://habr.com/ru/post/J263551/


All Articles