<= [[start|Back to Yii2 Overview]] | Yii2 App Templates ====== Yii Powered ====== YiiPowered is a showcase of websites and projects built with Yii framework. YiiPowered is not really an application template. But it is a non-trivial application, which is available with code at GitHub. [[https://www.yiipowered.com/en/about|About YiiPowered]] ===== Docker Installation ===== - Build the docker image: ''docker build -t yiipowered .''. - Run docker stack: ''docker-compose up''. - Add //yiipowered.test// to your ''hosts'' file (on Windows: Open file ''C:\Windows\System32\Drivers\etc\hosts'' with Notepad running as admin). - There are ''.php-orig'' sample configs in ''config'' directory. Copy all these files to ''.php'' without ''-orig'' and adjust to your needs. - Run ''docker exec -it yiipowered bash''. - Inside this bash termimnal, run: ''composer install && php yii migrate'' to setup the database tables. - Open http://yiipowered.test in your browser. - Register as a new user. - In the docker bash terminal (see above), run ''yii user/assign USERNAME admin'' to assign //admin// role to user //USERNAME//. ===== Users ===== * Simple user administration * Self-registration * User has two stati ===== Behaviors ===== The ''Project'' model has these behaviors: * timestamp * blameable * sluggable * taggable ===== Queues ===== There are queues for ===== ActiveRecord ===== There is a nice example of an attribute evalidation using new and old attribute values: public function rules() { return [ // ... ['status', 'validateStatus'] ]; } public function validateStatus() { if ($this->isAttributeChanged('status', false)) { if ($this->status == self::STATUS_DELETED && $this->getOldAttribute('status') != self::STATUS_DRAFT) { $this->addError('status', Yii::t('project', 'You can only delete a project from a draft.')); } if ($this->getOldAttribute('status') == self::STATUS_DELETED) { $this->addError('status', Yii::t('project', 'You can not restore a deleted project.')); } } } ===== Widgets ===== ==== Bookmarks ==== * Show a little bookmark icon at the top left corner of the project image * Handle bookmark/un-bookmark action via API calls ==== Vote ===== ===== REST API ===== * Introduction page with example links * API is a module within the application 'modules' => [ 'api1' => [ 'class' => \app\modules\api1\Module::class, ], ], * There are extended AR Models in the REST API module, mostly to implement ''Linkable'' or ''fields()'' * Example of ''n:m'' relation: /** * @return \yii\db\ActiveQuery */ public function getUsers() { return $this->hasMany(User::className(), ['id' => 'user_id'])->viaTable('{{%project_user}}', ['project_id' => 'id']); } * Each model has an own controller * The controllers extend a custom API controller which has the method ''getCurrentUser'' * ''index'' action creates and validates a search model, then just returns a DataProvider: class ProjectController extends Controller { public function actionIndex() { $projectSearch = new ProjectSearch(); $projectSearch->load(\Yii::$app->request->get()); if (!$projectSearch->validate()) { throw new BadRequestHttpException('Invalid parameters: ' . json_encode($projectSearch->getErrors())); } return $projectSearch->getDataProvider(); } } ===== RSS Feed ===== The RSS feed is a regular controller action. * Get ''Project'' records: $projects = Project::find() ->with('images', 'users') ->limit(50) ->all(); * Instantiate the Feed object * Set feed metadata * Add projects as feed ''Item'' * Render the feed $feed = new Feed(); $feed->title = 'YiiPowered'; $feed->setWebMaster('sam@rmcreative.ru', 'Alexander Makarov'); // ... foreach ($projects as $project) { $url = Url::to(['project/view', 'id' => $project->id, 'slug' => $project->slug], true); $item = new Item(); $item->title = $project->title; // ... $item->setAuthor('noreply@yiipowered.com', implode(', ', $authors)); $feed->addItem($item); } $feed->render(); ===== Markdown Page ===== The ''api'' docs page is a rendered Markdown page. use yii\helpers\Markdown; // ... class DocsController extends Controller { public function actionIndex() { $docs = file_get_contents(\Yii::getAlias('@app/modules/api1/docs.md')); return $this->render('index', [ 'content' => Markdown::process($docs, 'gfm'), ]); } } ===== Other Features ===== ==== Form Control without Label ==== * add the label as ''placeholder'' attribute * add method ''->label(false)'': field($model, 'title') ->textInput([/* ... */ 'placeholder' => $model->getAttributeLabel('title')]) ->label(false) ?> ==== Model Constants, Labels ==== class User extends ActiveRecord implements IdentityInterface { const STATUS_DELETED = 0; const STATUS_ACTIVE = 10; // ... public function rules() { return [ ['status', 'default', 'value' => self::STATUS_ACTIVE], ['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]], ['status', 'filter', 'filter' => 'intval'], // ... ]; } // Get the label for the current status public function getStatusLabel() { $statuses = self::getStatuses(); return ArrayHelper::getValue($statuses, $this->status); } // Get an array of status labels, indexed by status constants public static function getStatuses() { return [ self::STATUS_DELETED => Yii::t('user', 'Delete'), self::STATUS_ACTIVE => Yii::t('user', 'Active'), ]; } }