Substring Count in Twig - count

I am looking to use substr_count in Twig, does anything exist already? I want to perform something like this;
<?php
$text = 'This is a test';
echo strlen($text); // 14
echo substr_count($text, 'is'); // 2
I can do an extension but it seems this might be something built in already that I have missed.

How about this?
{%set count = text|split('is')|length-1 %}

This doesn't exist in the list of Twig functions or filters.
You'll have to write your own custom function/filter or try a package (note; I've never used this package so can't comment on it, but was on the first page of Google results).

I went for an extension
namespace AppBundle\Twig;
class SubStrCountExtension extends \Twig_Extension
{
public function getFunctions()
{
return array(
new \Twig_SimpleFunction('substr_count', array($this, 'substr_count')),
);
}
public function getName()
{
return 'substr_count_extension';
}
public function substr_count($str, $char)
{
return substr_count($str, $char);
}
}
And in services.yml
app.twig_extension.substr_count_extension:
class: AppBundle\Twig\SubStrCountExtension
tags:
- { name: twig.extension }

I use solution in Symfony 3.2.8 but in the description does not say this block of code should is inside : services
If you does not make show this error:
There is no extension able to load the configuration for .....
This code should is inside services this is correct:
services:
app.twig_extension.substr_count_extension:
class: AppBundle\Twig\SubStrCountExtension
tags:
- { name: twig.extension }
Finally, the correct use in twig is:
tu placa es: {{substr_count(datos.picoyplaca,4)}}
Regards

Related

Silverstripe 4: Include Template from Filepath

I'm working on a Silverstripe 4 project where we need to include a SS template file from a path.
Here's a simple example giving the gist of what I'm trying to achieve.
class ExampleController extends ContentController
{
public function IncludeTemplateFromFilePath() {
var $FilePath = '/path/to/file';
???
return $output
}
}
Template syntax:
<div>$IncludeTemplateFromFilePath</div>
I've had a look through the SSViewer documentation and looked at the Silverstripe source code but can't work out the correct syntax to make this work.
There are many examples of:
return SSViewer::get_templates_by_class(static::class, $suffix, self::class);
But what is the syntax to get a template from it's filepath?
I believe you can do the following:
public function IncludeTemplateFromFilePath()
{
return SSViewer::execute_string(
file_get_contents('/path/to/Template.ss'),
[
'Content' => 'Value that will be in $Content when used in /path/to/Template.ss'
]
);
}
Reference: http://api.silverstripe.org/4/SilverStripe/View/SSViewer.html#method_execute_string

Twig Date Filter Issue | Wrong output

I am working on Symfony application and using Twig for layout.
I facing wrong output issue i google it but can't find the solution.
I have date & time 201801031400 I used this
{{ val.start_date|date("m/d/Y") }}
but get the wrong output 10/27/8364
When i used this {{ "now"|date("m/d/Y") }} it give me correct output
Thanks in Advance!
You need to a function to Twig to achieve this, you can see how to register an extension here
TwigExtension
namespace My/Project/Twig/Extensions
class ProjectTwigExtension extends Twig_Extension {
public function getFunctions() {
return array(
new Twig_SimpleFunction('convert_api_date', function($date) {
return new DateTime($date);
}),
);
}
public function getName() {
return 'ProjectTwigExtension'; //this is mandatory
}
}
twig
{{ convert_api_date('201801031400') | date('d/m/Y') }}
{{ convert_api_date('201801031400') | date('H:i') }}
Above answer will perfectly alright i just my solution code too.
First Twig date filter not support the 201801031400. so for this you have to make your own extension.
How to create twig extension create twig extention
<?php
// src/AppBundle/Twig/AppExtension.php
namespace AppBundle\Twig;
class DateParserFilter extends \Twig_Extension
{
public function getFilters ()
{
return array(
new \Twig_SimpleFilter('parse_date', array($this, 'parseDate'))
);
}
public function parseDate ($string, $formats)
{
if (is_string($formats))
{
$formats = array($formats);
}
foreach ($formats as $format)
{
$dateTime = \DateTime::createFromFormat($format, $string);
if ($dateTime !== false)
{
return $dateTime;
}
}
return $string;
}
public function getName ()
{
return "parse_date";
}
}
after this use your own extension filter first then use twig builtin date filter example show below :)
{{ val.start_date | parse_date(["YmdHi", "d/m/Y H:i"]) | date("M d, Y") }}
Its depend what you have in my case i have [2018][01][03][14][00] = [Y][m][d][H][i]
hope it will help you :)
source of this extension - link
You have to divide your unix timestamp value by 1000.
I'm still not sure with what it's related, but this operation is used by authoritative online converters, that most likely faced the same problem.
I came to this conclusion thanks to this answer Converting a UNIX Timestamp to Formatted Date String.
Below is the proof that your unix timestamp is correct:
1) from www.freeformatter.com
2) from www.epochconverter.com
The data is slightly different due to the time zone. It must be taken into account.
Write in the comments, why should I divide by 1000. I myself will be interested.

symfony 3.2.4 ... Unable to find template "OCPlatformBundle:Advert:index.html.twig

I am using symfony 3.2.4 (got with console --version).
I am working the openclassroom tutorial.
That controller always return the error below.
Nevertheless, the file below exist with and is accessible.
src/OC/PlatformBundle/Resources/views/Advert/index.html.twig
I got crazy with that. Does someone have an idea ?
Thanks in advance.
<?php
// src/OC/PlatformBundle/Controller/AdvertController.php
namespace OC\PlatformBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
class AdvertController extends Controller
{
public function indexAction()
{
$content = $this->get('templating')->render('OCPlatformBundle:Advert:index.html.twig');
return new Response($content);
}
}
Unable to find template "OCPlatformBundle:Advert:index.html.twig"
(looked into: /var/www/html/symfony/app/Resources/views,
/var/www/html/symfony/vendor/symfony/symfony/src/Symfony/Bridge/Twig/Resources/views/Form).
*
Did you try to create your template in app/Resources/views/Advert/index.html.twig ?
This is a better practice : Store all your application's templates in app/Resources/views/ directory. (From SF doc)...
So, you'll be able to "call" it by this way:
/***/
public function indexAction()
{
return $this->render('Advert/index.html.twig', []);
}
/***/

Share a method with all controllers : Best practice

I'm developing a notification system in symfony2 and I need to get the notifications for every page I'm running.
the trivial solution is to copy the content of the function in every controller and call the function from $this.
How can I make the notification function accessible for every controller? I heard that setting a controller as service is bad practice. what's the best practice then ?
If just using it for output in the template then best approach would be to use a custom TwigFunction and then calling that in a base/layout/extended template like so..
TwigExtension
namespace Acme\NotificationBundle\Twig;
use Acme\NotificationBundle\Provider\NotificationProviderInterface;
class AcmeNotificationExtension extends \Twig_Extension
{
protected $container;
protected $notificationProvider;
public function __construct(
ContainerInterface $container,
NotificationProviderInterface $notificationProvider
)
{
$this->notificationProvider = $notificationProvider;
}
public function getFunctions()
{
return array(
new \Twig_SimpleFunction(
'acme_render_notifications',
array($this, 'renderNotifications')
),
);
}
public function renderNotification($template = 'default:template.html.twig')
{
$notifications = $this->notificationsProvider->getCurrentNotifications();
// Or whatever method provides your notifications
return $this->container->get('templating')->render(
$template,
array('notifications' => $notifications)
);
}
public function getName()
{
return 'acme_notification_extension';
}
}
Services
parameters:
acme.twig.notification_extension.class:
Acme\NotificationBundle\Twig\AcmeNotificationExtension
services:
acme.twig.notification_extension:
class: %acme.twig.notification_extension.class%
arguments:
- #service_container
- #acme.provider.notifcation
// Or what ever your notification provider service is named
tags:
- { name: twig.extension }
This way you would be able to call your notifications in any template using acme_render_notifications() (with the default template) or acme_render_notifications('AcmeOtherBundle:Notifications:in_depth.html.twig') (with a different template if needed) and your controller aren't even touched.
If it was put in a parent template in a block like ..
{% block notifications %}
{{ acme_render_notifications() }}
{% endblock notifications %}
..then it would run on every page unless you had overridden the block in your child class.
The way I would do it, and I think it is among the best practices, is setting up a service with the function then just instantiate it in each controller.
No doubt its bad practice,
Many solutions are possible, Here we will discuss on abstract level
A global utility can be used with different scopes (application, session scope) depending upon the requirements
Make this utility accessible to all available controllers

Displaying currency symbol in twig

How can I display the currency symbol in twig? I saved the numeric value of the symbol like:
for EURO : €
for DOLLAR: $
When I render these values, & is converted to & and the currency symbol does not show. Any idea will be greatly appreciated. Thank you.
To do it well, you've to add a function or a filter which is called as a helper to render currency symbols within your twig templates.
To use the following function,
{{ currency('en_US') }}
You've to add a twig extension as follow,
xxx.twig.your_extension:
class: XXX\YourBundle\Twig\YourExtension
tags:
- { name: twig.extension }
You've then to add a currency function,
namespace XXX\YourBundle\Twig;
class YourExtension extends \Twig_Extension
{
public function getFunctions() {
return array(
'currency' => new \Twig_Function_Method($this, 'currencyFunction'),
);
}
public function currencyFunction($locale) {
$formatter = new \NumberFormatter($locale, \NumberFormatter::CURRENCY);
$symbol = $formatter->getSymbol(\NumberFormatter::CURRENCY_SYMBOL);
return $symbol;
}
public function getName() {
return 'your_extension';
}
}
I figured it out. When rendering, I need to use the raw filter of twig.
It is an old thread, but for the new people coming here, Twig has now an extension for the currency symbols (with new filters |currency_symbol ) as you can see in the documentation

Resources