Perhaps everything that I will write below is obvious, and everyone has been using it for a long time, but I just recently realized this and thought it out, so maybe someone will come in handy.
Unfortunately, yii2 and the yii2-mongodb extension do not work with the attached documents, thereby leaving behind a significant advantage of the document -oriented database.
The documentation suggests using the extension for attached documents, but you can do without it.
Suppose we have a model that generates a PDF file for downloading, and we want to monitor the number of downloads, the IP addresses that downloaded and, for example, the time when the file was downloaded.
For simplicity, I assume that the file itself is stored in a string, but this, of course, can be completely wrong - it can lie somewhere in the repository or be formed by a function.
Basic model (part)
/** * @property string $pdf_data , * @property array $downloads_data * */ Class PdfData extends \yii\mongodb\ActiveRecord /** @inheritdoc */ public static function collectionName() { return ['database', 'pdf'] } /** @inheritdoc */ public function attributes() { return [ 'pdf_data', 'downloads_data' ]; }
Additional model - for checking and assigning values to array elements
use \MongoDB\BSON\UTCDateTime /** * */ class DowmnloadData extends \yii\base\Model { /** @var \MongoDB\BSON\UTCDateTime $datetime */ public $datetime; /** @var string $clientIp */ public $clientIp; /** @var string $clientHost */ public $clientHost; /** @var string $clientUserAgent */ public $clientUserAgent; /** @var string $referer */ public $referer; /** @var bool $result */ public $result = false; /** @inheritdoc */ public function rules() { return [ ['datetime', 'default', 'value' => function() { return new UTCDateTime(strtotime("now") * 1000); }], ['clientIp', 'default', 'value' => function() { return Yii::$app->request->getUserIP(); }], ['clientHost', 'default', 'value' => function() { return Yii::$app->request->getUserHost(); }], ['clientUserAgent', 'default', 'value' => function() { return Yii::$app->request->getUserAgent(); }], ['referer', 'default', 'value' => function() { return Yii::$app->request->getReferrer(); }], ['result', 'boolean'], ]; }
Further, in the controller action, which gives the file to the outside, something like the following:
// -- skip -- /** * @param string $id * @return null * @throws \yii\web\NotFoundHttpException */ public function actionDownload($id) { if(($model = PdfData::findOne($id)) === null) throw new \yii\web\NotFoundHttpException(Yii::t('app', 'File not found')); $downloadData = new DowmnloadData(); if(!empty($model->pdf_data)) { $downloadData->result = true; $downloadData->validate(); // - $data = $model->downloads_data; // $data[] = $downloadData->attributes; // // array_values ( ) mongodb $model->updateAttributes(['downloads_data' => array_values($data)]); // Yii::$app->response->sendContentAsFile($model->pdf_data, 'we are the champions.pdf', [ 'mimeType' => 'text/xml', 'inline' => true ]); } return null; }
Thus, inside the main model's downloads_data
array, we have all the attributes that were invented in DowmnloadData
, and we can then show and analyze them at will, without multiplying more than the attributes of the main model or the number of collections in the database.
Source: https://habr.com/ru/post/311432/
All Articles