Create an action - Symfony2 - symfony

I created a bundle backend/main/:
my app/routing.yml
backendmain:
resource: "#backendmainBundle/Resources/config/routing.yml"
prefix: /main
my backend/Bundle/mainBundle/config/routing.yml:
backendmain_homepage:
pattern: /hello/{name}
defaults: { _controller: backendmainBundle:Default:index }
my backend/Bundle/mainBundle/DefaultController.php:
namespace backend\Bundle\mainBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class DefaultController extends Controller
{
public function indexAction($name)
{
return $this->render('backendmainBundle:Default:index.html.twig', array('name' => $name));
}
public function testAction($name)
{
return $this->render('backendmainBundle:Default:test.html.twig', array());
}
}
How can I call the action test in my browser?
Sorry, but was Fabien on drugs, when he created Symfony2? Symfony 1.4 was so freaking easy!

There isn't any match in your routes definition for the test action. The only route you added is for the index action. So you need to add something like,
backendmain_test:
pattern: /test
defaults: { _controller: backendmainBundle:Default:test }
In your backend/Bundle/mainBundle/config/routing.yml file so that you can make a call to your test action.
Update:
Using annotations
app/config/routing.yml
backendmain:
resource: "#backendmainBundle/Controller/DefaultController.php"
prefix: /main
type: annotation
DefaultController.php
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
// ...
class DefaultController extends Controller
{
/**
* #Route("/test", name="backendmain_test")
*/
public function testAction()
{
// ...
}
// ...

Related

Symfony Routing only works in debug mode

I try to add an route to my symfony Projekt. But it doesnt work.
My routing.yml:
app:
resource: '#AppBundle/Controller/'
type: annotation
login:
path: /login
defaults: { _controller: AppBundle:Login:index }
My LoginController.php:
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class LoginController extends Controller
{
/**
* #Route("/login", name="homepage")
*/
public function indexAction(Request $request)
{
// replace this example code with whatever you need
return $this->render('login/index.html.twig', [
'base_dir' => realpath($this->getParameter('kernel.project_dir')).DIRECTORY_SEPARATOR,
]);
}
}
When i try to load this page, i become "The server returned a "404 Not Found"."
But when i open app.php and change this line:
$kernel = new AppKernel('prod', false);
to this one:
$kernel = new AppKernel('prod', true);
it works.
Why, i have to set debug true, to load this page?
When i use app_dev.php/login all works fine. No error appears. Site will be loaded.
I have def. changed the routing.yml file. not the routing_dev.yml!
Thank you !!

Symfony 3 inject service into controller

I'm using symfony 3.1.7 and I have problems with inject services into a controller, my english is bad I believe that it is better if I show all the code.
The error:
Type error: Argument 1 passed to
...Bundle\Controller\AdminController::__construct() must
implement interface
Symfony\Component\DependencyInjection\ContainerInterface, none given,
called in /......./project/var/cache/dev/classes.php on line 2512
This is my code:
GenericRestController
namespace MyCoreBundle\Controller;
use Symfony\Component\DependencyInjection\ContainerInterface as Container;
use MyCoreBundle\Handler\GenericRestHandlerInterface as Generic;
/** other uses like FOSRestController **/
/**
* Class GenericRestController
*/
abstract class GenericRestController extends FOSRestController
{
protected $handler;
protected $container;
public function __construct(Container $container,Generic $handler)
{
$this->container = $container;
$this->handler = $handler;
}
/** other methods like get, post, put, etc **/
}
AdminController
namespace ...Bundle\Controller;
use MyCoreBundle\Controller\GenericRestController;
class AdminController extends GenericRestController
{
}
RESOLVED
The solution was change the routes as Cerad says.
Oficial documentation
services.yml
services:
app.hello_controller:
class: AppBundle\Controller\HelloController
routing.yml
hello:
path: /hello
defaults: { _controller: app.hello_controller:indexAction }
Thanks mtaqi and Cerad
The solution was change the routes as Cerad says.
Oficial documentation
services.yml
services:
app.hello_controller:
class: AppBundle\Controller\HelloController
routing.yml
hello:
path: /hello
defaults: { _controller: app.hello_controller:indexAction }
Sorry for the delay and thanks!

Inject Doctrine Repository into controller

I had the following controller:
<?php
namespace AppBundle\Controller;
use AppBundle\Controller\BaseController;
use Symfony\Component\HttpFoundation\Request;
class UserController extends BaseController
{
public function allAction(Request $request)
{
$users = $this->getDoctrine()
->getRepository('AppBundle:User')
->findAll();
return $this->respond(['users' => $users], 200);
}
}
And I would like to inject the repository into the controller (for testing purposes)
Controller:
<?php
namespace AppBundle\Controller;
use AppBundle\Controller\BaseController;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\HttpFoundation\Request;
class UserController extends BaseController
{
private $userrepository;
public function __construct(EntityRepository $userrepository)
{
$this->userrepository = $userrepository;
}
public function allAction(Request $request)
{
$users = $this->userrepository->findAll();
return $this->respond(['users' => $users], 200);
}
}
services.yml
services:
userrepository:
class: Doctrine\ORM\EntityRepository
factory_service: doctrine.orm.entity_manager
factory_method: getRepository
arguments:
- AppBundle\Entity\User
usercontroller:
class: AppBundle\Controller\UserController
arguments:
- "#userrepository"
routing.yml
api_users_all:
path: /api/users.{_format}
defaults: { _controller: usercontroller:allAction, _format: json }
requirements:
_method: GET
I keep facing the following error:
PHP Fatal error: Call to a member function get() on a non-object in /Applications/MAMP/htdocs/api/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php on line 350
line 350
return $this->container->get($id);
So my guess is that the controller is no longer 'ContainerAware' or something like that.
But I can't seem to figure this out.
I am working with symfony 2.7
After you configure the router to call controller via service, controller is not created directly but requested from the Dependency Injection container. And yes, there is no longer container because you inject only one parameter to it: user repository.
If you want whole container (which is not recommended) and you extending Symfony Controller in your BaseController set it in your service:
services:
usercontroller:
class: AppBundle\Controller\UserController
calls:
- [setContainer, ["#service_container"]]
arguments:
- "#userrepository"
If you not extending Symfony Controller, inject container as argument:
services:
usercontroller:
class: AppBundle\Controller\UserController
arguments:
- "#userrepository"
- "#service_container"
Controller:
class UserController extends BaseController
{
private $userrepository;
private $container;
public function __construct(EntityRepository $userrepository, $container)
{
$this->userrepository = $userrepository;
$this->container = $container;
}
It's not recommended, inject only what you want eg. if you use in your controller only repository and mailer inject only them not the whole container.

How to definitely disable registration in FOSUserBundle

In my project, I allow only one user to manage the content of the website. This user will be added using the command line at first.
Now, I want to get the registration action inaccessible and I don't know how?
Till now, I just put the ROLE_ADMIN in the access control for the route register to avoid that visitors can go throw it.
Any tips?
Take a look at the routing configuration imported from
vendor/friendsofsymfony/user-bundle/Resources/config/routing/all.xml
If you want just the basic security actions, just import
#FOSUserBundle/Resources/config/routing/security.xml
instead of
#FOSUserBundle/Resources/config/routing/all.xml
This way you can simply select which components (security, profile, resetting, change_password) you want to use or event import only specific routes from those components.
There are many ways to solve this issue. You can simply remove fos_user_registration_register route from routing.yml. Or use more complicated solution: set up event listener to FOS\UserBundle\FOSUserEvents::REGISTRATION_INITIALIZE event and redirect user to login page.
services.xml
<service id="app.registration.listener" class="AppBundle\EventListener\RegistrationListener">
<tag name="kernel.event_subscriber" />
<argument type="service" id="router" />
</service>
RegistrationListener.php
<?php
namespace AppBundle\EventListener;
use FOS\UserBundle\Event\GetResponseUserEvent;
use FOS\UserBundle\FOSUserEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
class RegistrationListener implements EventSubscriberInterface
{
/**
* #var UrlGeneratorInterface
*/
private $router;
/**
* #param UrlGeneratorInterface $router
*/
public function __construct(UrlGeneratorInterface $router) {
$this->router = $router;
}
public static function getSubscribedEvents()
{
return [
FOSUserEvents::REGISTRATION_INITIALIZE => 'onRegistrationInitialize',
];
}
public function onRegistrationInitialize(GetResponseUserEvent $event)
{
$url = $this->router->generate('fos_user_security_login');
$response = new RedirectResponse($url);
$event->setResponse($response);
}
}
You can just change app/config/security.yml:
- { path: ^/register, role: ROLE_ADMIN }
Change from the default (IS_AUTHENTICATED_ANONYMOUSLY) to ROLE_ADMIN and it will stop allowing anonymous users from getting to the /register form.
Another simple solution (the one I used) is to overwrite the registerAction() default FOSUserBundle controller method:
namespace Acme\UserBundle\Controller;
use FOS\UserBundle\Controller\RegistrationController as FOSRegistrationController;
use Symfony\Component\HttpFoundation\Request;
class RegistrationController extends FOSRegistrationController
{
public function registerAction(Request $request)
{
return $this->redirectToRoute('getStarted', array(), 301);
}
}
Doing this will leave active other routes, as the confirmation page.
I simply overwrote the register action and redirect the user to my first registration page (getStarted).
If you use the JMSSecurityExtraBundle you can use the denyAll directive like so:
- { path: ^/register, access: denyAll }
This is how I solve this issue...
First you have to define your listener in the services.yml file:
services:
registrationListner:
class: App\YourBundle\Listener\RegistrationListener
arguments: [#service_container]
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest}
Then create your class RegistrationListener:
<?php
namespace App\YourBundle\Listener;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
class RegistrationListener
{
private $router;
public function __construct(ContainerInterface $container){
$this->router = $container->get('router');
}
public function onKernelRequest(GetResponseEvent $event)
{
$route = $event->getRequest()->attributes->get('_route');
if ($route == 'fos_user_registration_register') {
//here we're gonna to redirect to you_route for example, I guess in the most cases it will be the index...
$event->setResponse(new RedirectResponse($this->router->generate('your_route')));
}
}
}
Hope it helps.
You can try to change your routing.yml
fos_user_registration_register:
path: /register{trailingSlash}
defaults: { _controller: AcmeBundle:Default:register, trailingSlash : "/" }
requirements: { trailingSlash : "[/]{0,1}" }
And in your DefaultController
public function registerAction(Request $request)
{
return $this->redirectToRoute('404OrWhatYouWant');
}

Redirect with Event Listener for all "No route found 404 Not Found - NotFoundHttpException"

How can I trigger redirect to a specific router in event listener?
There are many examples but I couldn't find one for "GetResponseForExceptionEvent". For exampe, when I pass #roter as an argument $this->router.... doesn't seem to be working so on.
I checked these but I probably missed something:
Show a specific route instead of error page (404) - Symfony2
symfony2: hook into NotFoundHttpException for redirection
Symfony2 redirect for event listener?
Symfony2: Getting Route in Page Load Event Listener
Redirect if the user is logged in
service.yml
services:
kernel.listener.kernel_request:
class: Booking\AdminBundle\EventListener\ErrorRedirect
tags:
- { name: kernel.event_listener, event: kernel.exception, method: onKernelException }
Event listener:
namespace Booking\AdminBundle\EventListener;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class ErrorRedirect
{
public function onKernelException(GetResponseForExceptionEvent $event)
{
$exception = $event->getException();
if ($exception instanceof NotFoundHttpException) {
// redirect to '/' router or '/error'
//$event->setResponse(...........);
}
}
}
You have 2 options:
Use an Event Listener
Use a route that matches all the routes that don't exist and trigger an action in a controller.
Let me know if that works.
Option 1
Note: Have a look at Symfony2 redirect for event listener
1 Pass the router to your event listener:
kernel.listener.kernel_request:
class: Booking\AdminBundle\EventListener\ErrorRedirect
arguments:
router: "#router"
tags:
- { name: kernel.event_listener, event: kernel.exception, method: onKernelException }
2 Use the router within the listener to redirect users:
namespace Booking\AdminBundle\EventListener;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Bundle\FrameworkBundle\Routing\Router;
class ErrorRedirect
{
/**
* Holds Symfony2 router
*
*#var Router
*/
protected $router;
/**
* #param Router
*/
public function __construct(Router $router)
{
$this->router = $router;
}
public function onKernelException(GetResponseForExceptionEvent $event)
{
$exception = $event->getException();
if ($exception instanceof NotFoundHttpException) {
/** Choose your router here */
$route = 'route_name';
if ($route === $event->getRequest()->get('_route')) {
return;
}
$url = $this->router->generate($route);
$response = new RedirectResponse($url);
$event->setResponse($response);
}
}
}
Option 2
You can create a special route that will match all routes that don't exist; You can then handle the redirect the way you want within the controller of your choice, here PageNotFoundController:
1 At the end of app/config/routing.yml
pageNotFound:
pattern: /{path}
defaults: { _controller: AcmeDemoBundle:PageNotFound:pageNotFound, path: '' }
requirements:
path: .*
2
<?php
namespace Acme\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class PageNotFoundController extends Controller
{
public function pageNotFoundAction()
{
// redirect the way you want
}
}

Resources