How to override the controller for Symfony4 - php

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

Related

Controller has no container set, did you forget to define it as a service subscriber

I'm trying to refactor some controllers in Symfony 5 server, but suddenly I'm unable to change or create controllers because of the following error:
'App\Controller{{ControllerName}}' has no container set, did you forget to define it as a service subscriber?
This is the controller:
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Request;
use App\Entity\Shiftsummary;
use App\Entity\Station;
use App\Entity\Shift;
use App\Entity\Line;
use \Datetime;
class StartStationController extends AbstractController {
/**
* #Route("/start", name="StartStation")
*/
public function route(Request $request)
{
...
} }
This is the content of service.yaml
services:
_defaults:
autowire: true
autoconfigure: true
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
App\Controller\:
resource: '../src/Controller'
tags: ['controller.service_arguments']
The controllers are inside the src/controller/ folder
The issue had to do with the cached files, deleting /var/cache made the error not occur.
Thanks go to Cerad for point this out.
I have to add that if you set the wrong namespace, you get this error too:
// src/Controller/Api/ProductController.php
namespace App\Controller;
class ProductController extends AbstractController {}
namespace must follow folders structure.
namespace App\Controller\Api;
this is just it, your controller did not have container injected. However, framework expects it to be done if your controller inherits from AbstractController.
in ControllerResolver.php:
TLDR; What you need is to inject it.
In your services.yaml, add the following setter call
In my case, the class had just a different name than the file.
You have to change:
namespace App\Controller;
with:
namespace App\Controller\Api;
None of above helped in my case.
I solved my case by:
calls:
- [setContainer, ["#service_container"]]
https://symfony.com/doc/5.4/service_container/calls.html
In my case it was an error in the controller name when I used the bin/console command :
bin/console make:controller APIController this command add automatically suffix -Controller to the file.
Then the controller created is called APIControllerController.
Next I made a copy/paste of Auth0 guide to create API nammed APIController.
In the end the file had the name APIControllerController.php and the class APIController: you just had to change the filename and remove the duplicate -Controller suffix.
Or - in general - verify the name of file controller and the class name ;)
(Another possibility, even more basic than the other suggestions:)
I had a simple controller that was requiring another PHP file, but in the course of some changes that required file couldn't even be compiled. Fixing that required file resolved the somewhat misleading "has no container set..." message.
I have just resolved this issue.
Turned out for me - I had miss typed __construct() as a private function, should be public

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.

How to add a prefix to many routes in Symfony 4

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
{
}

Symfony where to initialize routes? (routing.yml or inside controller)

On the routing page of smyfony is an routing example (the first one). Now they give us 4 options of code (Annotations, YAML, XML, PHP). Where is the difference? And maybe you can take a look on my Controller + Route.
The controller looks like this:
<?php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class ToDoListController extends Controller
{
/**
* #Route("/ToDoList", name="ToDoList")
*/
public function showToDoList()
{
}
}
?>
Now I added this route into the routing.yml too.
ToDoList:
path: /Aufgabenliste
defaults: {_controller: AppBundle\Controller \ToDoListController::showToDoList}
Is that correct? Whats about the path? In the first example of the symfony page they wrote defaults: { _controller: AppBundle:Blog:show } but in the description they wrote:
The _controller string is called the logical name. It follows a pattern that points to a specific PHP class and method, in this case the AppBundle\Controller\BlogController::listAction and AppBundle\Controller\BlogController::showAction methods.
Allright. So in Symfony you get to choose between different methods of routing. You can do this for example via annotations or yml(I used to use yml but now I switched to annotations). The only difference is in... format of the file ;) For example I realy like to use annotations because instead of having one billion entries in one file I have every route right next to the code it leads to. At this point for you it depends on what you like better. However I think it's considered as good practice to use annotations.
<?php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class ToDoListController extends Controller
{
/**
* #Route("/ToDoList", name="ToDoList")
*/
public function showToDoList()
{
}
}
?>
Code above is ok - you used required namespaces and created correct annotation. All of this you have to do in your bundle you are working on. Also you have to go to app/config/routing.yml and put there something like this:
YourBundleName:
resource: "#YouBundle/Controller/"
type: annotation
Of course it's just an example - you need to adjust it to your needs. This way you are saying to Symfony that you want to use annotations.

Categories