Formatting in Yii 2.0

I am a bit unhappy how formatting values is currently being handled by Yii. While this is straightforward in most cases, setting custom formatters in place is less than ideal: If I’d want to format e.g. filesizes and money values, I would have to write a custom MyFormatter class and set it in place instead of CFormatter. This absolutely has to be an all-purpose class, which makes sharing formatters between projects/branches quite hard. Also: Setting CFormatter up for i18n is a bit tedious. So can we please:

[list=1]

[*]Have a CFormatter class that respects the locale setting?

[*]Have a better way of registering custom single-purpose formatters? My current idea were to have a CFormatter.customFormatters array holding a list of custom formatters. If a CFormatter.formatXyz method isn’t present, CFormatter would check that list in order for formatters with such a method.

[/list]

I opened an issue on this about a year ago, I did my own CLocaleFormater that uses Yii format functions, and it was very straightforward to write.

Are you referring to ticket #892?

Exactly!

I might be asking for a bit much … But would it be possible to have some locale-aware wrappers for CNumberFormatter? A formatFloat() would be a nice-to-have as well. I’m afraid the current i18n data won’t be sufficient for that, though.

For referece, here is my CLocaleFormatter, it is very simple:




/**

 * CLocaleFormatter class file.

 *

 * @author Rangel Reale <rangelreale@gmail.com>

 * @link http://www.yiiframework.com/

 * @copyright Copyright &copy; 2008-2010 Yii Software LLC

 * @license http://www.yiiframework.com/license/

 */


/**

 * CLocateFormatter formats using the current locale.

 *

 * @author Rangel Reale <rangelreale@gmail.com>

 * @version $Id$

 * @package system.utils

 * @since 1.1.1

 */


class CLocaleFormatter extends CFormatter

{

	/**

	 * @var string the format width to be used to format a date using CDateFormatter formatDateTime function. Defaults to 'medium'.

	 */

	public $dateFormatWidth='medium';

	/**

	 * @var string the format width to be used to format a time using CDateFormatter  formatDateTime function. Defaults to 'medium'.

	 */

	public $timeFormatWidth='medium';


	/**

	 * Formats the value as a date.

	 * @param mixed the value to be formatted

	 * @return string the formatted result

	 * @see dateFormatWidth

	 */

	public function formatDate($value)

	{

		return Yii::app()->dateFormatter->formatDateTime($value, $this->dateFormatWidth, null);

	}


	/**

	 * Formats the value as a time.

	 * @param mixed the value to be formatted

	 * @return string the formatted result

	 * @see timeFormatWidth

	 */

	public function formatTime($value)

	{

		return Yii::app()->dateFormatter->formatDateTime($value, null, $this->timeFormatWidth);

	}


	/**

	 * Formats the value as a date and time.

	 * @param mixed the value to be formatted

	 * @return string the formatted result

	 * @see dateFormatWidth

	 * @see timeFormatWidth

	 */

	public function formatDatetime($value)

	{

		return Yii::app()->dateFormatter->formatDateTime($value, $this->dateFormatWidth, $this->timeFormatWidth);

	}

	

	/**

	 * Formats the value as a number using the locale.

	 * @param mixed the value to be formatted

	 * @return string the formatted result

	 */

	public function formatNumber($value)

	{

		return Yii::app()->locale->numberFormatter->formatDecimal($value, '');

	}

	

	/**

	 * Formats the value as a currency using the locale.

	 * @param mixed the value to be formatted

	 * @return string the formatted result

	 * @see numberFormat

	 */

	public function formatCurrency($value, $currency='')

	{

		return Yii::app()->locale->numberFormatter->formatCurrency($value, '');

	}


	/**

	 * Formats the value as a percentage using  the locale.

	 * @param mixed the value to be formatted

	 * @return string the formatted result

	 * @see numberFormat

	 */

	public function formatPercentage($value)

	{

		return Yii::app()->locale->numberFormatter->formatPercentage($value, '');

	}


	/**

	 * Formats the value as a percentage using  the locale.

	 * @param mixed the value to be formatted

	 * @return string the formatted result

	 * @see numberFormat

	 */

	public function formatStatistical($value)

	{

		return Yii::app()->locale->numberFormatter->formatStatistical($value, '');

	}

	

	/**

	 * Parses the value as a date.

	 * @param mixed the value to be parsed

	 * @return string the parsed result

	 * @see dateFormatWidth

	 */

	public function parseDate($value)

	{

		if ($value!==null && $value!='')

			return CDateTimeParser::parse($value, Yii::app()->locale->getDateFormat($this->dateFormatWidth));

		return null;

	}


	/**

	 * Parses the value as a time.

	 * @param mixed the value to be parsed

	 * @return string the parsed result

	 * @see timeFormatWidth

	 */

	public function parseTime($value)

	{

		if ($value!==null && $value!='')

			return CDateTimeParser::parse($value, Yii::app()->locale->getTimeFormat($this->timeFormatWidth));

		return null;

	}


	/**

	 * Parses the value as a date and time.

	 * @param mixed the value to be parsed

	 * @return string the parsed result

	 * @see dateFormatWidth

	 * @see timeFormatWidth

	 */

	public function parseDatetime($value)

	{

		if ($value!==null && $value!='')

		{

			$dtformat=strtr(Yii::app()->locale->dateTimeFormat,array('{0}'=>Yii::app()->locale->getTimeFormat($this->timeFormatWidth),'{1}'=>Yii::app()->locale->getDateFormat($this->dateFormatWidth)));

			return CDateTimeParser::parse($value, $dtformat);

		}

		return null;

	}

	

	/**

	 * Parse the value as a number formatted by the PHP number_format() function.

	 * @param mixed the value to be parsed

	 * @return string the parsed result

	 * @see numberFormat

	 */

	public function parseNumber($value)

	{

		$nparse=new CNumberParser(Yii::app()->locale);

		return $nparse->parseDecimal($value);

	}

	

	/**

	 * Parses the value as a currency using PHP number_format() function.

	 * @param mixed the value to be parsed

	 * @return string the parsed result

	 * @see numberFormat

	 */

	public function parseCurrency($value, $currency='')

	{

		$nparse=new CNumberParser(Yii::app()->locale);

		return $nparse->parseCurrency($value, $currency);

	}


	/**

	 * Parses the value as a percentage using PHP number_format() function.

	 * @param mixed the value to be parsed

	 * @return string the parsed result

	 * @see numberFormat

	 */

	public function parsePercentage($value)

	{

		$nparse=new CNumberParser(Yii::app()->locale);

		return $nparse->parsePercentage($value);

	}


	/**

	 * Parses the value as a percentage using PHP number_format() function.

	 * @param mixed the value to be parsed

	 * @return string the parsed result

	 * @see numberFormat

	 */

	public function parseStatistical($value)

	{

		$nparse=new CNumberParser(Yii::app()->locale);

		return $nparse->parseStatistical($value);

	}

	

}



Hm, convenient. Thanks for sharing. I know, it isn’t up to par, but have my formatter for filesizes in return :lol:




class FilesizeFormatter extends CFormatter{

	public $suffixes=array(

		'B',

		'KB',

		'MB',

		'GB',

		'TB',

		'PB',

	);

	

	public function formatFilesize($value)

	{

		$e=(int)floor(log($value, 1024));

		if($e > 0 && array_key_exists($e, $this->suffixes))

			return sprintf('%.2f', $value/pow(1024, $e)).$this->suffixes[$e];

		else

			return $this->formatNumber($value).'B';

	}

}