GridVeiw filer search

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
vano.mig
Сообщения: 54
Зарегистрирован: 2016.11.21, 10:25

GridVeiw filer search

Сообщение vano.mig » 2018.06.11, 17:18

Здравствуйте!, Помогите решить проблему с фильтром в GridView для поля из связной таблицы со связью hasMany
Model

Код: Выделить всё

<?php

namespace common\models;

use yii\behaviors\TimestampBehavior;
use common\components\behaviors\HistoryBehavior;
use yii\db\ActiveRecord;
use common\components\Date;
use common\models\gii\OfferToPayout;
use common\models\gii\OfferToCaps;

use Yii;

class Offer extends \common\models\gii\Offer
{
    public const STATUS_ACTIVE = 'active';
    public const STATUS_PAUSED = 'paused';
    public const STATUS_DISABLED = 'disabled';

    public const LEVEL_PUBLIC = 'public';
    public const LEVEL_REQUEST = 'request';
    public const LEVEL_PRIVATE = 'private';

    public const PAYMENT_NET15 = 'NET15';
    public const PAYMENT_NET30 = 'NET30';
    public const PAYMENT_NET45 = 'NET45';
    public const PAYMENT_NET60 = 'NET60';

    public $os_id;
    public $device_id;
    public $geo;
    public $category_id;
    public $restrictions;
    public $allowed_trafic;
    public $enabled_publisher;
    public $blocked_publisher;
    public $personal_caps;
    public $personal_caps_id;
    public $personal_pub_payout;
    public $pub_id;
    public function rules()
    {
        return [
            [['advertiser_id', 'offer_name', 'description', 'tracking_link', 'bundle_id', 'os_id', 'device_id', 'total_payout', 'margine', 'publisher_payout',  'geo', 'offer_type_id', 'trust_group',  'status', 'privacy_level',  'payment'], 'required'],
            [['advertiser_id', 'daily', 'monthly', 'total', 'exclude', 'offer_type_id'], 'integer'],
            [['total_payout', 'margine', 'publisher_payout'], 'number'],
            [['creatives', 'user_flow'], 'string'],
            [['start_date', 'expiration_date', 'created_at', 'updated_at', 'allowed_trafic', 'restrictions', 'enabled_publisher', 'blocked_publisher', 'category_id', 'pub_id', 'personal_caps_id', 'personal_pub_payout', 'personal_caps', 'image'], 'safe'],
            [['offer_name'], 'string', 'max' => 191],
            [['description', 'tracking_link', 'bundle_id', 'test_link'], 'string', 'max' => 255],

            [['payment', 'status'], 'string', 'max' => 50],
            [['version', 'trust_group', 'tags', 'privacy_level'], 'string', 'max' => 100],
        ];
    }

    public function behaviors()
    {
        return [
            [
                'class' => TimestampBehavior::class,
                'attributes' => [
                    ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'],
                    ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'],
                ],
                //'value' => new Expression('NOW()'),
                'value' => (new Date())->now(),
            ],
            [
                'class' => HistoryBehavior::class,
            ]
        ];
    }

    public function getOs()
    {
        return $this->hasMany(Os::className(), ['id'=>'os_id'])->viaTable('offer_to_os', ['offer_id'=>'id']);
    }

    /**
     * Include retations with Country table
     * @params mixed
     * @return \yii\db\ActiveQuery
     */
    public function getCountry()
    {
        return $this->hasMany(Country::className(), ['id'=>'country_id'])->viaTable('offer_to_country', ['offer_id'=>'id']);
    }

    /**
     * Include retations with device table
     * @params mixed
     * @return \yii\db\ActiveQuery
     */
    public function getDevice()
    {
        return $this->hasMany(Device::className(), ['id'=>'device_id'])->viaTable('offer_to_device', ['offer_id'=>'id']);
    }

    /**
     * Include retations with category table
     * @params mixed
     * @return \yii\db\ActiveQuery
     */
    public function getCategory()
    {
        return $this->hasMany(OfferCategory::className(), ['id'=>'category_id'])->viaTable('offer_to_category', ['offer_id'=>'id']);
    }

    /**
     * Include retations with traffic_type table for allowed
     * @params mixed
     * @return \yii\db\ActiveQuery
     */
    public function getAllowed()
    {
        return $this->hasMany(TrafficType::className(), ['id'=>'allowed_id'])->viaTable('offer_to_allowed', ['offer_id'=>'id']);
    }

    /**
     * Include retations with traffic_type table for restriction
     * @params mixed
     * @return \yii\db\ActiveQuery
     */
    public function getRestriction()
    {
        return $this->hasMany(TrafficType::className(), ['id'=>'restriction_id'])->viaTable('offer_to_restriction', ['offer_id'=>'id']);
    }

    /**
     * Include retations with user table for unabled user
     * @params mixed
     * @return \yii\db\ActiveQuery
     */
    public function getUserEnabled()
    {
        return $this->hasMany(User::className(), ['id'=>'enabled_id'])->viaTable('offer_to_user_access', ['offer_id'=>'id']);
    }

    /**
     * Include retations with user table for blocked user
     * @params mixed
     * @return \yii\db\ActiveQuery
     */
    public function getUserBlocked()
    {
        return $this->hasMany(User::className(), ['id'=>'blocked_id'])->viaTable('offer_to_user_access', ['offer_id'=>'id']);
    }


    /**
     * Include retations with offer_type table
     * @params mixed
     * @return \yii\db\ActiveQuery
     */
    public function getType()
    {
        return $this->hasOne(OfferType::className(), ['id'=>'offer_type_id']);
    }

    /**
     * relation for get personal payuot
     * @params mixed
     * @return \yii\db\ActiveQuery
     */
    public function getAdvertiser()
    {
        return $this->hasOne(User::className(), ['id'=>'advertiser_id']);
    }

    /**
     * relation for get personal payuot
     * @params mixed
     * @return \yii\db\ActiveQuery
     */
    public function getUserPayout()
    {
        return $this->hasMany(OfferToPayout::className(), ['offer_id'=>'id']);
    }

    /**
     * relation for get personal payuot
     * @params mixed
     * @return \yii\db\ActiveQuery
     */
    public function getPersonalCaps()
    {
        return $this->hasMany(OfferToCaps::className(), ['offer_id'=>'id']);
    }

    /**
     * return statuses name
     * $params = mix;
     * return array;
     */

    public function getStatuses()
    {
        return [
            Offer::STATUS_ACTIVE => Yii::t('offer', 'Active'),
            Offer::STATUS_PAUSED => Yii::t('offer', 'Paused'),
            Offer::STATUS_DISABLED => Yii::t('offer', 'Disabled'),
        ];
    }

    /**
     * return levels name
     * $params = mix;
     * return array;
     */

    public function getLevels()
    {
        return [
            Offer::LEVEL_PUBLIC => Yii::t('offer', 'Public'),
            Offer::LEVEL_REQUEST => Yii::t('offer', 'Request'),
            Offer::LEVEL_PRIVATE => Yii::t('offer', 'Private'),
        ];
    }

    /**
     * return trust_groups name
     * $params = mix;
     * return array;
     */

    public function getTrustGroups()
    {
        return (new User())->getTrustGroups();
    }

    /**
     * return payment_nets name
     * $params = mix;
     * return array;
     */

    public function getPaymentNet()
    {
        return [
            Offer::PAYMENT_NET15 => Yii::t('offer', 'NET15'),
            Offer::PAYMENT_NET30 => Yii::t('offer', 'NET30'),
            Offer::PAYMENT_NET45 => Yii::t('offer', 'NET45'),
            Offer::PAYMENT_NET60 => Yii::t('offer', 'NET60'),
        ];
    }

    /**
     * upload image
     */
    public function upload()
    {
        if ($this->validate()) {
            $this->image->saveAs('uploads/' . $this->image->baseName . '.' . $this->image->extension);
            return true;
        } else {
            return false;
        }
    }
}

view

Код: Выделить всё

<?php

use yii\helpers\Html;
use yii\grid\GridView;
use frontend\models\Offer;
use frontend\models\OfferCategory;
use frontend\models\Country;

/* @var $this yii\web\View */
/* @var $searchModel frontend\models\OdderSearch */
/* @var $dataProvider yii\data\ActiveDataProvider */

$this->title = 'Offers';
$this->params['breadcrumbs'][] = $this->title;
?>

<div class="box">
    <div class="box-header with-border">
        <h1 class="box-title">
            <?php echo Yii::t('user', 'Offers'); ?>
        </h1>

    </div>
    <div class="box-body">
        <div class="offer-index">
            <p>
                <?php if (Yii::$app->user->can('offer.create')) {
                    echo Html::a(Yii::t('user', 'Create Offer'), ['create'], ['class' => 'btn btn-success']);
                } ?>
            </p>

            <?= GridView::widget([
                'dataProvider' => $dataProvider,
                'filterModel' => $searchModel,
                'columns' => [
                    'id',
                    'offer_name',
                    [
                            'attribute'=>'status',
                        'value'=>function($data){return $data->status;},
                        'filter'=>  Html::activeDropDownList($searchModel, 'status', Offer::getStatuses(),['class'=>'form-control','prompt' => '--Select--']),
                    ],
                    ['attribute' => 'privacy_level',
                        'value' => function ($data) {
                            return $data->privacy_level;
                        },
                        'filter' => Html::activeDropDownList($searchModel, 'privacy_level', Offer::getLevels(),['class'=>'form-control','prompt' => '--Select--']),
                    ],
               
                    'total_payout',
                    'total',
/
                    ['attribute' => 'trust_group',
                        'value' => function ($data) {
                            return $data->trust_group;
                        },
                        'filter' => Html::activeDropDownList($searchModel, 'trust_group', Offer::getTrustGroups(),['class'=>'form-control','prompt' => '--Select--']),
                    ],

                    [
                        'attribute'=>'payment',
                        'value'=>function($data) { return $data->payment;},
                        'filter'=>Html::activeDropDownList($searchModel, 'payment', Offer::getPaymentNet(), ['class'=>'form-control','prompt' => '--Select--']),
                        'format'=>'raw',
                    ],
                    [
                        'attribute'=>'category_id',
                        'value'=>function($data) {$name = '';foreach ($data->category as $category){$name .= $category['name'].'<br>';}; return $name;},
                        'filter'=>Html::activeDropDownList($searchModel, 'category_id', yii\helpers\ArrayHelper::map(OfferCategory::find()->all(), 'id', 'name'), ['class'=>'form-control','prompt' => '--Select--']),
                        'format'=>'raw',
                    ],
                    //'test_link',
                    //'created_at',
                    //'updated_at',
                    [
                        'attribute'=>'country',
                        'value'=>function($data) {$name = '';foreach ($data->country as $counrty){$name .= '<span class="flag-icon flag-icon-'.strtolower($counrty['iso_code']).'"></span> ';}; return $name;},
                        'filter'=>Html::activeDropDownList($searchModel, 'country', yii\helpers\ArrayHelper::map(Country::find()->all(), 'id', 'name'), ['class'=>'form-control','prompt' => '--Select--']),
                        'format'=>'raw',
                    ],
                    [
                        'attribute'=>'image',
                        'value'=>function($data) {return '<img class="offer-preview" src="'.$data->image.'" alt="preview">';},
                        'format'=>'raw',
                    ],

                    ['class' => 'yii\grid\ActionColumn'],
                ],
            ]); ?>
        </div>
    </div>
</div>

ModelSearch

Код: Выделить всё

<?php

namespace frontend\models;

use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;

/**
 * OfferSearch represents the model behind the search form of `common\models\gii\Offer`.
 */
class OfferSearch extends Offer
{
    public $category_id;
    /**
     * {@inheritdoc}
     */
    public function rules()
    {
        return [
            [['id', 'advertiser_id', 'pub_id', 'daily', 'monthly', 'total', 'personal_caps', 'personal_caps_id', 'exclude', 'offer_type_id'], 'integer'],
            [['offer_name', 'description', 'tracking_link', 'bundle_id', 'version', 'creatives', 'trust_group', 'user_flow', 'tags', 'start_date', 'expiration_date', 'enabled_publisher', 'blocked_publisher', 'test_link', 'created_at', 'updated_at', 'category_id', 'country_id'], 'safe'],
            [['status', 'privacy_level'], 'string'],
            [['total_payout', 'margine', 'publisher_payout', 'personal_pub_payout', 'payment'], 'number'],
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function scenarios()
    {
        // bypass scenarios() implementation in the parent class
        return Model::scenarios();
    }

    /**
     * Creates data provider instance with search query applied
     *
     * @param array $params
     *
     * @return ActiveDataProvider
     */
    public function search($params)
    {
        $query = Offer::find()->with('category')->orderBy(['id'=>SORT_DESC]);
        // add conditions that should always apply here

        $dataProvider = new ActiveDataProvider([
            'query' => $query,
        ]);

        $this->load($params);

        if (!$this->validate()) {
            // uncomment the following line if you do not want to return any records when validation fails
            // $query->where('0=1');
            return $dataProvider;
        }
        //echo "<pre>";print_r($query);die;
        // grid filtering conditions
        $query->andFilterWhere([
            'id' => $this->id,
            'advertiser_id' => $this->advertiser_id,
            'total_payout' => $this->total_payout,
            'margine' => $this->margine,
            'publisher_payout' => $this->publisher_payout,
            'personal_pub_payout' => $this->personal_pub_payout,
            'pub_id' => $this->pub_id,
            'daily' => $this->daily,
            'monthly' => $this->monthly,
            'total' => $this->total,
            'personal_caps' => $this->personal_caps,
            'personal_caps_id' => $this->personal_caps_id,
            'exclude' => $this->exclude,
            'offer_type_id' => $this->offer_type_id,
            'status' => $this->status,
            'start_date' => $this->start_date,
            'expiration_date' => $this->expiration_date,
            'payment' => $this->payment,
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
            'category_id' => $this->id,
        ]);

        $query->andFilterWhere(['like', 'offer_name', $this->offer_name])
            ->andFilterWhere(['like', 'description', $this->description])
            ->andFilterWhere(['like', 'tracking_link', $this->tracking_link])
            ->andFilterWhere(['like', 'bundle_id', $this->bundle_id])
            ->andFilterWhere(['like', 'version', $this->version])
            ->andFilterWhere(['like', 'creatives', $this->creatives])
            ->andFilterWhere(['like', 'total_payout', $this->total_payout])
            ->andFilterWhere(['like', 'trust_group', $this->trust_group])
            ->andFilterWhere(['like', 'user_flow', $this->user_flow])
            ->andFilterWhere(['like', 'tags', $this->tags])
            ->andFilterWhere(['like', 'privacy_level', $this->privacy_level])
            ->andFilterWhere(['like', 'restrictions', $this->restrictions])
            ->andFilterWhere(['like', 'allowed_trafic', $this->allowed_trafic])
            ->andFilterWhere(['like', 'enabled_publisher', $this->enabled_publisher])
            ->andFilterWhere(['like', 'blocked_publisher', $this->blocked_publisher])
            ->andFilterWhere(['like', 'test_link', $this->test_link])
            ->andFilterWhere(['like', 'status', $this->status]);
            //->andFilterWhere(['like', 'category_id', $this->id]);

        return $dataProvider;
    }
}

где то  в модели поиска ошибка, не пойму что нужно исправить. Подскажите!. Спасибо!

andku83
Сообщения: 988
Зарегистрирован: 2016.07.01, 10:24
Откуда: Харьков

Re: GridVeiw filer search

Сообщение andku83 » 2018.06.11, 17:32

https://elisdn.ru/blog/89/related-models-on-yii2

Правильнее форматируйте сообщение.
Если вам нужна быстрая помощь, как думаете сколько людей будут искать "абстрактную" ошибку? (или вы ее все-таки покажете?)

vano.mig
Сообщения: 54
Зарегистрирован: 2016.11.21, 10:25

Re: GridVeiw filer search

Сообщение vano.mig » 2018.06.11, 17:38

я не знаю где точно ошибка...
но склоняюсь к тому что она в модели OfferSearch вот здесь

Код: Выделить всё

$query = Offer::find()->with('category')->orderBy(['id'=>SORT_DESC]);
или

Код: Выделить всё

'category_id' => $this->id,

andku83
Сообщения: 988
Зарегистрирован: 2016.07.01, 10:24
Откуда: Харьков

Re: GridVeiw filer search

Сообщение andku83 » 2018.06.11, 18:20

vano.mig писал(а):
2018.06.11, 17:38

Код: Выделить всё

'category_id' => $this->id,
ну тут точно ошибка, даже gii этот код сделало бы по другому: 'category_id' => $this->category_id

а php или дебагер ничего не пишут?
в чем заключается ошибка?

vano.mig
Сообщения: 54
Зарегистрирован: 2016.11.21, 10:25

Re: GridVeiw filer search

Сообщение vano.mig » 2018.06.12, 10:07

все, спасибо, разобрался.
сделал так

Код: Выделить всё

$query = Offer::find()->joinWith(['category', 'country'])->orderBy(['id'=>SORT_DESC]);

Код: Выделить всё

 'offer_to_category.category_id' => $this->category_id,
 'offer_to_country.country_id' => $this->country,

Ответить