OmgDef / yii2-multilingual-behavior

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

Searching language fields example #41

Closed ustmaestro closed 9 years ago

ustmaestro commented 9 years ago

First of all this is a very useful extension, I worked with it in Yii 1.x version and I want to say that is just awesome. Now I'm working with Yii 2.x version and i have a little problem

How to search in translated fields? Examples please!

Migrations:

            $this->createTable($dataTableSchema . '{{%post}}', [
                'id'            => Schema::TYPE_PK,
                'author_id'     => Schema::TYPE_INTEGER . ' NOT NULL',
                'image'         => Schema::TYPE_STRING . '(255)',
                'sort_order'    => Schema::TYPE_INTEGER . ' NOT NULL DEFAULT 0',
                'views'         => Schema::TYPE_INTEGER . ' NOT NULL DEFAULT 0',
                'status'        => Schema::TYPE_SMALLINT . ' NOT NULL DEFAULT 1',
                'create_time'   => Schema::TYPE_TIMESTAMP,
                'update_time'   => Schema::TYPE_TIMESTAMP,
            ], $tableOptions);

            $this->createTable($dataTableSchema . '{{%post_lang}}', [
                'post_id'           => Schema::TYPE_INTEGER . ' NOT NULL',
                'language'          => Schema::TYPE_STRING . '(16) NOT NULL', 
                'title'             => Schema::TYPE_STRING . '(255) NOT NULL',
                'slug'              => Schema::TYPE_STRING . '(255) NOT NULL',
                'meta_description'  => Schema::TYPE_STRING . '(255)',
                'meta_keywords'     => Schema::TYPE_STRING . '(255)',
                'content'           => Schema::TYPE_TEXT,
                'short_description' => Schema::TYPE_TEXT,
                'tags'              => Schema::TYPE_TEXT,
            ], $tableOptions);

Controller

            /**
             * Displays a single Post model.
             * @param string $slug
             * @return mixed
             */
            public function actionSlug($slug)
            {
                $model = $this->findModelBySlug($slug);
                return $this->render('view', [ 'model' => $model ]);
            }

            /**
             * Finds the Post model based on slug.
             * If the model is not found, a 404 HTTP exception will be thrown.
             * @param string $slug
             * @return Post the loaded model
             * @throws NotFoundHttpException if the model cannot be found
             */
            protected function findModelBySlug($slug)
            {   
                if (($model = Post::find()->localized()->where(['slug' => $slug, 'status' => Post::STATUS_ACTIVE])->one()) !== null) {
                    return $model;
                } else {
                    throw new NotFoundHttpException('The requested page does not exist.');
                }
            }

I don't know how to make this work. In previous version I used Criteria.

Can you please create an example with search in translated fields

OmgDef commented 9 years ago

@ustmaestro You should use joinWith

Post::find()->joinWith('translation')->andWhere(['{{%activities_lang}}. slug' => $slug])->one()
ustmaestro commented 9 years ago

This is a simple example how to use search by a translated field

Supposed you have links like:

http://127.0.0.0/en/blog/post/demo-article http://127.0.0.0/ru/blog/post/demo-statiya http://127.0.0.0/ro/blog/post/demo-articol

where

demo-article
demo-statiya
demo-articol

are the slug's of same post in different languages en, ru, ro

In our url rules we need to pass this rule

'blog/post/<slug:[\w-]+>' => 'blog/post/slug',  // if blog module
'blog/post/<slug:[\w-]+>' => 'post/slug',       // if blog is not a module

to find post by slug in our PostController we need an action called "actionSlug" and a function that will search model by slug

/**
 * Displays a single Post model.
 * @param string $slug
 * @return mixed
 */
public function actionSlug($slug)
{   
    $model = $this->findModelBySlug($slug);
    $this->counter($model);
    return $this->render('view', [ 'model' => $model ]);
}

And search by slug field in translation table

/**
 * Finds the Post model based on slug.
 * If the model is not found, a 404 HTTP exception will be thrown.
 * @param string $slug
 * @return Post the loaded model
 * @throws NotFoundHttpException if the model cannot be found
 */
protected function findModelBySlug($slug)   
{
    if (( $model = Post::find()
            ->joinWith('translation')                                       // join translation table
            ->andWhere([ 
                PostLang::tableName().'.slug' => $slug,                     // add slug condition
                PostLang::tableName().'.language' => Yii::$app->language,   // add language condition
                'status' => POST::STATUS_ACTIVE                             // add status condition
            ])
            ->one()     
    ) !== null) {
        return $model;
    } else {
        throw new NotFoundHttpException(Yii::t('blog','The requested post does not exist.'));
    }
    return null;
}

Hope this will be useful.

ustmaestro commented 9 years ago

@OmgDef You have a typo {{%activities_lang} must be {{%post_lang}

OmgDef commented 9 years ago

@ustmaestro It seems you solved your problem. Can I close the issue?

ustmaestro commented 9 years ago

OK. Can you please check https://github.com/OmgDef/yii2-multilingual-behavior/issues/23