I have some variables in twig-templates, so think use global scope for it.
config.yml
twig:
globals:
varA: "#wf.autoload.getA"
varB: "#wf.autoload.getB"
In service yml I have:
services.yml
wf.autoload:
class: Scope\WfBundle\WfAutoloadService
arguments: ["#doctrine.orm.entity_manager"]
WfAutoloadService class have public function for getting variables
class WfAutloadService {
...
public function getA(){
return ...;
}
public function getB(){
return ...
}
...
}
My idea doesn't work. Method of #=service(wf.autoload).getA() also doesn't work.
Is it possible? Or it bad idea and bad practice?
Thanks
If getA() and getB() returns object, you can use a factory when configuring your service:
services:
wf.autoload:
class: Scope\WfBundle\WfAutoloadService
arguments: ["#doctrine.orm.entity_manager"]
wf.autoload.getA:
class: A
factory: ["#wf.autoload", getA]
And set the global twig:
twig:
globals:
varA: "#wf.autoload.getA"
I you want to use this functions in many twig templates you can create a twig extension
For example :
class MyExtensions extends \Twig_Extension
{
public function getFunctions()
{
return array(
'getA' => new \Twig_Function_Method($this, 'getA', array('is_safe' => array('html')))
);
}
public function getA() // you can if you want pass parameters
{
//your code
return ...
}
}
Declare it as service :
myextensions.twig_extension:
class: Project\YourBundle\Twig\MyExtensions
public: false
tags:
- { name: twig.extension }
And call it in yours twig template :
{{ getA() }}
Related
What do I need to in order to make this work?
interface BaseServiceInterface {
public function getRecords();
}
class BaseService implements BaseServiceInterface{
public function getRecords(){
return "bla";
}
}
class SomeOtherService{
private $baseService;
public function __construct(BaseServiceInterface $baseService){
$this->baseService = $baseService;
}
}
my service.yml looks like this:
base_service:
class: AppBundle\Service\BaseService
autowire: true
When I try to run this I get:
Cannot autowire argument 1 for AppBundle\Service\SomeOtherService because the type-hinted class does not exist (Class BaseServiceInterface does not exist).
autowire does not work directly with interface.
you need to create the service alias to make it works.
services:
AppBundle\Service\BaseServiceInterface: '#AppBundle\Service\BaseService'
reference: https://symfony.com/doc/current/service_container/autowiring.html#working-with-interfaces
I use Twig and I have a header in each file with some variables.
How I can include the header in each file without always calling the variables ?
I've a file, in it, I extends the layout.html.twig and in this layout I extends the header.html.twig
on the header I've some variables sent by the controller. but the variables are executed only if I go to the header view...
How can I do to include the header view with twig?
Despite the fact that is really difficult to understand what exactly you're after, probably, you're looking for a way to set global variables.
Twig globals allows you to set global variables.
Set static variables:
# app/config/config.yml
twig:
# ...
globals:
variables: {}
If you need more than static variables, create your own extension:
<?php
namespace Example\CommonBundle\Twig;
use \Doctrine\ORM\EntityRepository;
class TooltipsExtension extends \Twig_Extension
{
protected $bookingsTooltip;
public function __construct(EntityRepository $bookingsTooltip)
{
$this->bookingsTooltip = $bookingsTooltip;
}
public function getGlobals()
{
return array(
'tooltips' => $this->bookingsTooltip->getTooltips(),
);
}
public function getName()
{
return 'tooltips';
}
}
Register twig extension:
# app/config/services.yml
example.tooltips_extension:
class: Example\CommonBundle\Twig\TooltipsExtension
public: false
arguments:
- #example.tooltips
tags:
- { name: twig.extension }
Access variables inside your html:
{{ dump(tooltips) }}
Error:
...ThemeValidator::__construct() must be of the type array, null given...
For some reason the Service is not being called, but the Class is being loaded directly.
validation.yml
theme:
- NotBlank: ~
- DashboardHub\Bundle\AppBundle\Validator\Constraints\ThemeValidator: ~
Validator Class
<?php
namespace DashboardHub\Bundle\AppBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
class ThemeValidator extends ConstraintValidator
{
protected $config;
public function __construct(array $config)
{
$this->config = $config;
}
public function validatedBy()
{
return 'theme.validator';
}
public function validate($value, Constraint $constraint)
{
var_dump($this->config); exit;
}
// ...
service.yml
dashboardhub_app_main.validator.constraints.theme:
class: DashboardHub\Bundle\AppBundle\Validator\Constraints\ThemeValidator
arguments: ["%dashboard_hub_app%"]
tags:
- { name: validator.constraint_validator, alias: theme.validator }
Edit
parameters:
dashboard_hub_app:
themes:
Github: DashboardHubAppBundle:Template:Github.html.twig
GithubTravis: DashboardHubAppBundle:Template:GithubTravis.html.twig
Edit2
It works find when used in the Form Service
dashboardhub_app_main.form.type.dashboard:
class: DashboardHub\Bundle\AppBundle\Form\DashboardType
arguments: ["%dashboard_hub_app%"]
tags:
- { name: form.type, alias: dashboard }
parameters:
dashboard_hub_app: -- !!!!! IS NULL yes
funny :)
parameters follow one by one, so you need to be careful, paramenters && themes - are different.
to inject an array you need provide a value for this paramenter, but i guess you need to inject this one
themes:
Github: DashboardHubAppBundle:Template:Github.html.twig
GithubTravis: DashboardHubAppBundle:Template:GithubTravis.html.twig
arguments: ["%themes%"]
and result will be an array inside your Validator class
array (size=2)
'Github' => string 'DashboardHubAppBundle:Template:Github.html.twig' (length=47)
'GithubTravis' => string 'DashboardHubAppBundle:Template:GithubTravis.html.twig' (length=53)
I need to get doctrine working inside my helper, im trying to use like i normaly do in a controller:
$giftRepository = $this->getDoctrine( )->getRepository( 'DonePunctisBundle:Gift' );
But this gave me:
FATAL ERROR: CALL TO UNDEFINED METHOD
DONE\PUNCTISBUNDLE\HELPER\UTILITYHELPER::GETDOCTRINE() IN
/VAR/WWW/VHOSTS/PUNCTIS.COM/HTTPDOCS/SRC/DONE/PUNCTISBUNDLE/HELPER/UTILITYHELPER.PH
What Im missing here?
EDIT:
services file
services:
templating.helper.utility:
class: Done\PunctisBundle\Helper\UtilityHelper
arguments: [#service_container]
tags:
- { name: templating.helper, alias: utility }
Firts lines of helper file
<?php
namespace Done\PunctisBundle\Helper;
use Symfony\Component\Templating\Helper\Helper;
use Symfony\Component\Templating\EngineInterface;
class UtilityHelper extends Helper {
/*
* Dependency injection
*/
private $container;
public function __construct( $container )
{
$this->container = $container;
}
The problem here is that your Helper class is not container-aware; that is, it has no idea about all the services Symfony has loaded (monolog, twig, ...and doctrine).
You fix this by passing "doctrine" to it. This is called Dependency Injection, and is one of the core things that makes Symfony awesome. Here's how it works:
First, give your Helper class a place for the Doctrine service to live, and require it in the Helper's constructor:
class UtilityHelper
{
private $doctrine;
public function __construct($doctrine)
{
$this->doctrine = $doctrine;
}
public function doSomething()
{
// Do something here
}
}
Then, you use services.yml to define how Symfony should construct that instance of Helper:
services:
helper:
class: Done\PunctisBundle\Helper\UtilityHelper
arguments: [#doctrine]
In this case, #doctrine is a placeholder that means "insert the Doctrine service here".
So now, in your Controller, or in anything else that is container-aware, you can get access to Doctrine through the Helper class like this:
class SomeController()
{
public function someAction()
{
$this->get("helper")->doctrine->getRepository(...);
}
}
EDIT
After looking at your edit, it appears that you're injecting the entire service container into the Helper class. That's not a best practice -- you should only inject what you need. However, you can still do it:
services.yml
services:
helper:
class: Done\PunctisBundle\Helper\UtilityHelper
arguments: [#service_container]
UtilityHelper.php
class UtilityHelper
{
private $container;
public function __construct($container)
{
$this->container = $container;
}
public function doSomething()
{
// This won't work, because UtilityHelper doesn't have a getDoctrine() method:
// $this->getDoctrine()->getRepository(...)
// Instead, think about what you have access to...
$container = $this->container;
// Now, you need to get Doctrine
// This won't work... getDoctrine() is a shortcut method, available only in a Controller
// $container->getDoctrine()->getRepository(...)
$container->get("doctrine")->getRepository(...)
}
}
I've included a few comments there that highlight some common pitfalls. Hope this helps.
In Helper, Services etc you cannot use it like in actions.
You need to pass it like argument to youre Helper via service description in conf file(services.yml or *.xml).
Example:
services:
%service_name%:
class: %path_to_youre_helper_class%
arguments: [#doctrine.orm.entity_manager]
tags:
- { name: %name% }
And dont forget catch it in __construct of youre Helper.
Example:
use Doctrine\ORM\EntityManager;
....
private $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
You can use it like:
public function myMethod()
{
$repo = $this->em->getRepository('DonePunctisBundle:Gift');
}
My question is pretty simple: How can I write a function once and make it available globally across every Twig template I have in a bundle?
Try to reproduce more or less the following class in Bundle\Twig\Extensions
class LabelsExtension extends \Twig_Extension
{
function getName()
{
return 'labels';
}
function getFunctions()
{
return array(
'perso_label' => new \Twig_Function_Method($this, 'persoLabel')
);
}
function persoLabel($value)
{
if ($value == 1) return 'HI';
}
}
Then in your config.yml or services.yml, you need to have something like this:
services:
twig.extension.mynamespace.labels:
class: Namespace\Bundle\Twig\Extension\LabelsExtension
tags:
- { name: 'twig.extension' }
So now you can call it in any template with {{ perso_label(1) }} or whatever.