Немного Уииишечки

Вот попалось немного уии-шного проекта, пришлось встряхнуть пыль и вспомнить каково он работать с фреймворком, а то эти друпалы со своей системой меню иногда бесят.

На существующем сайте нужно запилить пару фичей, из интересного пока могу только поделится двумя из них: первое — по заданному адресу нужно отдавать изображение последнего поста, и второе — в одной колонке модели сохранять массив данных, не спрашивайте зачем последнее, просто так получилось.

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

/**
 * Retrive latest post image.
 */
public function actionLatest()
{
	$criteria=new CDbCriteria(array(
		// Тут разные критерии запроса модели...
	));
	$post=Post::model()->find($criteria);

	$path=Yii::getPathOfAlias('webroot.files') . '/'; // В папке files у меня хранятся картинки
	$file=$path.$post->image; // Колонка в базе у меня image, в ней хранится название картинки

	if (file_exists($file))
	{
		$mime = exif_imagetype($file);
		if ($mime) {
			header("Content-Type: ".image_type_to_mime_type($mime)); // Отправляем заголовком тип данных
			header("Content-Length: ".filesize($file)); // И размер файла
			readfile($file); // Можно конечно и через fpassthru но тогда нужно делать fopen и в моем случае будет не оптимально
		}
	}
}

Вот и все, теперь по запросу нашего контроллера и действия latest браузер будет показывать картинку. А если нужно чтобы было предложение сохранить файл или еще что-то то можно использовать заголовок x-sendfile для сервера lighttpd или для apache с модулем mod_xsendfile, или если у вас nginx то есть альтернатива X-Accel-Redirect. Вот и все, с первой задачей разобрался. На очереди другая.

А вторая это не совсем задача, это скорее вариант решения, и скорее всего он не очень удачен и больше смахивает на костыль но лучше быстрое и рабочее решение чем этот дурацкий перфекционизм… Суть проблемы в том что есть модель данных и одно из свойств этой модели может иметь несколько значений. Делать отдельную таблицу для этих значений мне не очень хотелось, к тому же они не нужны были не для поиска, не для обработки или для чего-то еще, просто обычные поля с дополнительной информацией. Да-да, знаю что все возможно и в будущем они могут использоваться и для поиска и для всего остального, но это будет в будущем и там еще как выкрутится!

Первым делом решил как сохранять список полей, а учитывая что в mysql нет нормальной поддержки массивов, хотя в sql3 стандарте она описана, то решил хранить строкой. Да, простой строчкой текста, разделяя значения запятыми с пробелом. А чтобы это все дело нормально работало в модели добавил пару методов: beforeSave — чтобы конвертировать массив в строку, и afterFind — где конвертировал обратно в массив. Ну и последняя условность, поле назовем list:

/**
 * Convert field `list` to string before saving model.
 */
protected function beforeSave()
{
	if(parent::beforeSave())
	{
		if(is_array($this->list))
			$this->list=join(', ', this->list);
		return true;
	}
	else
	return false;
}

/**
 * Covrert field `list` to array after fetched from db.
 */
protected function afterFind()
{
	parent::afterFind();
	if(!is_array($this->list))
		$this->list=explode(', ', $this->list);
}

Это в принципе и все решение, но его можно дополнить если нужно будет работать с моделью после сохранения, тогда нужно будет снова преобразовать в массив.

p.s. С yii работаю не так долго, так что еще не привык ко всему, а учитывая что стандартов для стиля кода я так и не нашел, то иногда могу и наговнокодить 😀

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *