I'm using Symfony2 and i'm trying to POST a form to my controller, but my controller take it as a GET request everytime... Even when i'm using restclient, i put POST for the request but when i use $request->getMethod(), the answer is always GET :/
The source code is really simple :
<?php
namespace TC\UserBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class UserController extends Controller
{
/**
* #Route("/user/register")
* #Method({"POST"})
*/
public function registerAction(Request $request)
{
echo $request->getMethod();
return new Response();
}
}
And when i add the requirements _method: POST like this :
tc_user_register:
path: /user/register/
defaults: { _controller: TCUserBundle:User:register }
requirements:
_method: POST
I got this :
No route found for "POST /user/register"
Whatever i do, Symfony2 take it as a GET request, any idea ?
Thanks !
Couple of things #Xtroyer:
1 If you use routing.yml file, requirements: _method is not recognised since Symfony 2.2, it is now:
tc_user_register:
path: /user/register/
defaults: { _controller: TCUserBundle:User:register }
methods: [POST]
2 If you use Annotations. #Method is not recognised if you don't mention the following use statement in your controller:
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
3 You can check what route is exactly registered with the following command?
php app/console router:debug | grep tc_user_register
You should have:
Name Method Scheme Host Path
tc_user_register POST ANY ANY /user/register/
Related
I have a Symfony (4.1) project. In this project i need to create new route, like this.
Controller
/**
*
* #Route("/search-user", name="search-user")
*/
public function searchUser(Request $request)
{
dd("Search user");
return $this->render("XXX");
}
Routes.yaml
controllers:
resource: '../src/Controller/'
type: annotation
prefix: '/'
The problem: When i go to endpoint/search-user returns 404 not found.
I´m some new in Symfony, so somebody can see what's wrong?
You can launch
php bin/console debug:router
to have a list of all your existing routing.
Can you add your controller declaration?
check that is in the src/Controller folder
check that there is no routing prefix in your controller (#route before class declaration)
i have a symfony application where a logout () is not manually :
( in file routing.yml)
logout:
pattern: /logout
and i would like when i click on /logout we must be able to record information in the database and for that i use :
SessionLogoutHandler class
here is my code :
namespace Symfony\Component\Security\Http\Logout;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Compta\MyappliBundle\Entity\LogTache;
use Compta\MyappliBundle\Entity\User;
use Doctrine\ORM\EntityManager;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class SessionLogoutHandler implements LogoutHandlerInterface
{
public function logout(Request $request, Response $response, TokenInterface $token)
{
$em = $this->getDoctrine()->getEntityManager();
$user= $this->get('security.context')->getToken()->getUser();
$u = new LogTache();
$u->setDate(new \DateTime());
$u->setUser($user->getUsername());
$u->setActioneffectue('Déconnexion');
$em->flush($u);
$request->getSession()->invalidate();
} }
when i click on /logout i get an error :
Fatal error: Call to undefined method
Symfony\Component\Security\Http\Logout\SessionLogoutHandler::getDoctrine()
in
C:\wamp\www\MyAppli\vendor\symfony\src\Symfony\Component\Security\Http\Logout\SessionLogoutHandler.php
on line 46
how to solve it ?
thank in advance
excuse my english
You don't have access to the container from that class. The $this->getDoctrine()... and $this->get() is more likely to be found in a controller action.
You can add a constructor and pass in '#doctrine' and '#security.context' as arguments from the service definition, or with Symfony 3.3 type-hint the appropriate classes (for Doctrine - Doctrine\Common\Persistence\ObjectManager) and use them within the class.
Symfony 2.6 deprecated the security.context service, so it's also quote likely you are running a older version of the framework. Upgrading may bring additional benefits, such as the v3.3+ auto-wiring of services.
Is there any configuration in Symfony2 that allow use of case Insensitive routing?
For example, routes below should be treated as they are the same:
www.exmaple.com/all
www.exmaple.com/ALL
There is a pull request about this, but no reference how to make it happen.
As of Symfony2.4, you can now define condition to your route and use the expression language to do complexe check. See Router: Completely Customized Route Matching with Conditions documentation.
Another solution would be to override the route compiler class to change/extend the php compilation of your route matcher:
contact:
path: /{media}
defaults: { _controller: AcmeDemoBundle:Main:contact, media: organic }
requirements:
media: email|organic|ad
options:
compiler_class: MyVendor\Component\Routing\CaseInsensitiveRouteCompiler
See Symfony\Component\Routing\RouteCompiler class.
Or, as fabpot said in the pull request comment, your could override Request::getPathInfo[1] method to always return a lowercase string (use the setFactory[2] to override default request class).
*1 github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/Request.php#L866
*2 github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/Request.php#L402
I found a nifty way to do this in pure symfony (no apache mod_rewrite) without having to create a case-insensitive forwarding rule for every route.
This utilizes the twig ExceptionController. Because this occures after the routing has failed to match (or a 404 exception has been thrown for some other reason) it won't break any existing routing urls that use capitals (though that would still be a bad idea).
namespace Application\Symfony\TwigBundle\Controller;
use Symfony\Component\HttpKernel\Exception\FlattenException;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Bundle\TwigBundle\Controller\ExceptionController as BaseExceptionController;
/**
* ExceptionController.
*/
class ExceptionController extends BaseExceptionController
{
/**
* Redirects 404s on urls with uppercase letters to the lowercase verion,
* then uses it's parent class to
* Convert an Exception to a Response.
*
* #param Request $request The request
* #param FlattenException $exception A FlattenException instance
* #param DebugLoggerInterface $logger A DebugLoggerInterface instance
*
* #return Response
*
* #throws \InvalidArgumentException When the exception template does not exist
*/
public function showAction(Request $request, FlattenException $exception, DebugLoggerInterface $logger = null)
{
if ( (string) $exception->getStatusCode() === '404' && preg_match('/[A-Z]/', $request->getPathInfo())) {
$lowercaseUrl = strtolower($request->getPathInfo());
if ($request->isMethod('POST')) {
return new RedirectResponse(
$lowercaseUrl,
'307'//307 status code preserves post information.
);
}
$queryString = $request->getQueryString();
return new RedirectResponse(
$lowercaseUrl.( strlen($queryString)>0 ? '?'.$queryString : '' ),
'301'//301 status code plays nice with search engines
);
}
return parent::showAction($request, $exception, $logger);
}
}
The only other trick is that you need to configure this controller as a service you can inject the correct arguments into the parent class's constructor:
in services.yml
services:
application.custom.exception_controller:
class: Application\Symfony\TwigBundle\Controller\ExceptionController
arguments: [ "#twig", "%kernel.debug%" ]
in config.yml:
twig:
exception_controller: application.custom.exception_controller:showAction
Of course, you can stick this controller and service definition anywhere
As far as I know, this isn't possible with Symfony 2. However, you should be able to accomplish it with Apache's mod_rewrite. See this blog post for details.
Make sure to read the comments, as there are some errors with the initial post.
I'm trying to update a record in my mysql database by calling the put method from my sencha touch 2 frontend. I'm calling this url /api/users/id but I keep getting a Symfony error:
No route found for "PUT /api/users/1
This is what I have in my routing.yml file
users:
resource: "Acme\MainBundle\Controller\UsersController"
prefix: /api
type: rest
Also, I have the putUsersAction setup in my User*s*Controller
public function putUsersAction($id, Request $request)
{
$values['birthdate'] = $request->get('birthdate');
$values['clubid'] = $request->get('clubid');
$em = $this->getDoctrine()->getEntityManager();
$user = $this->getDoctrine()
->getRepository('AcmeMainBundle:User')
->find($id);
$club = $this->getDoctrine()
->getRepository('AcmeMainBundle:Club')
->find($values['clubid']);
$user->setBirthdate($values['birthdate']);
$user->addClub($club);
$em->flush();
$view = View::create()
->setStatusCode(200)
->setData($user);
return $this->get('fos_rest.view_handler')->handle($view);
}
Why is Symfony telling me there's no PUT /api/users/id route?
EDIT 1: router:debug output
[router] Current routes
Name Method Pattern
_wdt ANY /_wdt/{token}
_profiler_search ANY /_profiler/search
_profiler_purge ANY /_profiler/purge
_profiler_info ANY /_profiler/info/{about}
_profiler_import ANY /_profiler/import
_profiler_export ANY /_profiler/export/{token}.txt
_profiler_phpinfo ANY /_profiler/phpinfo
_profiler_search_results ANY /_profiler/{token}/search/results
_profiler ANY /_profiler/{token}
_profiler_redirect ANY /_profiler/
_configurator_home ANY /_configurator/
_configurator_step ANY /_configurator/step/{index}
_configurator_final ANY /_configurator/final
get_users GET /api/users.{_format}
post_users POST /api/users.{_format}
get_clubs GET /api/clubs.{_format}
post_clubs POST /api/clubs.{_format}
put_users PUT /api/users.{_format}
At first you should debug your routing and see if the route is being registered correctly. Your posted routing snipped lacks correct intendation. It should read:
user:
resource: "Acme\MainBundle\Controller\UserController"
prefix: /api
type: rest
Afterwards you can debug your routing with the console command:
php app/console router:debug
Furthermore you can use grep ( Unix ) or findstr ( Windows ) to search the output for your route:
php app/console router:debug | grep /api
or
php app/console router:debug | findstr /api
Next make sure for the automatic routing of FOSRestBundle to work as expected to name your controller User*s*Controller and the file User*s*Controller.php.
See: FOSRestBundle Documentation
Please note that you have forgotten to call persist($user) before flushing and that you cannot call flush on your User entity but on your EntityManager. See my example below.
You can slim down your controller a lot by using DependencyInjection , the symfony2 ParamConverter, implicit resource name definition and the #View Annotation provided by the FOSRestBundle.
Your Controller would then read something like this:
<?php
namespace Acme\MainBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use JMS\DiExtraBundle\Annotation as DI;
use Acme\MainBundle\Entity\User;
use FOS\RestBundle\Controller\Annotations\View;
/**
* #DI\Service
*/
class UserController
{
/** #DI\Inject("doctrine.orm.entity_manager") */
private $em;
// ...
/**
* #View()
*/
public function putAction(User $user, Request $request)
{
$club = $this->em
->getRepository('AcmeMainBundle:Club')
->findOneById($request->get('clubid'));
$user
->setBirthdate($request->get('birthdate')
->addClub($club);
// you should add some validation here
$this->em->persist($user);
$this->em->flush();
return $user;
}
// ...
}
Explanations:
I have used the JMSDiExtraBundle's annotations. You need this bundle to make them work.
Otherwise you should declare your controller as a service and inject the EntityManager manually ( for example in your bundle's Resources/config/services.xml ) in the service container.
Declare your controller as Service with #DI\Service annotation.
Inject your EntityManager here to be be able to access it throughout the class with $this->em with the #DI\Inject annotation.
Use FOSRest's #View annotation.
Don't forget to set sensio_framework_extra.view: { annotations: false } before using this if you have the SensioFrameworkExtraBundle's in your application.
Make sure you have return $this; at the end of your User entity's setBirthdate(...) and addClub(...) functions.
Please not that i have used [JMSDiExtraBundle's property injection][3] in the example.
The bundle has to be installed in order to be used.
You might be able to slim down the controller further by using the NoxLogicMultiParamBundle.
I cannot post more than 2 links because im new over here...
please look for the following resources on google:
NoxLogicMultiParamBundle
FOSRestBundle documentation
JMSDiExtraBundle documentation
user:
pattern: /api/user/{id}
defaults: { _controller: AcmeMainBundle:User:putUsers, id: 1 }
or you could use the FQCN:
defaults: { _controller: Acme\MainBundle\Controller\UserController::putUsersAction, id: 1 }
and to match only PUT request use the below code, although some browsers don't support PUT and DELETE see this link
user:
pattern: /api/user/{id}
defaults: { _controller: Acme\MainBundle\Controller\UserController::putUsers, id: 1 }
requirements:
_method: PUT
...and of course to see all of your routes, run this from your project folder:
php app/console router:debug
I am trying to start on Symfony2 but ran into a problem right away following the Symfony 2 "the book" part "Creating pages in Symfony 2":
I did this:
Created the bundle
php app/console init:bundle "Acme\StudyBundle" src
*Added the namespace in app/autoload.php *
$loader->registerNamespaces(array(
'Acme' => __DIR__.'/../src',
));
Initialized the bundle
// app/AppKernel.php
public function registerBundles()
{
$bundles = array(
// ...
new Acme\StudyBundle\AcmeStudyBundle(),
);
// ...
return $bundles;
}
Created the routes in app/config.routing.yml and src/Acme/StudyBundle/Resources/config/routing.yml
# app/config/routing.yml
homepage:
pattern: /
defaults: { _controller: FrameworkBundle:Default:index }
hello:
resource: "#AcmeStudyBundle/Resources/config/routing.yml"
# src/Acme/StudyBundle/Resources/config/routing.yml
hello:
pattern: /hello/{name}
defaults: { _controller: AcmeStudyBundle:Hello:index }
Created the controller
// src/Acme/StudyBundle/Controller/HelloController.php
namespace Acme\StudyBundle\Controller;
use Symfony\Component\HttpFoundation\Response;
class HelloController
{
public function indexAction($name)
{
return new Response('<html><body>Hello '.$name.'!</body></html>');
}
}
When I load the page: http://localhost/app_dev.php/hello/Ryan Symfony gives me an exception:
Unable to find controller "AcmeStudyBundle:Hello" - class "Acme\StudyBundle\Controller\HelloController" does not exist.
I got over the code several times but cannot find anything wrong.
just add
<?php
in the beginning of your controller file : src/Acme/StudyBundle/Controller/HelloController.php
it's solved the problem to me.
Afaik there is a discussion going on within the Symfony 2.0 dev guys in what places they should keep the "Bundles" extension.
I've just grabbed the latest version of Symfony via Git and followed your code 1:1.
I got various error messages too but when I changed...
in src/Acme/StudyBundle/Resources/config/routing.yml
defaults: { _controller: AcmeStudyBundle:Hello:index }
to
defaults: { _controller: AcmeStudy:Hello:index }
app/config/routing.xml
resource: "#AcmeStudyBundle/Resources/config/routing.yml"
to
resource: "#AcmeStudy/Resources/config/routing.yml"
...i got a pretty "Hello Ryan" in the browser.
Hope this helps!
You are probably running PR9. Update to PR11(latest), and I would bet this gets resolved. Symfony devs removed the 'Bundle' suffix in PR9, but added it back again shortly there after.
Also, Symfony devs keep an Update log that I find extremely helpful.