Страница 1 из 3
События в yii2
Добавлено: 2019.08.08, 16:44
svil
События в yii2. Нужно в таблицу event записывать факт добавления записи в таблицу article.
В дальнейшем таких таблиц будет много, откуда записывать факты создания, изменения, удаления записей.
Самая понятная статья
http://qaru.site/questions/202812/how-t ... ts-in-yii2
Прочитав, мне стало ясно, что для добавления записей в таблицу event механизм событий не нужен.
Есть ли смысл создавать события, если при создании новой записи вв таблице БД также можно создавать поля в таблице Event?
Код: Выделить всё
public function actionCreate()
{
$model = new Article();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
$events = new Event();
$events->title = "Добавлена запись: ".$model->name;
return $this->redirect(['view', 'id' => $model->id]);
Поведение не применить, потому что поля разные в таблицах.
Re: События в yii2
Добавлено: 2019.08.08, 17:51
Alexum
Я предпочитаю записывать через afterSave(). Плюсы такого подхода: гибкость (можно фильтровать, что и как записывать в лог и хранить в сериализованном виде), сохранять новое и старое значение, записывать не id связанных элементов а их текстовые названия. Это позволяет вести журнал любых изменений с полнотекстовым поиском по изменённому значению. Минусы - под каждую модель формы нужно писать свой метод (если конечно не сделать его простым и унифицированным, но в функционале он будет уступать).
В самой простой реализации выглядит примерно так:
Код: Выделить всё
public function afterSave($insert, $changedAttributes)
{
parent::afterSave($insert, $changedAttributes);
if ($changedAttributes) {
$log = [];
if ($insert) {
// Что пишем при создании записи?
} else {
// Что при редактировании? Н-р:
foreach ($changedAttributes as $attribute => $value) {
$label = $this->getAttributeLabel($attribute);
$log[$label] = [
0 => $value, // Старое значение
1 => $this->$attribute, // Новое значение
];
}
}
Log::record($this->id, self::tableName(), serialize($log), $this->getScenario());
}
}
Re: События в yii2
Добавлено: 2019.08.12, 21:02
svil
Есть таблица Article и другие таблицы в БД, при добавлении в них записи
должна заполняться таблица Event.
Пока не выходит
Код: Выделить всё
<?php
namespace app\components;
use yii\base\Application;
use yii\base\BootstrapInterface;
use yii\base\Event;
use yii\db\ActiveRecord;
class ShopNotificator implements BootstrapInterface
{
/**
* Bootstrap method to be called during application bootstrap stage.
* @param Application $app the application currently running
*/
public function bootstrap($app)
{
Event::on(
ActiveRecord::className(),
ActiveRecord::EVENT_AFTER_INSERT, function ($event) {
[$this, 'opinionCreated'];
});
}
public function opinionCreated(Event $event)
{
$ev = new \app\models\Event();
$ev->title = $event->sender;
$ev->save();
}
}
Re: События в yii2
Добавлено: 2019.08.12, 21:36
ElisDN
Код: Выделить всё
'bootstrap' => [
'log',
ShopNotificator::class,
]
Re: События в yii2
Добавлено: 2019.08.12, 22:14
svil
Спасибо
Re: События в yii2
Добавлено: 2019.08.12, 22:18
svil
Код: Выделить всё
Unknown bootstrapping component ID: ShopNotificator
Добавила
Код: Выделить всё
'components' => [
'ShopNotificator' => [
'class' => 'app\components\ShopNotificator'],
Re: События в yii2
Добавлено: 2019.08.12, 22:21
svil
Не помогло, запись в таблицу \app\models\Event() не добавляется
Re: События в yii2
Добавлено: 2019.08.12, 22:26
ElisDN
А что в $ev->title присваиваете?
Re: События в yii2
Добавлено: 2019.08.12, 22:35
svil
Пока так пробую для теста
Когда запишется, хочу получать данные из $event, нужны поля таблиц, данные в которые добавляются/редактируются
Re: События в yii2
Добавлено: 2019.08.13, 01:56
yiiliveext
svil писал(а): ↑2019.08.12, 21:02
Есть таблица Article и другие таблицы в БД, при добавлении в них записи
должна заполняться таблица Event.
Пока не выходит
Код: Выделить всё
<?php
public function bootstrap($app)
{
Event::on(
ActiveRecord::className(),
ActiveRecord::EVENT_AFTER_INSERT, function ($event) {
[$this, 'opinionCreated'];
});
}
}
У вас функция ничего не возвращает.
Код: Выделить всё
public function bootstrap($app)
{
Event::on(
ActiveRecord::className(),
ActiveRecord::EVENT_AFTER_INSERT, function ($event) {
return [$this, 'opinionCreated'];
});
}
P.S. Посмотрел исходники Yii, так все равно работать не будет. Смотрите ответ ниже.
Re: События в yii2
Добавлено: 2019.08.13, 02:32
yiiliveext
svil писал(а): ↑2019.08.12, 21:02
Код: Выделить всё
<?php
Event::on(
ActiveRecord::className(),
ActiveRecord::EVENT_AFTER_INSERT, function ($event) {
[$this, 'opinionCreated'];
});
Вот так вот будет работать.
Код: Выделить всё
Event::on(
ActiveRecord::className(),
ActiveRecord::EVENT_AFTER_INSERT,
[$this, 'opinionCreated']
);
Re: События в yii2
Добавлено: 2019.08.13, 21:40
svil
Процесс сдвинулся стремительно с мертвой точки и вставил в таблицу event 2873 записей одинаковых "тестирую событие" на локальном
и выдает ошибку
PHP Fatal Error – yii\base\ErrorException
Maximum execution time of 30 seconds exceeded
Код: Выделить всё
1. in /Users/svetlanailina/Sites/yii2_bz_events/vendor/yiisoft/yii2/log/Logger.php at line 148
139140141142143144145146147148149150151152153154155156157 * `Logger::LEVEL_PROFILE_BEGIN`, `Logger::LEVEL_PROFILE_END`.
* @param string $category the category of the message.
*/
public function log($message, $level, $category = 'application')
{
$time = microtime(true);
$traces = [];
if ($this->traceLevel > 0) {
$count = 0;
$ts = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
array_pop($ts); // remove the last trace since it would be the entry script, not very useful
foreach ($ts as $trace) {
if (isset($trace['file'], $trace['line']) && strpos($trace['file'], YII2_PATH) !== 0) {
unset($trace['object'], $trace['args']);
$traces[] = $trace;
if (++$count >= $this->traceLevel) {
break;
}
}
2. yii\base\ErrorHandler::handleFatalError()
$_POST = [
'_csrf' => 'PGufsxVqqLB214SdLf3-7uEWoM6Utm5kcUPz824fPaFIKdjDUi2f3wG27fR-m7LevmLrlNrfPi4_Mb2KFil85A==',
'Article' => [
'name' => 'оо',
'description' => 'оо',
],
];
$_COOKIE = [
'PHPSESSID' => 'mih734mjfnn2h3khqjepdc2101',
'_csrf' => '8946c09f1e67ae68c3ae223e81a87a3a17d9ce56304208c71d1424e9ab5bb87ca:2:{i:0;s:5:"_csrf";i:1;s:32:"tBGpGG7owaiiSfL0_tKZNiPJNrNyx6AE";}',
'advanced' => 'uva7rlvbdk3ckqnfhabav4f0in',
'_csrf-frontend' => 'f6a02f99fc6fa0922c68d462510876e80094e5ecf7931ef4406a4d89a49cc25fa:2:{i:0;s:14:"_csrf-frontend";i:1;s:32:"jkSfkPcGSh_vMGDfRI5RdLL_B7Bs9tUr";}',
];
$_SESSION = [
'__flash' => [],
];
Yii Framework
2019-08-13, 18:51:06
Apache/2.4.37 (Unix) PHP/7.1.24
https://github.com/svil1502/yii2_bz_events
На удаленном хостинге выдает 502 ошибку
web.php
Код: Выделить всё
<?php
$params = require __DIR__ . '/params.php';
$db = require __DIR__ . '/db.php';
$config = [
'id' => 'basic',
'basePath' => dirname(__DIR__),
'bootstrap' => [
'log',
ShopNotificator::class,
],
'aliases' => [
'@bower' => '@vendor/bower-asset',
'@npm' => '@vendor/npm-asset',
],
'components' => [
'ShopNotificator' => [
'class' => 'app\components\ShopNotificator'],
'request' => [
// !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
'cookieValidationKey' => 'tATR8OV7ELA9FeQYX3fCDoKk_tmG6Egn',
],
'cache' => [
'class' => 'yii\caching\FileCache',
],
'user' => [
'identityClass' => 'app\models\User',
'enableAutoLogin' => true,
],
'errorHandler' => [
'errorAction' => 'site/error',
],
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
// send all mails to a file by default. You have to set
// 'useFileTransport' to false and configure a transport
// for the mailer to send real emails.
//'useFileTransport' => true,
'useFileTransport' => false,
],
'log' => [
'traceLevel' => YII_DEBUG ? 3 : 0,
'targets' => [
[
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning'],
],
],
],
'db' => $db,
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
],
],
],
'params' => $params,
];
if (YII_ENV_DEV) {
// configuration adjustments for 'dev' environment
$config['bootstrap'][] = 'debug';
$config['modules']['debug'] = [
'class' => 'yii\debug\Module',
// uncomment the following to add your IP if you are not connecting from localhost.
//'allowedIPs' => ['127.0.0.1', '::1'],
];
$config['bootstrap'][] = 'gii';
$config['modules']['gii'] = [
'class' => 'yii\gii\Module',
// uncomment the following to add your IP if you are not connecting from localhost.
//'allowedIPs' => ['127.0.0.1', '::1'],
];
}
return $config;
components/
Код: Выделить всё
<?php
namespace app\components;
use yii\base\Application;
use yii\base\BootstrapInterface;
use yii\base\Event;
use yii\db\ActiveRecord;
class ShopNotificator implements BootstrapInterface
{
/**
* Bootstrap method to be called during application bootstrap stage.
* @param Application $app the application currently running
*/
public function bootstrap($app)
{
// Event::on(
// ActiveRecord::className(),
// ActiveRecord::EVENT_AFTER_INSERT, function ($event) {
// [$this, 'opinionCreated'];
// });
Event::on(
ActiveRecord::className(),
ActiveRecord::EVENT_AFTER_INSERT,
[$this, 'opinionCreated']
);
// Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function ($event) {
// Yii::debug(get_class($event->sender) . ' добавлен');
// $ev = new \app\models\Event();
// $ev->title = "текстовочка";
// //$event->sender;
// $ev->save();
// });
}
public function opinionCreated(Event $event)
{
$ev = new \app\models\Event();
$ev->title = "тестирую событие";
//$event->sender;
$ev->save();
}
}
Re: События в yii2
Добавлено: 2019.08.13, 22:05
yiiliveext
Вы можете установить set_time_limit (0), но если у вас запрос не укладывается в 30 секунд, то вам скорее нужно пересмотреть архитектуру приложения.
Re: События в yii2
Добавлено: 2019.08.13, 22:23
svil
А почему вставляется 2873 записей в таблицу Event?
Re: События в yii2
Добавлено: 2019.08.13, 22:24
svil
Я добавляю в таблицу Article 1 запись, после которой вставляется в таблицу Event 2873 записей с title "тестирую событие"
Re: События в yii2
Добавлено: 2019.08.13, 22:25
svil
Архитектура для теста взята basic, две таблицы и больше ничего
Re: События в yii2
Добавлено: 2019.08.14, 00:31
ElisDN
svil писал(а): ↑2019.08.13, 22:24
Я добавляю в таблицу Article 1 запись, после которой вставляется в таблицу Event 2873 записей с title "тестирую событие"
Потому что $ev->save() тоже генерирует событие и скрипт зацикливается.
Вставляйте через Yii::$app->db->createCommand()->insert('events', ['title' => ...])->execute().
Re: События в yii2
Добавлено: 2019.08.14, 09:07
svil
Вместо даты created_at вставился null
Re: События в yii2
Добавлено: 2019.08.14, 09:08
svil
Модель event
Код: Выделить всё
<?php
namespace app\models;
use Yii;
use yii\behaviors\TimestampBehavior;
/**
* This is the model class for table "event".
*
* @property int $id
* @property string $title
*/
class Event extends \yii\db\ActiveRecord
{
public function behaviors()
{
return [
TimestampBehavior::className(),
];
}
/**
* {@inheritdoc}
*/
public static function tableName()
{
return 'event';
}
/**
* {@inheritdoc}
*/
public function rules()
{
return [
// [['title'], 'required'],
[['title'], 'string', 'max' => 250],
];
}
/**
* {@inheritdoc}
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'title' => 'Title',
];
}
}
Re: События в yii2
Добавлено: 2019.08.14, 09:09
svil
В модел event дату настроить? Потому что при save() дату добавляло текущую через TimestampBehavior::className()