How to add a prefix to many routes in Symfony 4 - php

I'd like all my Controller action routes in the namespace 'App\Controller\Api' to have the prefix '/api'. I also want to use annotations inside the controllers to set the rest of the route.
In Symfony 3 this was done by editing 'config/routing.yml':
app:
resource: '#AppBundle/Controller/Api'
type: annotation
prefix: /api
How can I do this in Symfony 4? Do I need to make a bundle? Which config file would I use since I don't have a 'config/routing.yml'?

Ok It looks like I should have just tried real path names. The following worked in 'config/routes.yaml':
api:
prefix: /api
resource: '../src/Controller/Api'

At first run composer require annotations and then
use Symfony\Component\Routing\Annotation\Route;
/**
* #Route("/blog")
*/
class BlogController extends Controller
{
}

Related

How to override the controller for Symfony4

I want to override the tird-party bundle's controller in Symfony4.
in this explanation.
It says.
If the controller is a service, see the next section on how to override it. Otherwise, define a new route + controller with the same path associated to the controller you want to override (and make sure that the new route is loaded before the bundle one).
What I want to do is to override this Controller.
myapp/vendor/sonata-project/admin-bundle/src/Controller/CRUDController.php
Now I make CRUDController.php in
myapp/src/Controller/CRUDController.php
It doesn't work,, maybe of course though.
However, what should I do next???
Thanks to #DreamOn comment
I made the file myapp/src/Controller/CRUDController.php
<?php
namespace App\Controller;
use Sonata\AdminBundle\Controller\CRUDController as BaseCRUDController;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class CRUDController extends BaseCRUDController{
}
But, it doesn't work, I guess I should do some routing setting.
Normally SonataAdmonBundle is routed like this.
routing.yml
admin_area:
resource: "#SonataAdminBundle/Resources/config/routing/sonata_admin.xml"
prefix: /admin
_sonata_admin:
resource: .
type: sonata_admin
prefix: /admin
However Symfony4/3.4 recommend annotation routing.
It makes me confused.
How can I register/routing my Controller?
I use this instead, not override.
Extend bundle controller. Add bundle controller as a base controller by:
use Sonata\AdminBundle\Controller\CRUDController as BaseCRUDController;
And make your CRUDController extends BaseCRUDController

Symfony 4 - controllers in two directories

In my application, I use Symfony 4. I want Symfony to search for controllers in two directories: A and B. I found something like this:
controllers:
resource: '../src/DirectoryA/Controller/'
type: annotation
, but it only works for one directory. How can I have Symfony to search for controllers in two directories?
Regards
In your config/services.yaml
App\DirectoryA\Controller\: # assuming you have namespace like that
resource: '../src/DirectoryA/Controller'
tags: ['controller.service_arguments']
App\DirectoryB\Controller\: # assuming you have namespace like that
resource: '../src/DirectoryB/Controller'
tags: ['controller.service_arguments']
This will add next directory for service arguments. Thats answers your questions based In directory, what you have posted is routing file, in there would be similiar
controllers_a:
resource: '../src/DirectoryA/Controller/'
type: annotation
controllers_b:
resource: '../src/DirectoryB/Controller/'
type: annotation
The accepted answer is of course completely correct.
However, once you move from having one controller directory to multiple directories, updating your services.yaml file can be a bit of a pain. Even having to have directories specifically for controllers can be limiting.
Here is an alternate approach which allows creating controllers wherever you want and automatically tagging them.
Start with an empty controller interface for tagging.
interface ControllerInterface {}
Now have all your controllers implement the interface
class Controller1 implements ControllerInterface { ...
class Controller2 implements ControllerInterface { ...
And then adjust the kernel to automatically tag all your controller interface classes with the controller tag.
# src/Kernel.php
protected function build(ContainerBuilder $container)
{
$container->registerForAutoconfiguration(ControllerInterface::class)
->addTag('controller.service_arguments')
;
}
And presto. You can create your controllers wherever you want with nothing in services.yaml.
Update:
If you would like to avoid editing Kernel.php then you can use the _instanceof functionality in your services.yaml file.
#config/services.yaml
services:
_instanceof:
App\Contract\ControllerInterface:
tags: ['controller.service_arguments']
Another Update: As long as your controller extends Symfony's AbstractController then no additional tagging is needed. You can even delete the default controller lines in the default services.yaml file if you want.

File routing on symfony

I was reviewing the symfony 3.4 routing page. I have a misunderstanding if anyone can help me. So say you have the following:
In Your controller:
class BlogController extends Controller
{
/**
* Matches /blog exactly
*
* #Route("/blog", name="blog_list")
*/
public function listAction()
{
// ...
}
}
And in your routing.yml:
blog_list:
path: /blog
defaults: { _controller: AppBundle:Blog:list }
Would you be able to delete the route annotation above the function. Because now the routing is being handled by the routing.yml?
Many thanks
You must choose one of this methods to set route for current url "/blog"
In Symfony Routing can be declare using YAML, XML, PHP or annotation. It is recommended you stick with only one but you can use multiple approaches in a single project.
Official doc for routing Symfony Routing
and the answer to your question is, I would say yes you could delete the annotation.
Because now the routing is being handled by the routing.yml
for the big project, I prefer YML routing.

Symfony 4 - how to use service tags when autowiring an entire path

I'm working on a bundle for Symfony 4 that is structured like this:
\Acme
\FooBundle
\Article
\Entity
- Article.php
- Comment.php
\Form
- ArticleType.php
\Repository
- ArticleRepository.php
- CommentRepository.php
- ArticleManager.php
\User
\Entity
- User.php
\Repository
- UserRepository.php
- UserManager.php
\SomethingElse
\Entity
- SomethingElse.php
\Repository
- SomethingElseRepository.php
- SomethingElseManager.php
There are many more folders and entities, but is irrelevant for the question.
Autowiring all the classes in that folder can be created with a config like this one:
Acme\FooBundle\:
resource: '../../*/{*Manager.php,Repository/*Repository.php}'
exclude: '../../{Manager/BaseManager.php,Repository/BaseRepository.php}'
autowire: true
But when you need to add service tags like doctrine.repository_service, this kind of configuration won't help no more. Without the tag, when using in controller like:
$this->getDoctrine()->getRepository(Bar::class)
or
$this->getDoctrine()->getManager()->getRepository(Bar::class)
it throws an error:
The "Acme\FooBundle\SomethingElse\Repository\SomethingElseRepository" entity repository implements "Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepositoryInterface", but its service could not be found. Make sure the service exists and is tagged with "doctrine.repository_service".
The thing is that, since they all reside in the same root folder I'm not allowed to use a config like the following one, because it would have duplicated Acme\FooBundle\ keys:
Acme\FooBundle\:
resource: '../../*/{*Manager.php}'
exclude: '../../{Manager/BaseManager.php}'
autowire: true
Acme\FooBundle\:
resource: '../../*/{Repository/*Repository.php}'
exclude: '../../{Repository/BaseRepository.php}'
autowire: true
tags: ['doctrine.repository_service']
So, I was wondering if there's a workaround that I couldn't find or I should just manually add each and every service?
Edit:
It would have been a nice feature to be able to use an annotation in the class so when it's loaded it "knows" it's tag, but I'm thinking it works the other way around, loading a class because is was tagged with a certain tag.
I had the same error message after upgrading to symfony 4.4 from 3.4.
The issue seemed to be that the entity had an annotation to #ORM\Entity(repositoryClass="App\Repository\MyRepository")
while the repository extends ServiceEntityRepository and in the constructor points to the entity parent::__construct($registry, MyEntity::class);.
Removing the annotation on the entity fixed the issue.
I encountered the same error message after refactoring (renaming) some entities and the related repositories using PhpStorm 2019.2 The refactor did not update the repository class name in the doc block for the entity:
* #ORM\Entity(repositoryClass="App\Repository\OldRepository")
So I used right-click > Copy Reference to get the fully qualified name of NewRepository and pasted it in to the doc block reference:
* #ORM\Entity(repositoryClass="\App\Repository\NewRepository")
PhpStorm prefixed the class with a backslash and I didn't notice until after trying many combinations of suggested solutions for this error. I only needed to remove the backslash and the error is gone:
* #ORM\Entity(repositoryClass="App\Repository\NewRepository")
You can autoconfigure tags in your Kernel / Main Bundle Class:
https://symfony.com/doc/current/service_container/tags.html#autoconfiguring-tags
<?php
namespace Acme\FooBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class FooBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->registerForAutoconfiguration(EntityRepository::class)
->addTag('doctrine.repository_service');
}
}
You can tag all of your repositories, like this:
App\Repository\:
resource: '../src/Repository'
autowire: true
tags: ['doctrine.repository_service']
Thanks #t-van-den-berg and #arleigh-hix !
I had this problem after migrating from Symfony 3.4 to 4.4, when I wanted to use old Repositories with new services.
My solution was a little variation:
use App\Repository\NewRepository;
//...
/**
* #ORM\Entity(repositoryClass=NewRepository::class)
*/
And service declaration (to use Interface):
App\Repository\NewRepository:
arguments:
- "#doctrine"
App\Repository\NewRepositoryInterface: '#App\Repository\NewRepository'

How can I add some route prefix to all controllers in Symfony2?

I am using annotations to define routes in controllers and I have 15 controllers. All are executed by /path1 , /path2.
Is there any way that in all those controller , I can access them via /admin/path1 and /admin/path2?
I don't want to enter that by changing each file.
Can I do that from a single location? I mean the whole bundle should open via /admin and then their respective paths.
try this
# app/config/routing.yml
acme_hello:
resource: "#AcmeHelloBundle/Resources/config/routing.yml"
prefix: /admin
or if using annotations
resource: "#AcmeHelloBundle/Controller"
type: annotation
prefix: /admin
Use this in routing.yml:
Admin:
resource: "#AdminBundle/Controller"
type: annotation
prefix: /admin
Just define the annotation for your Class (not for method)
/**
* #Route("/blog")
*/
http://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/routing.html#route-prefix
If you want to prefix specific controller DevController for example and have something like:
myproject.com/dev/test
in your Controller add the following Route annotation as in example:
/**
* #Route("/dev")
*/
class DevController extends Controller{
/**
* #Route("/test")
*/
public function testSavingAction(){
return new Response();
}
....

Categories