I want to retrieve Cities names from a table in the database and put them as options in a select input (combobox) which is defined in 'layout.html.twig' . All my views extends 'layout.html.twig', so how can I access to cities names in every page?
[Solution]
I'm not able to respond to my topic ,I didn't have much reputation so I edit my topic
I have found the solution, using "embedding controllers"
first I've created an action to retreive all cities names:
public function listCitiesAction(){
// retreiving cities
$entities = $this->getDoctrine()->getRepository("MedAdBundle:City")->findAll();
return $this->render('MedAdBundle:Ville:list_cities.html.twig',
array('entities' => $entities));
}
this action render list_cities.html.twig defined as :
<select class="form-control">
{% for entity in entities %}
<option>{{ entity.name}}</option>
{% endfor %}
</select>
finnaly I edit my layout.html.twig
<div>
{{ render(controller('MedAdBundle:City:listCities'))}}
</div>
In this way I can access to cities combobox in every page in my app ;)
Another nice way would be use render.
This allows you to call a controller out of your layout.html.twig
{{ render(controller("AcmeDemoBundle:Helper:citySelector")) }}
you also can cache the output with ESI.
It's well explained in the cookbook.
http://symfony.com/doc/current/cookbook/templating/global_variables.html
I would go with these steps:
Write a form hosting a symfony entity field configured to work with the Cities table
Define this form as a service in the DIC
Define a twig extension that exposes a function to output the form HTML
Use the twig function in the layout.html.twig that is extended by all the other templates
As an optimization I would look how I could wire Doctrine with some caching system (e.g. memcached) to avoid hitting the database on each page load.
This is where you can find documentation about the entity field: http://symfony.com/doc/current/reference/forms/types/entity.html
Use the Symfony documentation to find how to define a form as a service and how to write your own twig extension.
Related
Here is the use case:
I have a simple navbar with a simple dropdown menu.
I have a list of cities in the Database with the name of the cities. I want to get all the cities and add them to the dropdown menu.
Simple way is to send additional data, like array of cities to twig. But i have a lot of routes and i don't think that this is good to repeat fetching every time. This is not good, right?
public function testpageAction(){
$em = $this->getDoctrine()->getEntityManager();
$cities = $em->getRepository('AppBundle:City')->findAll();
return $this->render('appviews/testpage.html.twig',array('cities'=>$cities));
}
There is a method to inject variable into all templates, but this is static data, so it is not the solution.
There is a plan in my head to make a method that will be run before controller methods and it will send the data to those methods. But it does not seem good and I believe there is a better way to solve it.
You can have a CityController or a BaseController with method getAllCities, and embed this controller in your base template.
From Symfony docs :
In some cases, you need to do more than include a simple template. Suppose you have a sidebar in your layout that contains the three most recent articles. Retrieving the three articles may include querying the database or performing other heavy logic that can't be done from within a template.
The solution is to simply embed the result of an entire controller from your template.
Something like this:
class BaseController extends Controller
{
public function getAllCities()
{
// make a database call or other logic
// to get all cities
$cities = ...;
return $this->render(
'cities.html.twig',
array('cities' => $cities)
);
}
}
Your cities template:
{# app/Resources/views/cities.html.twig #}
{% for city in cities %}
{{ city}}
{% endfor %}
And in your base template:
{# app/Resources/views/base.html.twig #}
<div id="sidebar">
{{ render(controller(
'AppBundle:Base:getAllCities'
)) }}
</div>
I am using laravel 5 for my project. I have a view file layouts/app.blade.php which is extended by all the views. I have stored the application name , email in the database .... Now I need to show those data in my app.blade.php..
How do I do it?
Well as #DutGriff said, it seems to be that you are too new to laravel framework. Just dig in a bit and you get something called Service Injection in blade. Now, answer to your question:
Open you app.blade.php
Go ahead and type the following at very start of app.blade.php
#inject('model_name', 'App\ModelName')
{{{ $model_name = $model_name->where('app_name', 'app')->get() }}}
And then, just access it anywhere like:
{{ $model_name->name }}
I'm new to Symfony2 and after several tutorials decided to migrate on of my projects to this framework.
In my project I've got few modules that got different templates but share the same data. For example, menu: menu items are lifted from database and used by standart website menu and also by footer menu. I've read that the best practice is to create controller for such task, and embed it straight into main layout, like this:
//Controller
class PageComponentController extends Controller
{
public function menuAction()
{
//get menu items from database...
$menu_items = ...
return $this->render('MyProjectBundle:PageComponent:menu.html.twig', [
'menu_items' => $menu_items
]);
}
}
//Template
{% block body %}
{% render controller('MyProjectBundle:PageComponent:menu', { 'current_page': current_page }) %}
{% endblock %}
But then I need to pass those $menu_items in footer as well, and render footer from the footerAction() in PageComponentController.
I know that there are ways to do it, but what is the best way to share such mutual data between different embedded controllers in Symfony2?
UPDATE (solution based on oligan's answer):
Service container scope is both accessible from main controller (responsible for page rendering) and from embedded controllers. So it would be pretty clean and dry to write service class with getMenu() method that fetches data from DB, and outputMenu() method that returns existing data. Then, service data is set from main controller and could be retrieved from service container in embedded controllers.
I think the wisest is to use a service which would retrieve all the data you want http://symfony.com/doc/current/book/service_container.html (it's more or less like a controller but accessible everywhere )
To give you an idea what it is
class MenuService
{
public function getMyMenu()
{
... your code to get the menu
}
}
Then declare it in services.yml in your bundle
services:
getMenuService:
class: ..\...\...\MenuService
And then just use it in any controller by doing so
$menu = $this->container->get('getMenuService');
if you have to use template heritage then you can still access to an object in the parent template by doing
{% extends "...Bundle..:myMenu.html.twig" %}
{% set menu = myMenuTwigvar %}
and then myMenu for example menu.button1
I've just started a new Symfony2 project where I've used the generate:doctrine:crud to quickly scale out a few views, forms, etc.
The generated form code is just:
{{ form(form) }} but includes a generic create or delete button. I was wondering how I could add a class to these generic buttons or modify them in any way since it's just encompassed in {{ form(form) }}?
For reference I'm using Twitter Bootstrap to quickly apply some styles so I don't want to change the css based on the submit button.
Thanks!
You can specify CSS classes in the form builder class to avoid filling your Twig template with html even for rendering the form individually.
When you call {{ form(form) }} you are using a helper to simplify your code so you don't have to call form_widget for each one of your fields, but doing so you can't control the exact display in the template. To do it you have to specify the class that will be applied to the field.
In the WhateverType.php file, inside the Forms folder, you have the form builder. There you should have something like:
$builder
->add('text')
->add('whatever')
There you have to add the classes:
$builder
->add('text', 'attr'=> array('class'=>'btn')
->add('whatever')
Then, when your form is displayed in the template, it will apply the classes that you specified in the builder.
After following dmnptr's answer (breaking form into parts), you can pass an array of arguments to each form / form_row / form_label etc by:
{{ form(form, { 'attr': { 'class': 'your-css-class-1 your-css-class-2' } } ) }}
The attr param sets attributes for the item, so the above would produce:
<form class="your-css-class-1 your-css-class-2" ...
You are going to have to render each filed by hand and add necessary classes to elements in your TWIG. Read on how to do it in the official docs - http://symfony.com/doc/current/book/forms.html#rendering-each-field-by-hand
My site I have some content can be voted (+/-). It is working fine now, when all content has its own voter.
Now I'm looking for a way to create a single voting bundle with a entity(votedModel,votedId, user, vote).
Basically the bundle is ready. My problem is how to use it. I'd like to be able to do something like:
class ... extends Controller {
function showAction(Request $request,$id) {
...
$voter=new Voter('myCOntentType',$id,$userid);
...
return $this->render('...', array('voter'=>$voter->getVoter(),...))
}
}
getVoter() would create the voter view.
but I'm stacked how exactly start. I tried to call for the other controller in this manner, but can't create the voter form.
It worked with $voter=$this->forward('VoterbundleNewAction', array('id=>$id,'user'=>$user)->getContent();But this wasn't I had in mind.
I think my approach is all wrong and I may need to do this as service. I cant find my way around.
You can use include or render in your twig template to get other templates' output. So you could create a template (say, voter.html.twig) that contains the HTML for your voting system, and in the Twig, in any place where you need a voter, you could use:
{% include "AcmeVoterBundle:Voter:voter.html.twig" %}
or
{% render "AcmeVoterBundle:Voter:voter" with {"item": item} %}
In the first example, you simply include another template (see also: http://symfony.com/doc/current/book/templating.html#including-other-templates), in the latter situation you actually execute another action method of a controller and the output of that is put into your current template (see also: http://symfony.com/doc/current/book/templating.html#embedding-controllers)