yii2mod / yii2-comments

Comments module for Yii2
MIT License
158 stars 63 forks source link

Проблема при многоразовом использовании виджета на одной странице #14

Closed vityapro closed 8 years ago

vityapro commented 8 years ago

Хотелось бы сообщить о возможности возникновения бага при условии многоразово использования модуля на одной странице при рандомном порядке отображения сущностей к которым применяеться модуль, баг связан с логикой работы метода $this->getId(); и Pjax контейнера. Проблема в том что при многоразовом отправлении запросов id контейнера может меняться поскольку порядок присвоения контейнеру id меняеться в соотвецтвии с порядком отображения его на странице и врезультате мы получаем пачку коментариев другой сущности.

Как решение проблемы предлагаю переопределить метод init() в Comment.php и сделать его зависимым от entityId или же сделать возможным определять его ид с точки вызова виджета так же как и $formId (на ваше усмотрение)

Также столкнулся с связаной с этим проблемой решение которой не смог найти (при рандомном отображении сущностей к которым применяеться виджет) тоесть когда Pjax посылает запрпос на туже страницу на подгрузку контейнера с определенным id (но поскольку идет рандомное отображение) то при запросе Pjax его не находит и редиректит на страницу /comment/default для отмены редиректа присвоил ActiveForme следующий параметр 'data-pjax'=>true, в результате в Pjax просто подгружает в свой контейнер ответ со страници /comment/default а именно ['status' => 'success'] что тоже не есть верным результатом в целом буду рад услышать ваше мнение по поводу решения даной проблемы. Спасибо за внимание.

При использовании параметра 'showDeletedComments' => true выдвет Unknown Property по всей видимости вы просто забыли убрать его со страници описания в отделе Basic example: хотя параметр весьма полезный как альтернатива вместо отображения тексту Comment was deleted.

П.С. Спасибо за отличный виджет.

ihorchepurnyi commented 8 years ago

Здравствуйте, скиньте пожалуйста код примера в котором у вас ошибка

vityapro commented 8 years ago

Какая именно из ошибок вас интересует ?

ihorchepurnyi commented 8 years ago

1 исправим, нужен код для воспроизведения 2 проблемы

vityapro commented 8 years ago

Ок, я попытаюсь более детально описать вторую проблему потому как просто кодом не обойтись. Допустим у вас есть сущность Product к которой применяеться ваш виджет, в таблице товаров 100+, на страницу вы выводите только 10 случайных товаров тоесть в SQL запросе для выборки товаров вы используете ORDER BY rand() после чего выводите их на страницсау код моего SQL запро:

$query = Product::find()->select(product.*, case when product.currency_id is not null then product.price * currency.rate when program.currency_id is not null then product.price * cur.rate else product.price * (SELECT rate from currency where title = \'USD\') END priceE') ->where(['shoplook' => 1, 'product.is_available' => 1,])->orderBy(new Expression('rand()'))->limit(10);

ihorchepurnyi commented 8 years ago

окей, понял. То есть вы виджет применяете для каждого продукта?

vityapro commented 8 years ago

Совершенно верно

ihorchepurnyi commented 8 years ago

окей, спасибо. В ближайшее время постараюсь исправить.

vityapro commented 8 years ago

Спасибо

ihorchepurnyi commented 8 years ago

При использовании параметра 'showDeletedComments' => true выдвет Unknown Property по всей видимости вы просто забыли убрать его со страници описания в отделе Basic example: хотя параметр весьма полезный как альтернатива вместо отображения тексту Comment was deleted.

сделайте composer update, showDeletedComments был добавлен вчера.

vityapro commented 8 years ago

Ок

ihorchepurnyi commented 8 years ago

Добавил возможность установить id для pjax. Сделайте пожалуйста composer update.

<?php echo \yii2mod\comments\widgets\Comment::widget([
               'pjaxContainerId' => 'comment-pjax-container-' . $user->id
]); ?>

Сейчас попробовал применить виджет к разным юзерам, которые выбираются случайно. Перезагрузки страницы не было, все работало корректно. Вот код:

1) Нахожу юзеров

$users = UserModel::find()->orderBy(new Expression('rand()'))->all(); // в тестовой базе 6 юзеров

2) Вывод на фронтенде:

<div class="row">
    <?php foreach ($users as $user): ?>
        <div class="col-md-6">
            <div class="panel panel-default">
                <div class="panel-heading"><?php echo $user->email; ?></div>
                <div class="panel-body">
                    <?php echo \yii2mod\comments\widgets\Comment::widget([
                        'model' => $user,
                        'formId' => 'comment-form-' . $user->id,
                       'pjaxContainerId' => 'comment-pjax-container-' . $user->id
                    ]); ?>
                </div>
            </div>
        </div>
    <?php endforeach; ?>
</div>
vityapro commented 8 years ago

Вы выбераете всех юзеров, для того что бы выпала ошибка выберите одного или два (но не всех)

vityapro commented 8 years ago

первый и второй баг касались orderBy(new Expression('rand()')) но второй баг видет за условия что только несколько юзеров будут отображены

ihorchepurnyi commented 8 years ago

А если так

1) Выборка юзеров

$users = UserModel::find()->orderBy(new Expression('rand()'))->limit(2)->all();

2) А на фронтенде не много по другому генерировать formId, и pjaxContainerId

<?php foreach ($users as $key => $user): ?>
        <div class="col-md-6">
            <div class="panel panel-default">
                <div class="panel-heading"><?php echo $user->email; ?></div>
                <div class="panel-body">
                    <?php echo \yii2mod\comments\widgets\Comment::widget([
                        'model' => $user,
                        'formId' => 'comment-form-' . $key,
                        'pjaxContainerId' => 'comment-pjax-container-' . $key
                    ]); ?>
                </div>
            </div>
        </div>
    <?php endforeach; ?>

Перезагрузки вроде бы нет.

ihorchepurnyi commented 8 years ago

Но в способе который выше, pjax контейнер перезагрузится, но не факт что там будет ваш коммент, так как это random. Если вы хотите чтобы он перезагрузился на нужную запись из рандомной выборки, то тут я не смогу помочь. Так как с таким не сталкивался.

vityapro commented 8 years ago

Хорошо, спасибо за помощь и апдейт модуля. Если найду решение с обезательно сообщю.

ihorchepurnyi commented 8 years ago

не за что, в итоге мало чем помог)

ihorchepurnyi commented 8 years ago

Нашел хак, корявый конечно. Идея в том чтобы в экшене поймать pjaxId при pjax реквесте, исходя из его ид найти юзера, и смержить основную выборку с выборкой в которой будет этот юзер(для которого непосредственно добавляется комментарий). Также нужно добавить метод indexBy при выборке

1) Вот код контроллера

$users = UserModel::find()->orderBy(new Expression('rand()'))->indexBy('id')->limit(2)->all();
if (Yii::$app->request->getIsPjax()) {
    $pjaxId = Yii::$app->request->getQueryParam('_pjax');
    $userId = substr($pjaxId, -1);
    $users = ArrayHelper::merge($users, UserModel::find()->where(['id' => $userId])->indexBy('id')->all());
}

2) Код вьюхи, в pjaxContainerId последний символ это id юзера

<?php foreach ($users as $id => $user): ?>
        <div class="col-md-6">
            <div class="panel panel-default">
                <div class="panel-heading"><?php echo $user->email; ?></div>
                <div class="panel-body">
                    <?php echo \yii2mod\comments\widgets\Comment::widget([
                        'model' => $user,
                        'formId' => 'comment-form-' . $id,
                        'pjaxContainerId' => 'comment-pjax-container-' . $id
                    ]); ?>
                </div>
            </div>
        </div>
    <?php endforeach; ?>

В данном случае в ответе всегда будет запись для которой вы добавили коммент.

vityapro commented 8 years ago

Это просто гениально )

ihorchepurnyi commented 8 years ago

Честно говоря другого способа я не смог придумать...