I created a controller called NumbersController. Right now I want it to dispaly something that I put on url. The controller looks like this:
class NumbersController extends Controller {
/**
* #Route("/", name="_numbers")
* #Template()
*/
public function indexAction($number)
{
return array('number' => $number);
} }
I created a folder in view called Numbers and a file index.html.twig that contain just {{ number }}.
Somehow here is a problem with the routes and when I goto http://127.0.0.1/SERVER/symfony/web/app_dev.php/numbers/2 for example I get No route found for "GET /numbers.
I'm pretty sure that I understood how routes works from the default examples from symfony2 but I just can't figure out why don't work with a new controller.
_numbers:
resource: "#AcmeDemoBundle/Controller/NumbersController.php"
type: annotation
prefix: /numbers
So you have prefix. In that case your route should be #Route("/{number}")
http://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/routing.html#route-prefix
Related
Route("/) does not work.
I already tried to reinstall annotations and Symfony with Composer.
My routes.yaml :
index:
path: /
controller: App\Controller\ArticleController::homepage
My ArticleController.php :
namespace App\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class ArticleController
{
/**
* #Route("/")
*/
public function homepage()
{
return new Response("TEST");
}
/**
* #Route("/news/test-test")
*/
public function show()
{
return new Response("FUTURE");
}
}
The page always shows the public/index.php, but it should show "FUTURE" ;)
in your config folder you should find a folder called routes inside it should be a file called annotations.yaml which contains the following :
controllers:
resource: ../../src/Controller/
type: annotation
if you have this you should get "TEST" when you go to ("/")
and you get "FUTURE" when you go to (/news/test-test)
and make sure to clear the cache if it did not
and you have to comment every thing inside routes.yml
Like Ali Mhanna said, check first annotations.yaml.
Then, according to Symfony documentation (read it, it can help ;), run php bin/console debug:router
If you see your route, your route is working.
Ok so i have a controller with an action and 2 routes associated with it:
/**
* #Route("/index/preview/", name="mybundle.preview_index")
* #Route("/", name="mybundle.index")
* #Template
*/
public function indexAction(Request $request)
{
$preview = ($request->get('_route') === 'mybundle.preview_index');
$host = $request->getHttpHost(); //domain.com
if(!$preivew){
$host = 'domain2.com';
}
return array(
'preivew' => $preview,
'host' => $host,
'basePath' => $preview?'mybundle.preview_':'mybundle.',
);
}
Then I want to generate a route inside the twig template depending on the host:
{{ path(basePath~'index') }}
//Then somehow pass the host to this so that i get the intended domain
If I was accessing this route using the preview route then i would get:
domain.com/index/preview/
But if i wasnt it would give me:
domain2.com/
What I Have Tried
Setting the router context from within the controller, but that doesnt change routes generated in twig
I figured it out. Instead of using path() i have to use url() and set the host in the context of the router:
if(!$preview){
$context = $this->get('router')->getContext();
$context->setHost($host);
}
Then twig:
{{ url(basePath~'index') }}
In my Symfony2 app, I want to globally fetch a value from my database on each template and don't want to call on each Controller. I know I could define that as a service and inject that service into my twig templates (by defining it as a twig global).
Is that the common and recommended way? Or should I rather create an abstract Controller class where I fetch that value in my constructor and then inherit from all my other Controllers?
Note: It is actually not a static value that is the same for all users, but it is a user specific value which is different for each user.
If this variables are used to render the same spot on your page you can render an embedded controller. Like this:
<div id="sidebar">
{{ render(controller('YourBundle:User:stats')) }}
</div>
This will inject whole output of YourBundle/UserController/statsAction to the #sidebar div. Inside this action you can extract all inforamtion that you need.
If you need to use this variables in other way maybe you should look at response event.
Are you familiar with event listeners? http://symfony.com/doc/current/cookbook/service_container/event_listener.html
An event listener can be used to inject twig globals.
class ModelEventListener extends ContainerAware implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return array(
KernelEvents::CONTROLLER => array(
array('doProject', -1300),
),
KernelEvents::VIEW => array(
array('doView', -2100),
),
);
}
public function doProject(FilterControllerEvent $event)
{
$project = $whatever_is_needed_to_find_the_project();
if (!$project) throw new NotFoundHttpException('Project not found ' . $projectSearch);
// Add to request
$event->getRequest()->attributes->set('project',$project);
// Give all twig templates access to project
$twig = $this->container->get('twig');
$twig->addGlobal('project',$project);
}
# services.yml
cerad_core__model__event_listener:
class: '%cerad_core__model__event_listener__class%'
calls:
- [setContainer, ['#service_container']]
tags:
- { name: kernel.event_subscriber }
If it's a user value like you said you can get app.user.XXX on every twig template you need without processing nothing ;)
I've generated a bundle (#ShopfishApiBundle) using generate:bundle like I have many times. It has automatically registered the bundle in theAppKernel and it added the loading of the bundle's routing.yml to the app/Resource/config/routing.yml as well. This is within a Sylius installation running Symfony 2.3
The #ShopfishApiBundle/Resource/config/routing.yml looks like this:
shopfish_api:
resource: "#ShopfishApiBundle/Controller/ProductController.php"
type: annotation
The product controller looks like this:
namespace Shopfish\Bundle\ApiBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
/**
* #Route("/api")
*/
class ProductController extends Controller
{
/**
* #Route("/products")
* #Method({"GET"})
*
* #Rest\View
*/
public function allAction()
{
$products = array();
return array('products' => $products);
}
}
Loading any page instantly yields the below exception:
FileLoaderLoadException: Cannot load resource "#ShopfishApiBundle/Controller/". Make sure the "ShopfishApiBundle" bundle is correctly registered and loaded in the application kernel class.
In another Symfony2 (version 2.4) application I've made a similar bundle and this worked without error, I'm thinking something in Sylius messes this up. Do you know where I might solve this issue?
NOTE: I did a little test to see if a direct-no-annotations code snippet worked, and that seems to work. Though I want to use the FOS Rest bundle, using Annotations for Routing.
sf_api_controller:
pattern: /no-annotation-test
defaults:
_controller: ShopfishApiBundle:Product:all
I hadn't registered the essential SensionFrameworkExtraBundle in my AppKernel.php:
new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle()
Thanks, #pazi!
I've made it simpler (apologies for the complicated question which I've left at the bottom).
I want to have a twig template render another controller as a sub-part.
Here's the parent twig (Resources/views/Default/testRenderParent.html.twig):
<p>Look! I am your father!</p>
<p>But look, I am not your
{{ render(controller("SarelTestBundle:Default:testRenderChild")) }}</p>
Here's the child twig (Resources/views/Default/testRenderChild.html.twig):
KID
The controller (Controller/DefaultController.php):
<?php
namespace Sarel\Test\TestBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
/**
* #Template()
**/
class DefaultController extends Controller
{
/**
* #Route("/testRenderParent")
*/
public function testRenderParentAction()
{
return array();
}
/**
* #Route("/testRenderChild")
*/
public function testRenderChildAction() {
return array();
}
}
When you run this, with the following URL /testRenderChild you should get "KID" echoed.
When you run this, with the URL /testRenderParent (notice the "Parent" part), you should get echoed:
Look! I am your father!
But look, I am your KID
However, instead you get this echoed, and the error below it:
Look! I am your father!
But look, I am not your
Look! I am your father!
But look, I am not your
Look! I am your father!
But look, I am not your
Look! I am your father!
But look, I am not your
Look! I am your father!
But look, I am not your
Look! I am your father!
But look, I am not your
Look! I am your father!
But look, I am not your
Look! I am your father!
But look, I am not your
FatalErrorException: Error: Maximum function nesting level of '250' reached, aborting! in /Users/sarel/www/playpen/app/cache/dev/classes.php line 6134
Thus you can see, it's rendering "Look! I am your father! But look, I am your "... and then instead of rendering the child controller with it's twig template, it re-renders the parent, ending in an endless loop, which is arrested by the exception.
--- copy before I changed it ---
--- copy before I changed it ---
--- copy before I changed it ---
So I'm trying to embed a controller (and ultimately the template that the action renders) in my symfony2 project using the guidelines in enter link description here.
My Controller is defined below:
<?php
namespace OTS\CoreBundle\Controller;
/**
* #Template()
*/
class EmergencyContactsController extends Controller
{
public function addEmergencyContactAction(Request $request, $id) {
return array();
}
}
I have a twig template attached to that, which right now just have "hello world" in the form of a twig file called addEmergencyContact.html.twig.
When I go to the URL for this, which is something like localhost/my_route_to_it it works perfectly fine and I see "hello world" on the screen.
Now, according to this I merely have to put the following twig command in:
{{ render(controller('OTSCoreBundle:EmergencyContacts:addEmergencyContact', {'id': 15})) }}
When I do this and I load the holding-route it appears to be trying to load the main route, and then load the main route again inside the spot where I render the child-route. I know this because it's telling me there's variables missing - variables that I'm only using in the main twig file.
Yet, when I:
Don't have the {{ render... }} in there, it works fine - i.e. it's not other code that's giving me the exception of missing variable
Render only the child-route I get a nice "hello world" back - i.e. it's not the child twig or child controller that's buggy
Hmmm. The question is a bit confusing but:
A. Like all controller actions, your addEmergencyContact needs to return a response, not an array. So:
class EmergencyContactsController extends Controller
{
public function addEmergencyContactAction(Request $request, $id)
{
$tplData = array();
$tplData['id'] = $id;
return $this->render('CoreBundle::emergency_contact.html.twig', $tplData);
}
}
B. You need two template files. Something like:
class HelloWorldController extends Controller
{
public function helloWorldAction(Request $request, $id)
{
$tplData = array();
$tplData['id'] = $id;
return $this->render('CoreBundle::hello_world.html.twig', $tplData);
}
}
C. The render line then goes in the hello_world.html.twig file.
{{ render(controller('OTSCoreBundle:EmergencyContacts:addEmergencyContact', {'id': 15})) }}
D. Note that your emergency_contact template will only have access to values passed into it by the emergency contact action. It will not "inherit" the values that hello_world has.
So why is my code formatting messed up? Did not like numbered lists.
This turns out to be a bug in the way annotations work. When I change the controller from being globally #Template() enabled to moving that old-school back to each action individually, it works. Here's the updated controller, look at where the #Template() now sits:
<?php
namespace Sarel\Test\TestBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
class DefaultController extends Controller
{
/**
* #Route("/testRenderParent")
* #Template()
*/
public function testRenderParentAction()
{
return array();
}
/**
* #Route("/testRenderChild")
* #Template()
*/
public function testRenderChildAction() {
return array();
}
}