Closed anvarulugov closed 9 years ago
Please show full model. Maybe you have to provide rules for multilingual fields. Also show controller findModel action
Hello, thank you for your answer. I reconfigured the rules now it is working on create, but not on update, and when the update form is opened the fields are empty. Here are my models and the controller: Posts model:
<?php
namespace backend\modules\admin\modules\posts\models;
use Yii;
use yii\helpers\ArrayHelper;
use yii\behaviors\SluggableBehavior;
use yii\behaviors\TimestampBehavior;
use omgdef\multilingual\MultilingualBehavior;
use omgdef\multilingual\MultilingualQuery;
use common\models\User;
//use creocoder\taggable\TaggableBehavior;
use yii\db\Expression;
use yii\helpers\Inflector;
Inflector::$transliterator = 'Uzbek-Latin/BGN; NFKD';
/**
* This is the model class for table "posts".
*
* @property string $ID
* @property string $post_parent
* @property string $post_name
* @property string $post_author
* @property string $post_date
* @property string $post_title
* @property string $post_content
* @property string $post_password
* @property string $post_modified
* @property string $post_status
* @property string $post_type
* @property string $comment_status
* @property string $comment_count
* @property Postmeta[] $postmetas
* @property Postcategories $postTerms
*/
class Posts extends \yii\db\ActiveRecord
{
public $post_terms;
public $post_tags;
public $post_metas;
/**
* @inheritdoc
*/
public static function tableName()
{
return 'posts';
}
public function behaviors()
{
return [
[
'class' => SluggableBehavior::className(),
'attribute' => 'post_title',
'slugAttribute' => 'post_name',
'ensureUnique'=>true,
],
[
'class' => TimestampBehavior::className(),
'createdAtAttribute' => 'post_date',
'updatedAtAttribute' => 'post_modified',
'value' => new Expression('NOW()'),
],
'ml' => [
'class' => MultilingualBehavior::className(),
'languages' => [
'uz' => 'Uzbek',
'ru' => 'Russian',
'en' => 'English',
],
'languageField' => 'post_lang',
//'localizedPrefix' => '',
'requireTranslations' => true,
'dynamicLangClass' => false,
'langClassName' => PostsLang::className(), // or namespace/for/a/class/PostLang
'defaultLanguage' => 'ru',
'langForeignKey' => 'post_id',
'tableName' => "{{%posts_lang}}",
'attributes' => [
'post_title', 'post_content',
]
],
// [
// 'class' => Taggable::className(),
// 'attribute' => 'post_tags',
// 'name' => 'term_name',
// //'relation' => 'tags',
// 'frequency' => 'term_frequency',
// ],
// [
// 'class' => TaggableBehavior::className(),
// 'tagValuesAsArray' => false,
// 'tagRelation' => 'terms',
// 'tagValueAttribute' => 'term_name',
// 'tagFrequencyAttribute' => 'term_frequency',
// ],
];
}
/**
* @inheritdoc
*/
public function rules()
{
return [
[['post_parent', 'post_author', 'comment_count'], 'integer'],
[['post_author'], 'required'],
[['post_date', 'post_modified', 'post_terms', 'post_tags', 'post_metas'], 'safe'],
[['post_title', 'post_content'], 'string'],
[['post_name'], 'string', 'max' => 255],
[['post_password'], 'string', 'max' => 200],
[['post_status', 'post_type', 'comment_status'], 'string', 'max' => 20],
[['post_name'], 'unique']
];
}
/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'ID' => Yii::t('app', 'ID'),
'post_parent' => Yii::t('app', 'Parent'),
'post_name' => Yii::t('app', 'Slug'),
'post_author' => Yii::t('app', 'Author'),
'post_date' => Yii::t('app', 'Publish Date'),
'post_title' => Yii::t('app', 'Title'),
'post_content' => Yii::t('app', 'Content'),
'post_password' => Yii::t('app', 'Password'),
'post_modified' => Yii::t('app', 'Modified Date'),
'post_status' => Yii::t('app', 'Status'),
'post_type' => Yii::t('app', 'Type'),
'comment_status' => Yii::t('app', 'Discussion'),
'comment_count' => Yii::t('app', 'Comment Count'),
];
}
public static function find()
{
return new MultilingualQuery(get_called_class());
}
public function getStatus() {
$status = [
['key' => 'default', 'value' => Yii::t('app','Default')],
['key' => 'public', 'value' => Yii::t('app','Public')],
['key' => 'private', 'value' => Yii::t('app','Private')],
['key' => 'draft', 'value' => Yii::t('app','Draft')],
];
$status = ArrayHelper::map($status,'key','value');
return $status;
}
public function getCommentstatus() {
$commentstatus = [
['key' => 'default', 'value' => Yii::t('app','Default')],
['key' => 'users', 'value' => Yii::t('app','Users')],
['key' => 'none', 'value' => Yii::t('app','None')],
['key' => 'any', 'value' => Yii::t('app','Any')],
];
$commentstatus = ArrayHelper::map($commentstatus,'key','value');
return $commentstatus;
}
public function transactions()
{
return [
self::SCENARIO_DEFAULT => self::OP_ALL,
];
}
public function getAuthor() {
return $this->hasOne(User::className(),['id'=>'post_author']);
}
/**
* Metas relation, magic funciton to generate public property
* @return \yii\db\ActiveQuery
*/
public function getMetas()
{
return $this->hasMany(Postmeta::className(), ['post_id' => 'ID']);
}
/**
* Terms relation, magic funciton to generate public property
* @return \yii\db\ActiveQuery
*/
public function getTerms()
{
return $this->hasMany(Terms::className(), ['term_id' => 'term_id'])
->viaTable(TermRelations::tableName(), ['object_id' => 'ID'])
->andWhere(['term_type'=>'category']);
}
/**
* Tags relation, magic funciton to generate public property
* @return \yii\db\ActiveQuery
*/
public function getTags()
{
return $this->hasMany(Terms::className(), ['term_id' => 'term_id'])
->viaTable(TermRelations::tableName(), ['object_id' => 'ID'])
->andWhere(['term_type'=>'tag']);
}
/**
* Reformat tags from array to string, to display in view
* @return [string] [$tags]
*/
public function getTagsAsString() {
$tags = '';
foreach ($this->tags as $tag) {
$tags .= $tag->term_name.', ';
}
return $tags;
}
/**
* Reformat posted tags as array with saving new ones before setting value to $this->post_tags
* @return [object] [$this->post_tags]
*/
public function getTagsAsArray() {
if(!is_array($this->post_tags)) {
$post_tags = str_replace(', ', ',', $this->post_tags);
$post_tags = str_replace(' ,', ',', $this->post_tags);
$post_tags = explode(',', $post_tags);
} else {
$post_tags = $this->post_tags;
}
$tags = [];
foreach ($post_tags as $tag) {
$tag = ltrim($tag);
$tag_name = Inflector::slug($tag);
$term = Terms::find()->where(['term_name'=>$tag_name])->one();
if(!isset($term->term_id)) {
$new_term = new Terms();
$new_term->term_title = ucfirst($tag);
if($new_term->save()) {
$tags[] = $new_term;
}
} else {
$tags[] = $term;
}
}
$this->post_tags = $tags;
}
/**
* Event before saving post
* @param [type] $insert [description]
* @return [type] [description]
*/
public function beforeSave($insert) {
// Reformat posted tags as array with saving new ones before returning
$this->getTagsAsArray();
// Call parent beforeSave event to handle other processes
return parent::beforeSave($insert);
}
/**
* Event after saving post
* @param [type] $insert [description]
* @param [type] $changedAttributes [description]
* @return [type] [description]
*/
public function afterSave($insert, $changedAttributes)
{
/**
* Unlink terms and tags relations. Further new relations will linked.
*/
$this->unlinkAll('terms',true);
$this->unlinkAll('tags',true);
// Call of parent afterSave event to handle other processes
parent::afterSave($insert, $changedAttributes);
/**
* Linking post with categories via term_relations table
* @var TermRelations
*/
$term_relations = new TermRelations();
$term_relations->object_id = $this->ID;
if(is_array($this->post_terms)) {
foreach ($this->post_terms as $term) {
$term = Terms::findOne($term);
$term_relations->term_id = $term->term_id;
$this->link('terms',$term,$term_relations);
}
}
/**
* Linking post with tags via term_relations table
* @var TermRelations
*/
$tag_relations = new TermRelations();
$tag_relations->object_id = $this->ID;
if(is_array($this->post_tags)) {
foreach ($this->post_tags as $tag) {
$tag = Terms::findOne($tag->term_id);
$tag_relations->term_id = $tag->term_id;
$this->link('tags',$tag,$tag_relations);
}
}
foreach ($this->post_metas as $post_meta) {
$meta = Postmeta::findOne($post_meta['meta_id']);
$meta->post_id = $this->ID;
$meta->meta_value = $post_meta['meta_value'];
$meta->save();
}
}
public function beforeDelete()
{
if (parent::beforeDelete()) {
// Delete all relations with categories
$this->unlinkAll('terms',true);
// Delete all relations with tags
$this->unlinkAll('tags',true);
// Delete all post metas related to this post
$this->unlinkAll('metas',true);
return true;
} else {
return false;
}
}
}
PostsLang model:
<?php
namespace backend\modules\admin\modules\posts\models;
use Yii;
/**
* This is the model class for table "posts_lang".
*
* @property string $ID
* @property string $post_id
* @property string $post_lang
* @property string $post_title
* @property string $post_content
*/
class PostsLang extends \yii\db\ActiveRecord
{
/**
* @inheritdoc
*/
public static function tableName()
{
return 'posts_lang';
}
/**
* @inheritdoc
*/
public function rules()
{
return [
[['post_id', 'post_lang',], 'required'],
[['post_id'], 'integer'],
[['post_title', 'post_content'], 'string'],
[['post_lang'], 'string', 'max' => 6]
];
}
/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'ID' => Yii::t('app', 'ID'),
'post_id' => Yii::t('app', 'Post ID'),
'post_lang' => Yii::t('app', 'Post Lang'),
'post_title' => Yii::t('app', 'Post Title'),
'post_content' => Yii::t('app', 'Post Content'),
];
}
}
Posts controller:
/**
* Creates a new Posts model.
* If creation is successful, the browser will be redirected to the 'view' page.
* @return mixed
*/
public function actionCreate($type = 'post')
{
$model = new Posts();
if ($model->load(Yii::$app->request->post())) {
$model->post_type = $type;
$model->comment_count = 0;
$model->post_author = Yii::$app->user->identity->id;
$post_metas = Yii::$app->request->post('Postmeta');
unset($post_metas['meta_key']);
unset($post_metas['meta_value']);
$model->post_metas = $post_metas;
if($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->ID]);
}
} else {
return $this->render('create', [
'model' => $model,
'metas' => new Postmeta,
'type' => $type,
]);
}
}
/**
* Updates an existing Posts model.
* If update is successful, the browser will be redirected to the 'view' page.
* @param string $id
* @return mixed
*/
public function actionUpdate($id, $type = 'post')
{
$model = $this->findModel($id);
$model->post_terms = $model->terms;
$model->post_tags = $model->TagsAsString;
$metas = $model->metas;
if ($model->load(Yii::$app->request->post())) {
$post_metas = Yii::$app->request->post('Postmeta');
unset($post_metas['meta_key']);
unset($post_metas['meta_value']);
$model->post_metas = $post_metas;
if ($model->save()) {
return $this->redirect(['view', 'id' => $model->ID]);
}
} else {
return $this->render('update', [
'model' => $model,
'metas' => new Postmeta,
'type' => $type,
]);
}
}
protected function findModel($id)
{
if (($model = Posts::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
_form.php :
<?= $form->field($model, 'post_title')->textInput() ?>
<?= $form->field($model, 'post_title_en')->textInput() ?>
<?= $form->field($model, 'post_title_ru')->textInput() ?>
<?= $form->field($model, 'post_title_uz')->textInput() ?>
<?= $form->field($model, 'post_content')->widget(CKEditor::className(), [
'options' => ['rows' => 15],
'preset' => 'custom',
'clientOptions' => [
'customConfig' => Yii::$app->request->BaseUrl.'/media/plugins/ckeditor/config.js',
],
]) ?>
Thanks.
I changed the langClassName to dynamic:
//'dynamicLangClass' => false,
//'langClassName' => PostsLang::className(), // or namespace/for/a/class/PostLang
Now in $model->translations all the data are shown, if I print_r it. but the form fields are still empty.
@anvarulugov Your findModel
method should be similar to
protected function findModel($id)
{
if (($model = Activity::find()->notRemoved()->multilingual()->andWhere(['id' => $id])->one()) !== null) {
$model->setScenario('update');
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
Hello @OmgDef ! I changed the method as you stated. But not another error appeared :( Sorry for asking too many, questions, it is my first project on Yii2. So I'm really getting confused sometimes.
Error:
Calling unknown method: omgdef\multilingual\MultilingualQuery::notRemoved()
@OmgDef , thank you very much for a plugin. I solved the problem. Thank you again very much!
Hi. I installed your behavior and configrued my model:
And the _form.php:
When I create a new post in post_lang table only 'ru' is being added. But on updating a post that has not a translation yet, there nothing being added to posts_lang table. Logs show folling SQL queries: on create:
on update:
Can you help me? What am I doing wrong?