Unable to generate URL for named route - php

I'm trying to generate link to URL which contains two parameters (both of those parameters are not really necessary but I do it for practice). I created custom showAction in DiscovererController
/**
* #Route("/rivers/{river_id}/discoverers/{id}", name="discoverer_show")
* #Template
*/
public function showAction($river_id, $id){
$em = $this->getDoctrine()->getEntityManager();
$river = $em->getRepository('MyOwnBundle:River')->find($river_id);
if(!$river){
throw $this->createNotFoundException("no river with provided id");
}
$entity = $river->getDiscoverer();
return array('entity' => $entity);
}
As you can see two parameters are passed, id of the river and id of the discoverer (which is absurd but as I said, practice...).
In show action of a river (/rivers/1) I decided to put following code:
<p>{{entity.discoverer.name}}</p>
Note that 'entity' is a river here, and river has a discoverer. Unfortunatelly, when I try to render this action, I get error which tells me that:
An exception has been thrown during the rendering of a template ("Unable to generate a URL for the named route "discoverer_show" as such route does not exist.") in /path/to/project/src/My/OwnBundle/Resources/views/River/show.html.twig at line 9.
I dont have a clue what is wrong, I provided both necessary parameters and used "discoverer_show" which I defined in my controller. How to correctly render this link?

A piece of advice: do not use tabs in your source code at all! Make your IDE to replace tab character with 4 spaces. This could save you a lot of trouble... Tabs does not behave well in git too.

Ok, by accident i figured it out. Turns out annotations in symfony2 CANNOT begin with tab.
So this thing right here is NOT going to work
/**
* #Route("/people")
*/
But this will work like a charm:
/**
* #Route("/people")
*/

Related

in Laravel route , why using default and why to struct route like this

Route::get('/atomic/{id}',[ApiController::class,'index'])->defaults('task', 'atomic');
why use defaults here and what is a task & atomic, and Api controller does not have an index function. Please explain this route properly.
I am new to laravel I tried to google for a solution but no result
defaults method helps to pass extra params to controller without passing as route params
As a backend engineer you’ll often be asked to produce URL patterns
that just don’t work with the rest of the site without breaking your
current routing structure. Often you’ll create what’s known as a slug
for your content, a simple hyphen separated string which is unique in
the system. A typical slug would be just generated from the title like
“My Simple Article” becomes as a slug my-simple-article. This way
there’s a unique string in the system for each post.
If you’ve already been implementing routes like this in your system
you’ll likely have urls that look like /post/{slug} but you know now
that’s not going to be good enough. Your company’s marketing team or
SEO wizards want it to be /{slug} and that’s pretty tricky. You can’t
create the pattern /{post-slug} because it’s going to confuse the
system. What is you have an About Us page or a Contact Us page which
equally important urls like /about-us and /contact-us respectively.
The problem here being that the routing system might pick up the
/about-us link and believe it’s meant to be a slug for a Post model.
At this point Laravel will simply not find the model and throw a HTTP
404 error instead. Not good.
This is where the ‘defaults’ method on routes comes into use to save
the day.
if I consider your example then
Route::get('/atomic/{id}',[ApiController::class,'index'])->defaults('task', 'atomic');
while hitting URL http://127.0.0.1:8002/atomic/1 then in the controller,you will get both params $id and $task
public function index($id,$task){
dump($task);
dump($id);
}
the output of the above will be atomic and 1
defaults() method nothing but key-value pair params
/**
* Set a default value for the route.
*
* #param string $key
* #param mixed $value
* #return $this
*/
public function defaults($key, $value)
{
$this->defaults[$key] = $value;
return $this;
}
suppose if you want to pass multiple array params then use setDefaults method like below
Route::get('/atomic/{id}',[ApiController::class,'index'])->setDefaults([
'tasks'=> 'atomics',
'postTitle'=>'post title goes here'
]);
then in controller
public function index($id,$tasks,$postTitle){
dump($tasks);
dump($postTitle);
dump($id);
}
now if you hit URL http://127.0.0.1:8002/atomic/1 then it will print
atomics
post title goes here
1
Ref : The Power of Laravel’s Route ‘defaults’ for making root level SEO pages

Create a route on symfony based on a json body

My goal is to have a route that if the body which is a json string contains the string "type":"pay" to apply the route.
I tried this:
/*
* #Route(
* path="/myfunction",
* condition="request.getContent() matches '/\\b\\"type\\":\\"pay\\"\\b/i'"
* )
*/
But until now I get exception because when it finds the double quote " before type it thinks that the condition part should be over.
And I get exception like this:
Caused by
Symfony\Component\Config\Exception\FileLoaderLoadException: [Syntax Error] Expected Doctrine\Common\Annotations\DocLexer::T_CLOSE_PARENTHESIS, got 'type' at position 147
Until now I tried the following
condition="request.getContent() matches '/\\b"type":"pay"\\b/i'"
condition="request.getContent() matches '/\\b\"type\":\"pay\"\b/i'"
condition="request.getContent() matches '/\\b\\\\\\\\"type\\\\\\\\":\\\\\\\\"pay\\\\\\\\"\\b/i'"
According to the documentation http://symfony.com/doc/3.4/components/expression_language/syntax.html
I am using symfony 3.4
What you could do, is create an EventListener that listens to the kernel.request-event and has a priority that puts it before Symfony's RouterListener::onKernelRequest() for finding routes.
In this custom listener you can add an attribute to the request, which you can fill with the data from the request body. It could look something like this:
public function onKernelRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
// Maybe abort before reading content, if we don't expect a JSON-body
$jsonEncodedContent = $request->getContent();
// Decode JSON, validate
$request->attributes->set('content_type', ...);
}
Then in your route you should be able to access this attribute instead of reading the json body, you can access this attribute:
condition="request.attributes.content_type == 'pay'"
The downside to this approach is, that your listener must run at the right point, which might cause some issues later on as it's hard to test for this, and this might be hard to find and understand for new developers on your project.

Typo3 extension: Transfering an object via arguments doesn't work. What am i doing wrong?

Before i state my problem, please be aware that this is my first time working with Typo3 and/or creating an Extbase extension.
SO basically i want to create an extbase extension for Typo3, but i seem not to be able to wrap my head around the concept of transfering an object (assigned to the view of a specific template) via arguments to an action, with the purpose of attaching the object to another (with a 1:n relation).
My example:
I have an Objekt of the type "Appliance" assigned to the view of a template ("Show.html"). I can list all the properties of it in the Template, so it definitely exists in the view.
Now i want to create an Object of the type "Host" using a form and then attaching it to this specific "Appliance" object.
The problem is: I can't transfer the object of the type "Appliance" to the specific Action of the Controller of the type "Host" which itself should then assign it to the view of another template.
Look at the following code example:
<f:link.action action="new" controller="Host" arguments="{appliance:appliance}" >Add Host X</f:link.action>
This is the specific code line in the "Show.html" template that transfers the "Appliance" object to the Action "new" of the "Host" controller using arguments... The "Host" controller:
public function newAction(\Cjk\Icingaconfgen\Domain\Model\Appliance $appliance, \Cjk\Icingaconfgen\Domain\Model\Host $host = NULL)
{
$this->view->assign('appliance', $appliance);
$this->view->assign('host', $host);
}
At this point i get the following error message:
"Argument 1 passed to
Cjk\Icingaconfgen\Controller\HostController::newAction() must be an
instance of Cjk\Icingaconfgen\Domain\Model\Appliance, none given"
What am i doing wrong?
You need a Docblock that describes these parameters.
What may look like just comments, actually follows the PHPDoc standard. These declarations are interpreted by the TYPO3 ReflectionClass to map your Domain Model and validate parameters and object properties.
Make sure you completely flush the cache whenever you add or update one of these.
/*
* #param \Cjk\Icingaconfgen\Domain\Model\Appliance $appliance
* #param \Cjk\Icingaconfgen\Domain\Model\Host $host
* #return void
*
*/
public function newAction(\Cjk\Icingaconfgen\Domain\Model\Appliance $appliance, \Cjk\Icingaconfgen\Domain\Model\Host $host = NULL)
{
$this->view->assign('appliance', $appliance);
$this->view->assign('host', $host);
}
You need to be sure that there is an Appliance model given in your Fluid template, easily by debugging it before the link with e.g. <f:debug>{appliance}</f:debug>
If this is okay, you should add some doc comments above your newAction because Extbase is referring to that.
An example would be: (just as I am writing this, a good example was posted). :)

Symfony error - object not found

I am sorry for asking such a question and I know there have been questions like this before, but my case is rather...stupid. What I have is a project management system and I want to display all projects which works fine and is auto generated by Symfony. In the same controller which is ProjectController I made another action. I wanted to list all archived projects which have been completely done. For a start I simply copy pasted the code and the annotations and changed the routes and the name of the function. Here is my indexAction function
/**
* Lists all project entities.
*
* #Route("/", name="project_index")
* #Method("GET")
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$projects = $em->getRepository('AppBundle:Project')->findAll();
return $this->render('project/index.html.twig', array(
'projects' => $projects,
));
}
It is as simple as it can get. Now here is my archiveAction function which is the same
/**
* Lists all project entities.
*
* #Route("/archive", name="project_archive")
* #Method("GET")
*/
public function archiveAction()
{
$em = $this->getDoctrine()->getManager();
$projects = $em->getRepository('AppBundle:Project')->findAll();
return $this->render('project/index.html.twig', array(
'projects' => $projects,
));
}
So far I am not even filtering the projects, but doing the exact same thing as I do in the indexAction function and bear in mind both functions are in the same controller. Here is the error I receive when trying to show all archived projects -
AppBundle\Entity\Project object not found.
The index action works just fine and displays all projects, but if I change the route and change the name of the function and keep everything the same and they are in the same Controller - in one case it can find AppBUndle\Entity\Zadanie, but in the other case - it can't.
SOLVED I managed to solve the problem by putting the archive function on top. By on top I mean in first position before any other function. Before doing so I tried switching the routes. I took the route from indexAction and put it in the annotations from the archiveAction and the opposite. Both functions worked just fine. Then I returned them as they were and archive still didn't work. Then I simply put archive in first place before index and it worked as a charm. I have no idea what just happened and why but...didn't matter...it works. ( seriously though - if anybody knows why that is I would appreciate it)
EDIT: So 2 years and 4 months later I think I got the crank of it, the routes are cached so what I did was just clear the cache and it worked, but at the time I didnt pay attention to this detail
I found the same problem and I managed to find the cause of the problem.
routing problem, for example:
#Route ("/ {id}", name = "project_archive_show")
function2
#Route ("/ archive", name = "project_archive")
function1
urls must have personalized specifications:
for example :
#Route ("/ show / {id}", name = "project_archive_show")
function2
or says that id is an integer

How to create a route with custom path in Symfony RoutingBundle (PHPCR)?

I'm currently researching Symfony CMF and PHPCR for a project I recently started. What I'm currently trying to figure out is how to create a Route and save it into the database. As far as I understand, I must use Symfony\Cmf\Bundle\RoutingBundle\Doctrine\Phpcr\Route and persist the element into the database. This works fine, but automatically generates a route path, which is not what I want. What I need to do is generate a custom route which links to a specific controller. Here is my code:
$em = $this->get('doctrine_phpcr.odm.document_manager');
$parent = $em->find(null, '/cms/routes');
$route = new \Symfony\Cmf\Bundle\RoutingBundle\Doctrine\Phpcr\Route();
$route->setParentDocument($parent);
$route->setName('my_route_name');
$route->setDefault('_controller', 'AppBaseBundle:Frontend/Users:index');
$em->persist($route);
$em->flush();
If i execute this code, the generated route will be /cms/routes/my_route_name. From what I can see, you could use $route->setPath('/testing');, but that generates the following exception:
Can not determine the prefix. Either this is a new, unpersisted document or the listener that calls setPrefix is not set up correctly.
Does anybody have any ideas how to solve this?
In PHPCR, every document has a path where it is store. If you are familiar with doctrine ORM, the path has the role of the ID. The difference with ORM is that all documents (regardless of their type) live in the same tree. This is great, because your route can reference just anything, it is not limited to specific document types. But we need to create some structure with the paths. This is why we have the prefix concept. All routes are placed under a prefix (/cms/routes by default). That part of the document path is removed for the URL path. So repository path /cms/route/testing is the url domain.com/testing.
About your sample code: Usually, you want to configure the controller either by class of the content document or by route "type" attribute to avoid storing a controller name into your database to allow for future refactoring. A lot of this is explained in the [routing chapter of the CMF documentation][1] but the prefix is only used there, not explicitly explained. We need to improve the documentation there.
[1] http://symfony.com/doc/master/cmf/book/routing.html
I managed to find a way to overcome this issue. Because in my project I also have the RouteAutoBundle, I created a class which extends \Symfony\Cmf\Bundle\RoutingBundle\Doctrine\Phpcr\Route. Inside that class I added:
/**
* #PHPCR\Document(referenceable=true)
*/
class MenuRoute extends Route
{
protected $url;
/**
* Get $this->url
*
* #return mixed
*/
public function getUrl() {
return $this->url;
}
/**
* Set $this->url
*
* #param mixed $url
*/
public function setUrl($url) {
$this->url = $url;
}
}
After that I added this to cmf_routing_auto.yml:
App\MenuBundle\Document\MenuRoute:
uri_schema: /{getUrl}
token_providers:
getUrl: [content_method, { method: getUrl }]
So now one would just create an instance of MenuRoute (just like when using Route) and call the method setUrl($your_url) passing the desired url.
If anybody finds a better way, I'm opened to suggestions.

Categories