symfony2: how to access service from template
You can set the service a twig global variable in config.yml
, e.g
#app/config/config.yml
twig:
globals:
your_service: "@your_service"
And in your template.html.twig
file you can invoke your service this way:
{{ your_service.someMethod(twig_variable) }}
See here.
Accessing Method Through Service --- Symfony2
When you call $this->get("your.service")
you are asking the dependency injection container to load that service. You are requesting that it loads one of your controllers which extends Symfony's controller class which extends ContainerAware. The error you are getting is because the loaded controller is likely trying to access a service like "request" using $this->container->get("request")
but $this->container
is not set.
ContainerAware has a method setContainer
which you can actually run when your service is setup by using the calls:
argument in services.yml:
services:
cj.businessbundle.purchase:
class: CJ\BusinessBundle\Controller\PurchaseController
calls:
- [setContainer, [@service_container]]
Symfony2 does this for the loaded controller (PurchaseOrderController) but not if you just load a controller class yourself.
It would be much better practice to extract the newAction (or the required logic) from PurchaseController as a service itself rather than setting the whole controller as a service. This way both Purchase and PurchaseOrder controllers can call the service to create a new purchase (or whatever newAction does) and you are not loading a whole controller everytime. Check out the FOS user bundle user manager for a good example of a service or http://symfony.com/doc/2.1/book/service_container.html#what-is-a-service
Access Service from Controller and/or Twig template
You should not call your services from the twig file, but from the controller.
The role of the controller is to :
- validate your forms if there were a form posted
- call your services to get some stuffs to display in a view
- initialize forms if there is a form to display
- return a Response that typically contains a rendered twig view
Do not call your services using something like $client = new ClientLocation();
, but call it using the service container. This will allow you to take the whole power of the dependancy injection offered by Symfony2.
Your controller will look like :
<?php
namespace MyApp\Bundle\ServiceABCBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class DefaultController extends Controller
{
public function indexAction()
{
$locationService = $this->container->get('location_manager');
$someStuffs = $locationService->someMethod();
$response = $this->render(
'ServiceABCBundle:Default:index.html.twig', array('stuffs' => $someStuffs)
);
return $response;
}
}
From your twig file, you'll be able to use the stuffs
variable :
{{ stuffs }}
if your variable is a terminal ( a string, a number... ){{ stuffs.attribute }}
if your variable is an object or an array
About your services file, I am a bit confused, because your architecture does not look to be the standard Symfony2's one :
# ~/MyApp/Bundle/ServiceABCBundle/Resources/config/services.yml
Why your services.yml
file isn't in the src/MyApp/SomethingBundle/Resources/config/
directory?
If you didn't already read it, I suggest you to have a look to the Symfony2 : The Big Picture documentation, which is the best way to start with Symfony2.
Call a service from twig template in symfony 4
You can still define twig global variables - they would just go in with the rest of the Twig configuration in config/packages/twig.yaml
.
An alternative, and maybe better place to put that could be a Twig function. The service that defines the function (or filters) are as much a service as the controllers, and so you would type-hint your NavigationGenerator
and anything else you needed, in the constructor, for use in the function that is being called from Twig.
How to call a service in my twig template to create a form with Symfony 2
You should start by making sure that you really have to use a form to do the manipulations that you are trying to do. Maybe using a link to a page with the form would suffice.
But this doesn't not answer your question so here goes:
Since the form will be used on every page it should be placed in your main template, in this case the base.html.twig
. In fact, the content in the <main>
and <header>
tags should be moved to your base
template. Then, you should add an action in your controller which handles the form or just rename the indexAction
giving it a name more related to what you are trying to accomplish. After, you will move the code from the form in another template without any of you block tags.
menu.html.twig
{{ form_start(formulaire) }}
{{ form_widget(formulaire.Ajouter) }}
{{ form_widget(formulaire.projet) }}
{{ form_row(formulaire.modifier) }}
{{ form_row(formulaire.supprimer) }}
{{ form_end(formulaire) }}
controller
use Symfony\Component\HttpFoundation\Request;
class AdminController extends Controller
...
public function menuAction() {
$request = Request::createFromGlobals();
// code that was in the indexAction
return $this->render('AdminBundle::menu.html.twig', array(
'formulaire'=>$formulaire->createView()
));
}
}
In your base you will render the action.
base.html.twig
{{ render(controller('AdminBundle:Admin:menu')) }}
You can also find more documentation on this page:
http://symfony.com/doc/current/book/templating.html
Symfony2 - How to implement this search function as a service?
If you are trying to inject the request service, you would be better to inject the request_stack
service instead and access the current Request by calling the getCurrentRequest()
class Search
{
protected $request;
public function __construct(RequestStack $requestStack)
{
$this->request = $requestStack->getCurrentRequest();
//Do any kinds of initializing you need
}
public function mySearch()
{
$results = null;
$query = $this->request->query->get('q');
//Do your search base on $query
//I suggest to send the container instead of RequestStack because you want to do search by using EntityManger, too
//Return the results
}
}
and change your service.yml as below and set the scope to "request"
services:
search:
class: Acme\ProjectBundle\Services\Search
arguments: ["@request_stack"]
scope: "request"
You also have another option to send the container as a parameter to your service and in your service use container->getRequset()
Symfony - Service in Twig template
You can access the logged in user data directly in the twig template without requesting anything in the controller. The user is accessible like this : app.user
.
I would add a method hasGroup
to your User
object then you can call that method in your twig template to test if a user belongs to a group.
If you did this then you can just do this:
{% if app.user.hasGroup('groupName') %}
//do something
{% endif %}
Symfony2.8 how to build a search form that will be viewable from all templates
This could be achieved injecting a service into all templates as global variable:
First, define your service with its dependencies:
services:
app.fulltextsearch:
class: MyBundle\Services\FulltextSearch
arguments: ['@form.factory']
Second, to define this service as a global Twig variable:
# app/config/config.yml
twig:
# ...
globals:
fulltextSearch: '@app.fulltextsearch'
That's it!
Whenever the global variable is accessed in the template, the service will be requested from the service container and you get access to that object.
On the other hand, I suggest you create the whole form within FulltextSearch::mySearch
method for major reusability:
class FulltextSearch
{
private $router;
//...
public function mySearch() {
$form = $this->formFactory->createBuilder()
->setAction($this->router->generate('my_search'))
->add('search', FulltextSearch::class)
->getForm();
return $form->createView();
}
}
Note: Make sure to inject the @router
service in app.fulltextsearch
definition as well as '@form.factory'
.
Next, you base search template looks like this, (no needed <form>
tag, action
and method
attributes, this last by default is POST
):
{{ form(fulltextSearch.mySearch) }}
Related Topics
PHP Remove Elements from Associative Array
Using Ajax in a Wordpress Plugin
PHP Call Class Function by String Name
Error_Reporting(E_All) Does Not Produce an Error
How to Take an Array, Divide It by Two and Create Two Lists
Make Text Wrap in a Cell with Fpdf
Send Checkbox Value in PHP Form
How to Avoid Resending Data on Refresh in PHP
Php: Date Larger Than Current Date
Send Emails with International Accent and Special Characters
Php: Catch Exception and Continue Execution, Is It Possible
How to Convert All Characters to Their HTML Entity Equivalent Using PHP
PHP Date Time Current Time Add Minutes
Href="" Automatically Adds to Current Page Url (In PHP). Can't Figure It Out