I am using ZF2 for my project. And this is an e-commerce site. So I am dealing with currencies.
In ZF2 there is a view helper named currencyFormat()
I am from Turkey so my main currency format is TRY (This is the ISO code of Turkish Lira). But in Turkey we do not use TRY as Currency icon. The icons are "$" for USD, € for "EUR" and "TL" for Turkish Lira (TRY).
So when I format a currency for TRY I am doing it like this in view script:
<?php
echo $this->currencyFormat(245.40, 'TRY', 'tr_TR');
?>
The result of this code is "245.40 TRY". But it has to be "245.40 TL"
Is there a way to solve this? I do not want to use replacement function.
I'm guessing when you say I do not want to use replacement function you mean it would be laborious to do a str_replace every time you call the helper. The solution would be to replace the helper with your own. Here's a quick how to
First create a helper of your own which extends the existing helper and handles the replacement if necessary...
<?php
namespace Application\View\Helper;
use Zend\I18n\View\Helper\CurrencyFormat;
class MyCurrencyFormat extends CurrencyFormat
{
public function __invoke(
$number,
$currencyCode = null,
$showDecimals = null,
$locale = null
) {
// call parent and get the string
$string = parent::__invoke($number, $currencyCode, $showDecimals, $locale);
// format to taste and return
if (FALSE !== strpos($string, 'TRY')) {
$string = str_replace('TRY', 'TL', $string);
}
return $string;
}
}
Then in Module.php, implement the ViewHelperProviderInterface, and provide it with details of your helper
//Application/Module.php
class Module implements \Zend\ModuleManager\Feature\ViewHelperProviderInterface
{
public function getViewHelperConfig()
{
return array(
'invokables' => array(
// you can either alias it by a different name, and call that, eg $this->mycurrencyformat(...)
'mycurrencyformat' => 'Application\View\Helper\MyCurrencyFormat',
// or if you want to ALWAYS use your version of the helper, replace the above line with the one below,
//and all existing calls to $this->currencyformat(...) in your views will be using your version
// 'currencyformat' => 'Application\View\Helper\MyCurrencyFormat',
),
);
}
}
As of 1 March 2012 sign for Turkish Lira is TRY. http://en.wikipedia.org/wiki/Turkish_lira
So ZF outputs it right I think.
Related
URLSegmentFilter has a static array $default_replacements which holds, among others, the string to convert ampersands to (from & to -and-) for URL's.
I'm trying to extend the class and overwrite this static to translate the ampersand convert (only value is english and).
How can I overwrite the owner static for this goal?
class URLSegmentFilterExtension extends Extension {
private static $default_replacements = array(
'/&/u' => '-and-', // I need to translate this using _t()
'/&/u' => '-and-', // And this one
'/\s|\+/u' => '-',
'/[_.]+/u' => '-',
'/[^A-Za-z0-9\-]+/u' => '',
'/[\/\?=#]+/u' => '-',
'/[\-]{2,}/u' => '-',
'/^[\-]+/u' => '',
'/[\-]+$/u' => ''
);
}
First of all: The URLSegmentFilter mainly operates in the CMS context, where you usually just have a single locale (depending on the settings of the editing Member). So using _t() alone might not be very helpful? So you'd probably have to get the current editing locale (assuming you're using Fluent or Translatable) and set the locale for translations temporarily.
I don't see a way to hook in translations via an Extension there. I think you'd be better off creating a custom subclass and use it via Injector.
Something like this should work:
<?php
class TranslatedURLSegmentFilter extends URLSegmentFilter
{
public function getReplacements()
{
$currentLocale = i18n::get_locale();
$contentLocale = Translatable::get_current_locale();
// temporarily set the locale to the content locale
i18n::set_locale($contentLocale);
$replacements = parent::getReplacements();
// merge in our custom replacements
$replacements = array_merge($replacements, array(
'/&/u' => _t('TranslatedURLSegmentFilter.UrlAnd', '-and-'),
'/&/u' => _t('TranslatedURLSegmentFilter.UrlAnd', '-and-')
));
// reset to CMS locale
i18n::set_locale($currentLocale);
return $replacements;
}
}
Then you have to enable the custom URLSegmentFilter via config by putting something like this in your mysite/_config/config.yml file:
Injector:
URLSegmentFilter:
class: TranslatedURLSegmentFilter
Update: The above example assumes you're using the Translatable module. If you're using Fluent, replace the following line:
$contentLocale = Translatable::get_current_locale();
with:
$contentLocale = Fluent::current_locale();
You can update configuration dynamically in mysite/_config.php
$defaultReplacements = Config::inst()->get('URLSegmentFilter', 'default_replacements');
$translatedAnd = _t('URLSegmentFilter.And','-and-');
$defaultReplacements['/&/u'] = $translatedAnd;
$defaultReplacements['/&/u'] = $translatedAnd;
Config::inst()->Update('URLSegmentFilter', 'default_replacements', $defaultReplacements);
I want to show the date format like: 10月09日, 周三 (which means 10/9, Wed.)
and my data is UNIX time like [message.time]: 1380813820000
so this is what I do in twig:
{{ (message.time/1000)|date("m月d日, 周w") }}
But it show me: 10月09日,周3, Because date "w" are numbers, not Chinese text.
so can I do anything by Twig to converse the text format?
thanks
The underlying problem is, that Twig uses the DateTime::format method, which does not support locales or (as far as I know) any other type of functionality to translate the names of the weekdays.
There are three solutions:
Use strftime, which supports locales (and thus localized weekday-names).
If you can use the intl extension of PHP, then you can use the Twig-extensions which comes with a intl extension for Twig.
You translate the weekdays by yourself.
Plus to use your preferred solution in a Twig-template, you have to extend the functionality of Twig.
Using strftime and setlocale
The following (rather large) code implements the strftime solution:
<?php
// inspired by phpdude:
// https://github.com/fabpot/twig/issues/378#issuecomment-4698225
class DateTimeHelper_Twig extends Twig_Extension
{
public function getFilters()
{
return array(
'datetime' => new Twig_Filter_Method($this, 'datetime',
array('needs_environment' => true)),
);
}
// This uses `strftime` which makes use of the locale. The format is not
// compatible with the one of date() or DateTime::format().
public function datetime(Twig_Environment $env, $date,
$format = "%B %e, %Y %H:%M", $timezone = null)
{
$date = twig_date_converter($env, $date, $timezone);
return strftime($format, $date->getTimestamp());
}
public function getName()
{
return 'DateTimeHelper';
}
}
$loader = new Twig_Loader_String();
$twig = new Twig_Environment($loader);
// Call the setlocale before you use the `datetime` in your templates.
// This only needs to be done once per request.
// If you already have a locale configured in your environment,
// you can replace this with setlocale(LC_TIME, ""); - that way the
// locale of your environment is used.
setlocale(LC_TIME, "zh_CN.UTF-8");
// Add the extension to Twig like that:
$twig->addExtension(new DateTimeHelper_Twig());
$message = array('time' => time() * 1000);
// use the `datetime` filter with %a which gets replaced by the short weekday name of
// the current locale.
echo $twig->render('{{ (message.time/1000)|datetime("%m月%d日, 周%a") }}',
array('message' => $message)), PHP_EOL;
This code shows 10月09日, 周三 on my system (after I installed the debian package locales-all ;-) ).
Of course, locales come with a list of restrictions you probably need to be aware of:
You have to use the correct locale (probably with UTF-8) and the locale you need has to be installed on all the systems which use your code.
Also this solution is not fully platform-independent (on windows setlocale works different/gives different results). Check out the PHP-manual of setlocale
It's easy to screw things up.
Using intl and the Twig-extensions
If you can use the intl extensions and the "Twig-extensions"-package, you have to use localizeddate instead of date:
// add the extension like that
$twig->addExtension(new Twig_Extensions_Extension_Intl());
$message = array('time' => time() * 1000);
echo $twig->render('{{ (message.time/1000)|localizeddate("none", "none", "zh", null, "MM月dd日, eee") }}', array('message' => $message)), PHP_EOL;
That code also shows 10月09日, 周三 - it even adds the 周-thingie automatically.
Of course, the date-format here is also different - check out the ICU user guide.
You can try this code if the setlocale function cannot working on you system.
<?php
require_once dirname(__FILE__).'/vendor/autoload.php';
$loader = new Twig_Loader_String();
$twig = new Twig_Environment($loader);
$twig->addFilter(new Twig_SimpleFilter('format_date', function($value) {
$weekdays = array('日','一','二','三','四','五','六');
return sprintf("%s, 周%s", date("m月d日"), $weekdays[date("w")]);
}));
echo $twig->render('{{ time_at | format_date }}', array(
'time_at' => 1380813820000/1000
));
I found a quick filter replace , here is the code snippet:
<div class="date"><span>{{ (create_time/1000)|date("m月d日,周D")|replace({'Mon':'一','Tue':'二','Wed':'三','Thu':'四','Fri':'五','Sat':'六','Sun':'日'}) }}</span></div>
I'd like to tweak the Illuminate\Html\FormBuilder class in Laravel 4 to automatically include a CSS class with each input, corresponding to the type of input, e.g. <input type="radio" class="radio" />
I've created my own class, which extends the original:
namespace Shady;
class FormBuilder extends Illuminate\Html\FormBuilder {
public function input($type, $name, $value = null, $options = array()) {
$options['class'] = isset($options['class'])
? implode(' ', array_unique(array_merge(array($type), explode(' ', $options['class']))))
: $type;
parent::input($type, $name, $value, $options);
}
}
Now, the question is, how do I get Laravel 4 to use it?
I've had a look in app/config/app.php, and there's only a reference to the HTML Fascade class. I'm not sure how or where that translates into the Illuminate\Support\ServiceProvider\HtmlServiceProvider class, but that class hard-codes the FormBuilder class, ala
protected function registerFormBuilder()
{
$this->app['form'] = $this->app->share(function($app)
{
$form = new FormBuilder($app['html'], $app['url'], $app['session']->getToken());
return $form->setSessionStore($app['session']);
});
}
I'm wondering whether I can either trick it into loading my version of the class somehow? Or if not, how else do I add in this functionality smoothly and neatly? Cheers.
There's a new section in the docs about extending Laravel that should help: http://laravel.com/docs/extending
I also tried battling this issue as I wanted to do exactly the same as you, partly out of interest of extending core classes but also to stop repeating myself (DRY) from passing the same two classes in the second (options) array parameter each time I wanted a submit button, but to no avail.
Instead, I opted in the end to make a HTML macro, as others suggested above but here's an actual example for others who might come across this.
Example:
Save the following code to app/macros.php (this file doesn't exist by default so create it):
HTML::macro( 'submit', function( $value = null, $options = array() )
{
$options = array_merge( $options, array( 'class' => 'btn btn-info' ) );
return Form::input( 'submit', null, $value, $options );
});
Now include macros.php by adding require app_path().'/macros.php'; to the bottom of app/start/global.php.
And now in your views, instead of:
Form::submit( 'Submit', array( 'class' => 'btn btn-info' ) );
Use:
HTML::submit( 'Submit' );
And it will produce the same submit button, allowing the same parameters as Laravel by default but will automatically add btn and btn-info classes to the button, without you needing to repeat yourself each time. Hope this helps someone. =)
It's unnecessary to extend the HTML helper class. Instead, use CSS selectors to pick the elements.
As for making your own methods, you can use the HTML::macro()
See: http://laravel.com/api/source-class-Illuminate.Html.HtmlBuilder.html#32
And: http://laravel.com/api/source-class-Illuminate.Html.HtmlBuilder.html#390
I have the latest codeigniter version, and was wondering how can i get the segments in a url by their parameter name. For instance, here is a sample url:
www.somewebsitedomain.com/param1=something/param2=somethingelse/
now lets say i want to get the value for 'param1', which is 'something', how would i do so using the uri class?
Because by default the uri class only gets segments by number, or the order in which they appear, but i want to get segments by the parameter name in that segment. Or in general just get the parameter value. Hope that makes sense...
You could do $this->uri->uri_to_assoc(n) which will give something like the following
[array]
(
'name' => 'joe'
'location' => 'UK'
'gender' => 'male'
)
Then just just the param name you would like.
Source: http://codeigniter.com/user_guide/libraries/uri.html
You could actually put them as GET vars and use the Input Class:
$param = $this->input->get('param1'); // something
or you can do:
$params = $this->input->get(); // array('param1' => 'something', 'param2' => 'somethingelse')
to get all the parameters
I'm not sure this is what you're asking, but in many applications, URLs follow the form www.domain.com/controller/method/key1/value1/key2/value2. So I decided to extend the CI_URI class to return the value of any "key".
If you put this in your application/core folder, in a file named, MY_URI.php, it extends the built-in URI class:
class MY_URI extends CI_URI {
/* call parent constructor */
function __construct() {
parent::__construct();
}
/* return value of the URI segment
which immediately follows the named segment */
function getNamed($str=NULL) {
$key = array_search($str, $this->segments);
if ($key && isset($this->segments[$key+1])) {
return $this->segments[$key+1];
}
return false;
}
}
Then if your URLs are in the form
www.somewebsitedomain.com/param1/something/param2/somethingelse/
you can call this function as follows:
$this->uri->getNamed('param1) - returns "something"
$this->uri->getNamed('param2) - returns "somethingelse"
Can I basically do something like:
register_function_hook('myFunctionHook');
so then when any function is run:
functionA(); //The hook runs myFunctionHook();
anoterFunction(); //The hook runs myFunctionHook();
Class::functionA(); //The hook runs myFunctionHook();
Does such a thing exist?
-- Edit --
What I want to do is to get a breakdown of durations of each function. Ie. Performance Tuning. I want to get an idea of what takes all the time without installing xDebug on my Apache server, however I don't know if it is possible.
It's possible with register_tick_function(), also check this comment on the PHP manual:
$script_stats = array();
$time = microtime(true);
function track_stats(){
global $script_stats,$time;
$trace = debug_backtrace();
$exe_time = (microtime(true) - $time) * 1000;
$func_args = implode(", ",$trace[1]["args"]);
$script_stats[] = array(
"current_time" => microtime(true),
"memory" => memory_get_usage(true),
"file" => $trace[1]["file"].': '.$trace[1]["line"],
"function" => $trace[1]["function"].'('.$func_args.')',
"called_by" => $trace[2]["function"].' in '.$trace[2]["file"].': '.$trace[2]["line"],
"ns" => $exe_time
);
$time = microtime(true);
}
declare(ticks = 1);
register_tick_function("track_stats");
// the rest of your project code
// output $script_stats into a html table or something
This "hooks" to everything, not just functions but I think it fits your purpose.
No, its not possible the way you like
But You can achieve something close with inheritance.
class Vehicle {
function __construct() {
$this->hookFunction();
}
function hookFunction() {
//
}
}
class Car extends Vehicle {
}
Class Toyota extends Car {
}
new Toyota(); // will you hook function
// this exclude static call to member functions, or other inline functions.
What you looking for is called profiler. And PQP looks like one, which is standalone.
Instead of polluting the code, you should use a real Profiler, like that one provided by xdebug
Not sure if the Topic Starter needs this anymore, but perhaps others can still benefit from this.
There is a PHP lib, written completely in PHP, that allows you to do exactly what you want.
Here's an article about how it works, including the source code:
http://phpmyweb.net/2012/04/26/write-an-awesome-plugin-system-in-php/
It allows you to register a function from a class to be hooked. So it basically executes your code first, and then you determine wether you want to call the original function too after your code has been executed.