= [[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)'':
= $form->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'),
];
}
}