Host matching in Symfony3 routes - symfony

I have a website (example.com) which has a subdomain for the customer area like customer.example.com. Now I want to add a different subdomain which is exactly the same as that website but only has a different images.
This should result in example.com equals demo.example.com and customer.exmaple.com equals customer.demo.example.com.
At the moment I have the current route annotation bind to the class for the customer side:
/**
* Customer links
* #Route(host="customer.%domain%")
*/
class CustomerController extends Controller
{
(domain is defined in config.yml)
I tried changing that to match hosts like so:
/**
* Customer links
* #Route(
* host="customer.{domain}",
* defaults={"domain"="%domain%"},
* requirements={"domain"="%domain%|demo.%domain%"}
* )
*/
But this won't work since you need to provide a default parameter for domain, and this will always be the value in this case. So the URL works, but every other link will redirect you back to customer.domain.com
I tried the same thing in routing.yml which had the same results.
Is it possible to have a dynamic domain/subdomain, and if so, how could I do it?

Related

defines manually routes using Symfony2

I've set up my entities, now I want to
use the doctrine:generate:crud, during this command it asks what route
prefix I would like. I would expect that this means that the routes
would automatically be generate, this is not happening. So I need to
know if it is supposed to generate the routes, or if I'm supposed to
create them all manually? If it is the case that I need to generate
them manually is there a route class, to define all the routes for the
CRUD operations?
When you generate a CRUD with Symfony, it will ask you to choose a configuration format.
By default, it's annotation. If you haven't changed it, then your routes are in the entity controller, as annotation.
In the example below, you can see the #Route anotation, which is how to define the URL in anotation.
/**
* Finds and displays a user entity.
*
* #Route("/user/{id}", name="user_show")
* #Method("GET")
*
* #param User $user
* #return \Symfony\Component\HttpFoundation\Response
*/
public function showAction(User $user) {
$deleteForm=$this->createDeleteForm($user);
return $this->render('security/show.html.twig', array(
'security'=>$user,
'delete_form'=>$deleteForm->createView(),
));
}
In the end, it's not that "It didn't happen", it's simply and most likely that you haven't read some doc, and didn't knew about it... ;)
Symfony doc: Routing

Consistency in arg routes in symfony2

I'm a beginner in Symfony2 and I'm just wondering if the consistency of args has to be done myself in the controller or if there is a mechanism i don't know of
let's take a example:
i have a route like /company/id/user/id to display some information for the user
i have tried manually to change id for either company or user and there is no error if the user is not from the company ?!
Do i have to check in the controller displayUserAction if user and company are bound ?
/**
* #Route("/company/{company_id}/user/{site_id}")
* #ParamConverter("company", class="MyModel\Company", options={"mapping": {"company_id": "id"}})
* #ParamConverter("site", class="MyModel\User", options={"mapping": {"site_id": "id"}})
*/
public function displayUserAction(Company $company, User $user)
{
..
}
routing.yml
user_info:
path: /company/{company_id}/user/{site_id}
defaults: { _controller: UserBundle:Default:displayUser }
Edit:
I've found another way : map using several criteria
/**
* #Route("/company/{company_id}/user/{site_id}")
* #ParamConverter("company", class="MyModel\Company", options={"mapping": {"company_id": "id"}})
* #ParamConverter("site", class="MyModel\User", options={"mapping": {"site_id": "id", "company_id":"company"}})
*/
public function displayUserAction(Company $company, User $user)
{
..
}
You can re-order the arguments in the Action all you like. Symfony is smart enough to match the arguments - but you should keep the naming somewhat consistent - which you have done anyway. Symfony will match {company_id} in your route to $company in your Action for example no matter the order you place them in.
In your route, both arguments are required for the route to match. So the route will only match work if both arguments are bound.
In your Action, you would need to check the User belongs to the Company. The architecture of the Route and the Action don't care if the 2 entities are related, they only care that a value has been supplied.

Can I implement my own Symfony2 annotations easily?

Is there anything in the Symfony annotations modules that allow me to use them for other uses?
I know for #Route and #Method you need to extend existing libraries, so its just not that easy i'm guessing.
Currently, i'm working with the JS History API, and would LOVE to put the popState data for my JS files in the annotations. So they are already available when the routing generates the URL.
Q Doesn't this makes sense to have a, HTML5 annotated title, or some attribute here? It would be great to have the ability to define this data, as annotated, right next to the already existing route name and stuff.
Q Is there anybody that has tweaked with the annotations before?
I wanted to clarify my intentions here as I think I left out some crucial details (the mention of History API) for understanding my use case.
There is a few SPA front ends that have been integrated through a front-end bundle, and this connected via AJAX calls to a backend bundle which was a straight RESTful API, with the addition of a very fun-to-develop PHP API class I made that intereprets and processes (routes) the AJAX in a fashion that directly executes other PHP class controller `methods.
I use a lot of ajax for this Symfony 2 app (fosjsrouter) to handle routing. So instead of URLs triggering the routes and actions, the SPA click event fires off AJAX to the back end router, with a large JSON payload, not limited to PHP control parameter's (class/method/var names), and data sets.
OK, so getting back on track; Given the above scenario; In the JS class object end of the router, inside this I thought it was the best place to add some JS History API functionality to it, (state, back button, etc.)
The above class can be called if a history flag was called, which could become responsible for assigning initial state data. Primarily, this is because the JSON data object that's being around in this JS method contains already a lot of the crucial route data, and param information for that route needed in the backend PHP, which comes from the annotations.
So the idea is if I add accessibility for a history state title and URL to the annotations, then I will have access to that information right there available to define the initial state, if flagged, right inside the an ajax.done(), inside this main JS routing method.
Now we can pass state back and forth two ways between the db and realtime client-side async. You can use an observer, or anything, from there front-end, and jobs/queues on the backend to keep it fully reactive. (use React too :-))
EDIT I'm not so sure that's what I was thinking, it looks like its making me set the values of the title and url for this inside the return statement of the PHP function, where I want it set in the annotation (see return 'Matthias Noback';)
So I'm trying this, but where do I set these titles at?
<?php
namespace Blah\CoreBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
/**
* #Annotation
*/
class HistoryAnnotationController
{
//history state params are out properties here..
/**
* #var
*/
private $url;
/**
* #var
*/
private $title;
/**
*
*/
public function __construct()
{
}
/**
* #return mixed
*/
public function getTitle()
{
return $this->title;
}
/**
* #return mixed
*/
public function getUrl()
{
return $this->url;
}
}
I want to set it WAY back here, so the ajax that calls this route has access to it.. (look for #historyApiTitle in this code, etc..)
<?php
namespace Blah\Bundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller,
Symfony\Component\HttpFoundation\JsonResponse,
Sensio\Bundle\FrameworkExtraBundle\Configuration\Method,
Sensio\Bundle\FrameworkExtraBundle\Configuration\Route,
Sensio\Bundle\FrameworkExtraBundle\Configuration\Template,
Blah\Bundle\Entity\Test,
Doctrine\ORM\Query; //for hydration
class StuffController
{
/**
* #Route("/some/route/name/{test}", name="some_route_name", options={"expose"=true})
* #param $test
* #return mixed
* #historyApiTitle('This is the get something page')
* #historyApiUrl('/get_something')
*/
public function getSomethingAction($test)
{
$em = $this->getDoctrine()->getManager();
$dql = "
SELECT s
FROM BlahBundle:Stuff s
WHERE s.test = :test";
$query = $em->createQuery($dql);
$query->setParameter('test', $test);
$paginator = $this->get('knp_paginator');
$pagination = $paginator->paginate($query,
$this->get('request')->query->get('page', 1), 1000);
return $this->render('BlahBundle:Stuff:get_something.html.twig', array('pagination' => $pagination));
}
}
Q So looking at these TWO code examples, how do I connect the dots between the two to get this to work?
Yes you can annotations classes you can follow the following tutorial Creating Custom annotations Classes
Basic rules are the follows:
Your class should have the #Annotation -phpdoc comment
/**
* #Annotation
*/
class CustomAnnotation
{
public function __construct($options) {}
}
In Your Needed class just use it in standard way;
class Person
{
/**
* #CustomAnnotation("option")
*/
public function getName()
{
return 'some stuff';
}
}
You should looks at the AOPBundle, it allows you to do treatement from your personnals annotations. But I don't thinks trying to do annotations in the view is a good idea. You need to parse the javascript with php, and it sounds bad.

Symfony Newb Routing Issue

I have just started using Symfony and I am having a routing problem. Here is the routing fromt the controller:
/**
* #Route("/social/{name}/", name="_speed1")
* #Route("/social/drivers/")
* #Route("/social/drivers/{name}/", name="_driver")
* #Route("/social/", name="_speed")
* #Template()
*/
public function unlimitedAction()
{
If I go to speed/social/ or speed/social/bob or speed/social/drivers/ or speed/social/drivers/bob all of those pages render with no problem. However I need the name being passed in so I changed
public function unlimitedAction()
{
to
public function unlimitedAction($name)
{
If I go to speed/social/drivers/ or speed/social/drivers/bob it returns fine. However, if I go to speed/social/ then I get the following error:
Controller "MyBundle\Controller\DefaultController::unlimitedAction()"
requires that you provide a value for the "$name" argument (because there is
no default value or because there is a non optional argument after this one).
I can't understand why it works for one route but not the other.
So my question is, how can I acheive my routing so that I can go to:
speed/social/
speed/social/drivers/
speed/social/drivers/bob
And be able to pass the variable to the action without error.
Thanks!
To answer your question: you have to provide a default value for name parameter, for each route without the {name} parameter in the url. I can't test it right now and I can't remember the syntax when using annotations, but should be something like this:
/**
* #Route("/social/{name}/", name="_speed1", defaults={"name"=null})
* #Route("/social/drivers/{name}/", name="_driver", defaults={"name"=null})
* #Template()
*/
public function unlimitedAction($name)
{
}
This way you should be able to call /social/ and /social/foo as well as /social/drivers/ and /social/drivers/foo.
But, really, this is not the right way to go. Just define more actions, each binded to a single route:
/**
* #Route("/social", name="social_index")
* #Template()
*/
public function socialIndexAction() { } // /social
/**
* #Route("/social/{name}", name="social_show")
* #Template()
*/
public function socialShowAction($name) { } // /social/foo
As a general rule, each method (each action) should be focused to do just one thing and should be as short as possible. Use services and make your controllers do what they are supposed to do: understand user input, call services and show views.

Symfony2, Is it possible to have two route for one action in a controller?

I have an action inside my controller class and I want two different routes like below:
/**
* Displays a form to create a new entity.
*
* #Route("/edit/choose/date", name="user_choose_date")
* #Route("/supervisory/choose/date", name="sup_choose_date")
* #Template()
*/
public function chooseDateAction()
{
return array( );
}
The reason for that I would like to give the route access to some users but the user role are different.
Let's say:
User with supervisor role can access sup_choose_date
User with user role can access user_choose_date
The question is if it is possible to have two different routes for one action? or I have duplicate the code for different routes ?
Yes, it is possible when using YAML (or XML) routing.
Example:
sup_choose_date:
pattern: /supervisory/choose/date
defaults: { _controller: MyBundle:Default:chooseDate }
user_choose_date:
pattern: /edit/choose/date
defaults: { _controller: MyBundle:Default:chooseDate }
Worked for me!
You must set different names; if not, specify explicitly
I is possible on every kind of format including annotation. It should work as long as you have different name for every route.

Resources