Пробую использовать метод с тэгами, используя модели и события. Что нужно изменить здесь, чтобы можно было добавлять произвольные тэги?
Если использовать такой метод, то теги сохраняются (из базы), но новые нельзя добавить в посте редактирования и сохранить.
Blog.php
<?php
namespace medeyacom\blog\models;
use common\components\behaviors\StatusBehavior;
use Yii;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;
use yii\db\Expression;
use yii\web\UploadedFile;
use yii\helpers\Url;
use yii\helpers\ArrayHelper;
use common\models\ImageManager;
use common\models\User;
/**
* This is the model class for table "blog".
*
* @property integer $id
* @property string $title
* @property string $image
* @property string $text
* @property string $date_create
* @property string $date_update
* @property string $url
* @property integer $status_id
* @property integer $sort
*/
class Blog extends ActiveRecord {
const STATUS_LIST = ['off','on'];
const IMAGES_SIZE = [
['50','50'],
['800',null],
];
public $tags_array;
public $file;
/**
* @inheritdoc
*/
public static function tableName()
{
return 'blog';
}
public function behaviors()
{
return [
'timestampBehavior'=>[
'class' => TimestampBehavior::className(),
'createdAtAttribute' => 'date_create',
'updatedAtAttribute' => 'date_update',
'value' => new Expression('NOW()'),
],
'statusBehavior'=> [
'class' => StatusBehavior::className(),
'statusList'=> self::STATUS_LIST,
]
];
}
/**
* @inheritdoc
*/
public function rules()
{
return [
[['title', 'url'], 'required'],
[['text'], 'string'],
[['url'], 'unique'],
[['status_id', 'sort'], 'integer'],
[['sort'], 'integer','max'=>99, 'min'=>1],
[['title', 'url'], 'string', 'max' => 150],
[['image'], 'string', 'max' => 100],
[['image'], 'file', 'extensions'=>'jpg, gif, png, svg'],
[['file'], 'image'],
[['tags_array','date_create','date_update'],'safe'],
];
}
/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'title' => 'Заголовок',
'text' => 'Текст',
'url' => 'ЧПУ',
'status_id' => 'Статус',
'sort' => 'Сортировка',
'date_update' => 'Обновлено',
'date_create' => 'Создано',
'tags_array' => 'Тэги',
'tagsAsString' => 'Тэги',
'image' => 'Картинка',
'file' => 'Картинка',
'author.username'=>'Имя Автора',
'author.email'=>'Почта Автора',
];
}
public function getAuthor () {
return $this->hasOne (User::className(),['id'=>'user_id']);
}
public function getImages()
{
return $this->hasMany(ImageManager::className(), ['item_id' => 'id'])->andWhere(['class'=>self::tableName()])->orderBy('sort');
}
public function getImagesLinks()
{
return ArrayHelper::getColumn($this->images,'imageUrl');
}
public function getImagesLinksData()
{
return ArrayHelper::toArray($this->images,[
ImageManager::className() => [
'caption'=>'name',
'key'=>'id',
]]
);
}
public function getBlogTag () {
return $this->hasMany(BlogTag::className(),['blog_id'=>'id']);
}
public function getTags()
{
return $this->hasMany(Tag::className(),['id'=>'tag_id'])->via('blogTag');
}
public function getTagsAsString()
{
$arr = \yii\helpers\ArrayHelper::map($this->tags,'id','name');
return implode (', ',$arr);
}
public function getSmallImage()
{
if($this->image){
$path = str_replace('admin.','',Url::home(true)).'uploads/images/blog/50x50/'.$this->image;
}else{
$path = str_replace('admin.','', Url::home(true)).'uploads/images/ss.jpg';
}
return $path;
}
public function afterFind()
{
parent::afterFind();
$this->tags_array = $this->tags;
}
public function beforeSave ($insert)
{
if ($file = UploadedFile::getInstance($this,'file')) {
$dir = Yii::getAlias('@images').'/blog/';
if (!is_dir($dir . $this->image)) {
if (file_exists($dir.$this->image)){
unlink($dir.$this->image);
}
if (file_exists($dir.'50x50/'.$this->image)) {
unlink($dir.'50x50/'.$this->image);
}
if (file_exists($dir. '800x/'.$this->image)) {
unlink($dir.'800x/'.$this->image);
}
}
$this->image = strtotime ('now').'_'.Yii::$app->getSecurity()->generateRandomString(6) .'.'. $file->extension;
$file ->saveAs($dir.$this->image);
$imag = Yii::$app->image->load($dir.$this->image);
$imag ->background ('#fff',0);
$imag ->resize ('50','50', Yii\image\drivers\Image::INVERSE);
$imag ->crop ('50','50');
$imag ->save($dir.'50x50/'.$this->image, 90);
$imag = Yii::$app->image->load($dir.$this->image);
$imag->background('#fff',0);
$imag->resize('800',null, Yii\image\drivers\Image::INVERSE);
$imag->save($dir.'800x/'.$this->image, 90);
}
return parent::beforeSave($insert);
}
public function afterSave ($insert, $changedAttributes)
{
parent::afterSave($insert, $changedAttributes);
$arr = \yii\helpers\ArrayHelper::map($this->tags,'id','id');
foreach ($this->tags_array as $one) {
if(!in_array($one,$arr)){
$model = new BlogTag();
$model->blog_id = $this->id;
$model->tag_id = $one;
$model->save();
}
if(isset($arr[$one])) {
unset ($arr[$one]);
}
}
BlogTag::deleteAll(['tag_id'=>$arr]);
}
public function beforeDelete()
{
if (parent::beforeDelete()) {
$dir = Yii::getAlias('@images').'/blog/';
if(file_exists($dir.$this->image)){
unlink($dir.$this->image);
}
foreach (self::IMAGES_SIZE as $size){
$size_dir = $size[0].'x';
if($size[1] !== null)
$size_dir .= $size[1];
if(file_exists($dir.$this->image)){
unlink($dir.$size_dir.'/'.$this->image);
}
}
BlogTag::deleteAll(['blog_id'=>$this->id]);
return true;
} else {
return false;
}
}
}
Но когда пробую реализовать сохранение тегов другим методом, то ничего не сохраняется. 2 вариант кода ниже.
Попробую объяснить как бы хотелось реализовать, хотя сам не оч.понимаю логику))
public function afterFind()
{
$this->newtags = \yii\helpers\ArrayHelper::map($this->tags,'tag','tag');
}
function ‘afterFind’ происходит когда загрузились данные из базы в модель, заполнили данные модели т.е. когда в посте редактирования нажали ‘update’, то туда должны подтягиваться теги, которые связаны (а они, по идее, хранятся в ‘newtags’ , а изначально он = ‘null’ и соответственно, в afterFind мы их наполняем. При этом дёргая связь "Get tags ’ После этого, должны получить из неё массив $this ->tags (т.к. это ‘HasMany’ и дальше надо сделать из этого массив, чтобы скормить его vidget Select 2
Для этого берем данные $this ->tags с помощью ArrayHelper:: map- передаем данные и говорим, что нужно, чтобы был атрибут ‘tag’ из модели Таг.php ($property tag ) - он же был и ключем и значением.- это так надо для Select 2 т.е. он заполняется и во views нужно передать.
У меня есть таблица “blog_tag’ и связь 'getBlogTag”- она как-бы промежуточная между ‘blog’ и ‘tag’ и в ней есть ‘blog_id’ и 'tag_id"
Blog.php
<?php
namespace medeyacom\blog\models;
use common\components\behaviors\StatusBehavior;
use Yii;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;
use yii\db\Expression;
use yii\helpers\ArrayHelper;
use yii\helpers\Url;
use yii\web\UploadedFile;
use common\models\User;
use common\models\ImageManager;
/**
* This is the model class for table "blog".
*
* @property integer $id
* @property string $title
* @property string $text
* @property string $image
* @property string $url
* @property string $date_create
* @property string $date_update
* @property integer $status_id
* @property integer $sort
*/
class Blog extends ActiveRecord
{
const STATUS_LIST = ['off','on'];
const IMAGES_SIZE = [
['50','50'],
['800',null],
];
public $tags_array;
public $file;
public $newtags;
/**
* @inheritdoc
*/
public static function tableName()
{
return 'blog';
}
public function behaviors()
{
return [
'timestampBehavior'=>[
'class' => TimestampBehavior::className(),
'createdAtAttribute' => 'date_create',
'updatedAtAttribute' => 'date_update',
'value' => new Expression('NOW()'),
],
'statusBehavior'=>[
'class' => StatusBehavior::className(),
'statusList' => self::STATUS_LIST,
]
];
}
/**
* @inheritdoc
*/
public function rules()
{
return [
[['title', 'url'], 'required'],
[['text'], 'string'],
[['url'], 'unique'],
[['status_id', 'sort'], 'integer'],
[['sort'], 'integer', 'max'=>99, 'min'=>1],
[['title', 'url'], 'string', 'max' => 150],
[['image'], 'string', 'max' => 100],
[['file'], 'image'],
[['newtags'], 'safe'],
[['tags_array','date_create','date_update'], 'safe'],
];
}
/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'title' => 'Заголовок',
'text' => 'Текст',
'url' => 'ЧПУ',
'status_id' => 'Статус',
'sort' => 'Сортировка',
'tags_array' => 'Теги',
'image' => 'Картинка',
'file' => 'Картинка',
'tagsAsString' => 'Теги',
'author.username' => 'Имя Автора',
'author.email' => 'Почта Автора',
'date_update' => 'Обновлено',
'date_create' => 'Создано',
'smallImage'=> 'Картинка',
'newtags' => 'теги',
];
}
public function getAuthor(){
return $this->hasOne(User::className(),['id'=>'user_id']);
}
public function getImages()
{
return $this->hasMany(ImageManager::className(), ['item_id' => 'id'])->andWhere(['class'=>self::tableName()])->orderBy('sort');
}
public function getImagesLinks()
{
return ArrayHelper::getColumn($this->images,'imageUrl');
}
public function getImagesLinksData()
{
return ArrayHelper::toArray($this->images,[
ImageManager::className() => [
'caption'=>'name',
'key'=>'id',
]]
);
}
public function getBlogTag(){
return $this->hasMany(BlogTag::className(),['blog_id'=>'id']);
}
public function getTags()
{
return $this->hasMany(Tag::className(), ['id' => 'tag_id'])->via('blogTag');
}
public function getTagsAsString()
{
$arr = \yii\helpers\ArrayHelper::map($this->tags,'id','name');
return implode(', ',$arr);
}
public function getSmallImage()
{
if($this->image){
$path = str_replace('admin.','',Url::home(true)).'uploads/images/blog/50x50/'.$this->image;
}else{
$path = str_replace('admin.','',Url::home(true)).'uploads/images/ss.jpg';
}
return $path;
}
public function beforeDelete()
{
if (parent::beforeDelete()) {
$dir = Yii::getAlias('@images').'/blog/';
/* if($this->image != '')*/
/* if(!empty($this->image))*/
if(file_exists($dir.$this->image)){
unlink($dir.$this->image);
}
/* if($this->image && file_exists($dir.$this->image))
if (isset($this->image) && file_exists($idr.$this->image)){
unlink($dir.$this->image);}*/
/* if(file_exists($dir.$this->image)){
unlink($dir.$this->image);*/
foreach (self::IMAGES_SIZE as $size){
$size_dir = $size[0].'x';
if($size[1] !== null)
$size_dir .= $size[1];
if(file_exists($dir.$this->image)){
unlink($dir.$size_dir.'/'.$this->image);
}
}
BlogTag::deleteAll(['blog_id'=>$this->id]);
return true;
} else {
return false;
}
}
public function afterFind()
{
/* parent::afterFind();
$this->tags_array = $this->tags;*/
$this->newtags = \yii\helpers\ArrayHelper::map($this->tags,'tag','tag');
}
public function afterSave($insert, $changedAttributes)
{
/* parent::afterSave($insert, $changedAttributes);
$arr = \yii\helpers\ArrayHelper::map($this->tags,'id','id');
foreach ($this->tags_array as $one){
if(!in_array($one,$arr)){
$model = new BlogTag();
$model->blog_id = $this->id;
$model->tag_id = $one;
$model->save();
}
if(isset($arr[$one])){
unset($arr[$one]);
}*/
if (is_array($this->newtags)) {
$old_tags = ArrayHelper::map($this->tags,'tag','id');
foreach ($this ->newtags as $one_new_tag) {
if (isset($old_tags[$one_new_tag])) {
unset($old_tags[$one_new_tag]);
} else{
if($tg = $this->createNewTag($one_new_tag)){
Yii::$app->session->addFlash('success','добавлен тег' . $one_new_tag);
}else{
Yii::$app->session->addFlash('error','тег' . $one_new_tag . 'тег не добавился');
}
}
}
BlogTag::deleteAll(['and',['blog_id'=>$this->id],['tag_id'=>$old_tags]]);
}else{
/*BlogTag::deleteAll(['blog_id'=>$this->id]);*/
BlogTag::deleteAll(['tag_id'=>$arr]);
}
}
private function createNewTag ($new_tag) {
if(!$tag = Tag::find()->andWhere(['tag'=>$new_tag])->one()){
$tag = new Tag();
$tag ->tag = $new_tag;
if(!$tag->save()) {
$tag =null;
}
}
if ($tag instanceof Tag) {
$blog_tag = new BlogTag();
$blog_tag->blog_id = $this->id;
$blog_tag->tag_id = $tag->id;
if($blog_tag->save())
return $blog_tag->id;
}
return false;
}
public function beforeSave($insert)
{
if($file = UploadedFile::getInstance($this, 'file')){
$dir = Yii::getAlias('@images').'/blog/';
if(file_exists($dir.$this->image)){
unlink($dir.$this->image);
}
if(file_exists($dir.'50x50/'.$this->image)){
unlink($dir.'50x50/'.$this->image);
}
if(file_exists($dir.'800x/'.$this->image)){
unlink($dir.'800x/'.$this->image);
}
$this->image = strtotime('now').'_'.Yii::$app->getSecurity()->generateRandomString(6) . '.' . $file->extension;
$file->saveAs($dir.$this->image);
$imag = Yii::$app->image->load($dir.$this->image);
$imag->background('#fff',0);
$imag->resize('50','50', Yii\image\drivers\Image::INVERSE);
$imag->crop('50','50');
$imag->save($dir.'50x50/'.$this->image, 90);
$imag = Yii::$app->image->load($dir.$this->image);
$imag->background('#fff',0);
$imag->resize('800',null, Yii\image\drivers\Image::INVERSE);
$imag->save($dir.'800x/'.$this->image, 90);
}
return parent::beforeSave($insert);
}
}