Yii開発者用自転車セット

著者から


著者がハブに投稿を書くとき、彼は読者にトピックに関する最も完全で有用な情報を提供しようとします。 しかし、正しい答えや解決策がなければ? そして、この投稿は心の糧に過ぎず、価値は集合的な心にあります。



私は遠くから行った、私は主張しませんが、あなたの理解とサポートを願っています。 特にYiiフレームワークに関する開発者の日常的な問題の解決策について言えば、私たちのチームに解決策を提案します。 同時に、彼らはコミュニティのアイデアに興味を持っています。 まあ、あなたの脳をかなり粉にします。

進む





ファッショナブルな若者、特徴



モデルがN()メソッドを実行し、同時にtrue / falseを返す状況がありますが、これは問題ありません。 しかし、通常、ユーザーはエラーが発生した理由と、エラーの詳細を把握する必要があります。 ロジックがシンプルで完璧主義者ではない場合は良いことです-少しのビジネスロジックをコントローラーに入れて、詳細なエラーを表示しますが、私たちはそうではありません!

メソッドが最大20種類のエラーを引き起こす可能性がある場合、Vasyaがパイを購入したりコメントを投稿したりできない理由

Yiiにはモデル用の優れたvalidate()メソッドがありますが、モデル自体のデータの検証と確実に結びついており、モデルに直接関係しない抽象メソッドを作成した場合には適していません。



どうする?

そしてそう
trait CustomError { private $_errorMessages = []; /** * Use in method : return $this->setCustomErrorMessage(message); * * @param array $errorMessages * @return false */ public function setCustomErrorMessage($errorMessages) { if(!is_array($errorMessages)) $errorMessages = [$errorMessages]; $this->_errorMessages = $errorMessages; return false; } /** * @param string $errorMessage */ public function addCustomErrorMessage($errorMessage) { $this->_errorMessages[] = $errorMessage; } /** * @return array */ public function getCustomErrorMessages() { return $this->_errorMessages; } /** * @return mixed */ public function getCustomErrorMessageFirst() { return reset($this->_errorMessages); } /** * @return void */ public function clearCustomErrorMessages() { $this->_errorMessages = []; return; } }
      
      







5セントのようなシンプルなコードですが、非常に簡単です。 例:

 class Blog extends CActiveRecord { use CustomError; //    public function checkPrivacyCreate() { // ,      ... $parent_post = $this->getPost($this->parent_post_id); if (empty($parent_post)) return $this->setCustomErrorMessage(Yii::t('blog', 'post_not_found')); ... return true; } } //    public function actionAddPost() { .... if (!$model->addPost()) Tools::jsonError($model->getCustomErrorMessages()); //   JSON   ... }
      
      







私たちは何を逃げ出しますか? intからstringへのビネグレットの可能な答えではなく、bool値を返す適切なメソッドを取得します。 コードの重複なし、純粋な乾燥。 いいえ、しかし、私は賢い人々がよりクリーンなオプションを思い付くと確信しています、まあ、それは素晴らしいことです!



トレンディなもの、コンソールだけ、ハードコアのみ!



Smartprogressでは、継続的な統合を使用し、各コミットはローカルテスト、開発サーバーでのテスト、本番環境でのテスト、ユーザーでのテストなど、いくつかの段階を経ます



それは何ですか、そして、はい、すでに6つのデータベースがあります。 各ステージに2つ、作業とテスト。 私たちが移住を祈っていると言うことは、何も言わないことです。 しかし、残念なことに、Yii移行チームは、このような動物園の基盤に適したソリューションを提供していません。 はい、キーを使用して目的の接続を指定できますが、毎回長く退屈な怠azineのためにそれを行います(怠inessは、男性の連帯よりもプログラマの間で同情を引き起こす感覚です。アート)



ああ、そして私を引っ張った、すべての愛、バングバムと...

決定
 <?php Yii::import('system.cli.commands.MigrateCommand'); class MigratecomboCommand extends MigrateCommand { public $connections = array('db', 'db_test'); //       public function actionUp($args) { if(($migrations=$this->getNewMigrations())===array()) { echo "No new migration found. Your system is up-to-date.\n"; return 0; } $total=count($migrations); $step=isset($args[0]) ? (int)$args[0] : 0; if($step>0) $migrations=array_slice($migrations,0,$step); $n=count($migrations); if($n===$total) echo "Total $n new ".($n===1 ? 'migration':'migrations')." to be applied:\n"; else echo "Total $n out of $total new ".($total===1 ? 'migration':'migrations')." to be applied:\n"; foreach($migrations as $migration) echo " $migration\n"; echo "\n"; if($this->confirm('Apply the above '.($n===1 ? 'migration':'migrations')."?")) { foreach($migrations as $migration) { foreach($this->connections as $connectionId) { // !!!   ,       $this->connectionID = $connectionId; if($this->migrateUp($migration)===false) { echo "\nMigration failed. All later migrations are canceled.\n"; return 2; } } } echo "\nMigrated up successfully.\n"; } } public function actionDown($args) { $step=isset($args[0]) ? (int)$args[0] : 1; if($step<1) { echo "Error: The step parameter must be greater than 0.\n"; return 1; } if(($migrations=$this->getMigrationHistory($step))===array()) { echo "No migration has been done before.\n"; return 0; } $migrations=array_keys($migrations); $n=count($migrations); echo "Total $n ".($n===1 ? 'migration':'migrations')." to be reverted:\n"; foreach($migrations as $migration) echo " $migration\n"; echo "\n"; if($this->confirm('Revert the above '.($n===1 ? 'migration':'migrations')."?")) { foreach($migrations as $migration) { foreach($this->connections as $connectionId) { $this->connectionID = $connectionId; if($this->migrateDown($migration)===false) { echo "\nMigration failed. All later migrations are canceled.\n"; return 2; } } } echo "\nMigrated down successfully.\n"; } } private $_db; protected function getDbConnection() { if(($this->_db=Yii::app()->getComponent($this->connectionID)) instanceof CDbConnection) return $this->_db; echo "Error: CMigrationCommand.connectionID '{$this->connectionID}' is invalid. Please make sure it refers to the ID of a CDbConnection application component.\n"; exit(1); } }
      
      







Up / Downメソッドでは、すべての接続をループ処理し、各データベースに順番に移行を適用します。

基本的な解決策は不可能です。 私の意見では、どこか覗かれても、悔い改めます。 しかし、今では、1つのコマンドで十分です。これは、金曜日の夕方でも「抽象的」な状態で実行できます。

 yiic migratecombo up(/down/create/...)
      
      





また、移行は、$ connections変数で指定されたすべての既存のデータベースに適用されます。



しかし、微妙な違いがあります。 標準のYiiメソッドを使用せずに、データベースを介して直接、なんとなくmigrateな方法で移行することにした場合、次のようになります。

 class m140317_060002_fill_search_column extends CDbMigration { public function up() { $goals = $this->getDbConnection() //  ,  Yii::app()->db->createCommand...   $this->getDbConnection() ->createCommand("SELECT id, `name` FROM goals WHERE `moderated` != 'deleted'") ->queryAll();
      
      







テスト、ユニット、機能、ウサギ



私が試験の専門家であると言うことは、半年前にクリミアがロシアの一部になると宣言するようなものです。

しかし、私は長い間それをしてきました、そして、私は黙っておくことができないので、私は前もって謝罪します。



機能テストで最初に出会ったのは、サイトのほとんどすべての機能が許可されたユーザーのみが利用できることであり、ご存じのとおり、各テストの環境は初期状態です。

決めた
 class WebTestCase extends CWebTestCase { public $loginRequired = false; protected function setUp() { parent::setUp(); $this->setBrowser('*firefox'); $this->setBrowserUrl(TEST_BASE_URL); $this->prepareTestSession(); if($this->loginRequired) { $this->login(); } } }
      
      







ログインメソッドのコードは提供しません。すべてが純粋に個別のものです。 これで、テストクラスでloginRequired = trueを指定するだけで十分で、テストは承認されたユーザーによって実行されます。



私のような若くて経験の浅いテスターに​​助言することはできません。架空の、しかし最も現実的なデータを生成するための素晴らしいFakerツールです。 DataProviderに不可欠なもの

小さな例
 class MyTest extends CDbTestCase { public function newUserProvider() { //  3    $faker = \Faker\Factory::create('ru_RU'); $array = array(); for($i=0; $i<3; $i++) { $array[$i]['user']['name'] = $faker->name; $array[$i]['user']['address'] = $faker->address; $array[$i]['user']['country'] = $faker->country; } return $array; } /** * @param $user * @dataProvider newUserProvider */ public function testCreate($user) //    3        { $model = new User('signup'); $model->name = $user['name']; ... $model->save() } }
      
      









もちろん、これらは私たちがSmartprogress開発の長い期間にわたって生み出したトリックやパンのすべてではありません。

さらに多くの解決策と改善点がありますが、読者の皆さん、このトピックに関する私の考えとベストプラクティスを共有していただきたいと思います。 確かにすべての開発者には、さまざまなタスクのためのヘルパーと既製のソリューションの本当の動物園があります。

それらを私とhabrahabrコミュニティ全体と共有してください。



All Articles