OmgDef / yii2-multilingual-behavior

Yii2 port of the yii-multilingual-behavior.
146 stars 60 forks source link

On update load and save ml data? #18

Closed sajtosnorbert closed 9 years ago

sajtosnorbert commented 9 years ago

Hi there!

I am trying to use the behavior, but I have one problem and question.

On an update form I try to set the ml records (ex: title_en): <?= $form->field($model, 'title_en')->textInput(['maxlength' => 255]); ?>

In the action the load function does not update the ml records:

public function actionUpdate( $id ) {
    $model = $this->findModelMl( $id); // loads the multilingual records

    if ( $model->load( Yii::$app->request->post() ) && $model->save() ) {
        return $this->redirect( [ 'view', 'id' => $model->id ] );
    } else {
        return $this->render( 'update', [
            'model' => $model,
        ] );
    }
}

protected function findModelMl( $id ) {
    $model = ProductCategory::find()->where( [ 'id' => $id ] )->multilingual()->one();
    if ( $model !== null ) {
        return $model;
    } else {
        throw new NotFoundHttpException( 'The requested page does not exist.' );
    }
}

Is there any simple way to use the load function and update the records?

Thanks, Norbert

OmgDef commented 9 years ago

@sajtosnorbert Hi! Example of the load function

    protected function findModel($id)
    {
        if (($model = Activity::find()->multilingual()->andWhere(['id' => $id])->one()) !== null) {
            return $model;
        } else {
            throw new NotFoundHttpException('The requested page does not exist.');
        }
    }
sajtosnorbert commented 9 years ago

Hi!

I think you misunderstood my question... My question is about this line: if ( $model->load( Yii::$app->request->post() ) && $model->save() ) { Where we load the request data int the found model.

This is where ($model->load) it would be easy that if there are relevant ml data (title_en, ttle_de, etc.) in the request, the load function automatically updates the model data, and then save function saves it. In that case we don't need to manually update each ml data...

Thanks again. Norbert

OmgDef commented 9 years ago

@sajtosnorbert Hi! I use the similar code in all my projects. The load function automatically updates the model data, and then save function saves it (all translations saves automatically). It seems the problem in your model. Can you paste your model here?

sajtosnorbert commented 9 years ago

ProductCategory Model:

<?php

namespace app\models;

use omgdef\multilingual\MultilingualBehavior;
use omgdef\multilingual\MultilingualQuery;
use Yii;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;

/**
 * This is the model class for table "product_category".
 *
 * @property integer $id
 * @property integer $enabled
 * @property integer $sequence
 * @property string $created
 * @property string $updated
 *
 * @property Product[] $products
 * @property ProductCategoryMl[] $productCategoryMls
 */
class ProductCategory extends ActiveRecord {
    /**
     * @inheritdoc
     */
    public static function tableName() {
        return 'product_category';
    }

    /**
     * @inheritdoc
     */
    public function rules() {
        return [
            [ [ 'enabled', 'sequence' ], 'integer' ],
            [ [ 'created', 'updated' ], 'required' ],
            [ [ 'created', 'updated' ], 'safe' ]
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels() {
        return [
            'id'       => Yii::t( 'app.models.productCategory', 'id' ),
            'enabled'  => Yii::t( 'app.models.productCategory', 'enabled' ),
            'sequence' => Yii::t( 'app.models.productCategory', 'sequence' ),
            'created'  => Yii::t( 'app.models.productCategory', 'created' ),
            'updated'  => Yii::t( 'app.models.productCategory', 'updated' ),
        ];
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getProducts() {
        return $this->hasMany( Product::className(), [ 'product_category_id' => 'id' ] );
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getProductCategoryMls() {
        return $this->hasMany( ProductCategoryMl::className(), [ 'product_category_id' => 'id' ] );
    }

    public function behaviors() {
        return [
            'ml' => [
                'class'           => MultilingualBehavior::className(),
                'languages'       => Yii::$app->params['languages'],
                'defaultLanguage' => Yii::$app->params['defaultLanguage'],
                'langClassName'   => ProductCategoryMl::className(), // or namespace/for/a/class/PostLang
                'langForeignKey'  => 'product_category_id',
                'tableName'       => "{{%product_category_ml}}",
                'attributes'      => [
                    'title',
                    'content',
                    'slug',
                ]
            ],
        ];
    }

    public static function find() {
        return new MultilingualQuery( get_called_class() );
    }
}

ProductCategoryMl Model:

<?php

namespace app\models;

use Yii;

/**
 * This is the model class for table "product_category_ml".
 *
 * @property integer $id
 * @property integer $product_category_id
 * @property string $language
 * @property string $title
 * @property string $content
 * @property string $slug
 *
 * @property ProductCategory $productCategory
 */
class ProductCategoryMl extends \yii\db\ActiveRecord {
    /**
     * @inheritdoc
     */
    public static function tableName() {
        return 'product_category_ml';
    }

    /**
     * @inheritdoc
     */
    public function rules() {
        return [
            [ [ 'product_category_id', 'language', 'title', 'slug' ], 'required' ],
            [ [ 'product_category_id' ], 'integer' ],
            [ [ 'content' ], 'string' ],
            [ [ 'language' ], 'string', 'max' => 6 ],
            [ [ 'title', 'slug' ], 'string', 'max' => 255 ]
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels() {
        return [
            'id'                  => Yii::t( 'app.models.productCategoryMl', 'id' ),
            'product_category_id' => Yii::t( 'app.models.productCategoryMl', 'product_category_id' ),
            'language'            => Yii::t( 'app.models.productCategoryMl', 'language' ),
            'title'               => Yii::t( 'app.models.productCategoryMl', 'title' ),
            'content'             => Yii::t( 'app.models.productCategoryMl', 'content' ),
            'slug'                => Yii::t( 'app.models.productCategoryMl', 'slug' ),
        ];
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getProductCategory() {
        return $this->hasOne( ProductCategory::className(), [ 'id' => 'product_category_id' ] );
    }
}

Controller update function:

    public function actionUpdate( $id ) {
        $model = $this->findModel( $id, true );

        if ( $model->load( Yii::$app->request->post() ) && $model->save() ) {
            return $this->redirect( [ 'view', 'id' => $model->id ] );
        } else {
            return $this->render( 'update', [
                'model' => $model,
            ] );
        }
    }

Controller findModel function:

    protected function findModel( $id, $ml = false ) {
        if ( $ml ) {
            $model = ProductCategory::find()->where( [ 'id' => $id ] )->multilingual()->one();
        } else {
            $model = ProductCategory::findOne( $id );
        }
        if ( $model !== null ) {
            return $model;
        } else {
            throw new NotFoundHttpException( 'The requested page does not exist.' );
        }
    }

With this code title_en is not updated :(

Thanks for your help! Norbert.

OmgDef commented 9 years ago

@sajtosnorbert That's because you should not specify validators in ML model. All validators should be in parent model.

Example https://github.com/OmgDef/yii2-multilingual-behavior/blob/master/tests/models/Post.php

sajtosnorbert commented 9 years ago

Hi I was trying hard, then I found the problem!

My default language is 'hu' and I tried to save my hu language title as title_hu. In that case it is not saved, only the 'title' field is saved.

For example, these are the fields: <?= $form->field($model, 'title_hu')->textInput(['maxlength' => 255]); ?> <?= $form->field($model, 'title_en')->textInput(['maxlength' => 255]); ?> and I added this one for test: <?= $form->field($model, 'title')->textInput(['maxlength' => 255]); ?>

In my case 'title' uspdates the 'hu' language title and 'title_en' can be updated, but 'titlehu' can't be used. What If I want to cycle through the available languages and dynamically call tabulated data, and I will have only '%field%%lang%' form items no mater what actual language I am using.

Is there a way that the 'title_hu' field can be used for update? As I am newbie to Yii2... Is it a bug or I am missing some knowledge? :D

Thanks for your answers :)

Norbert.

OmgDef commented 9 years ago

@sajtosnorbert Hi! Attributes for default language should not be suffixed by '_language'. This is indicated in the documentation