Laravel provides with register controller and Auth::routes() defines the use of this controller. I went to auth() function in Router.php and found that upon registration route calls register function in register controller,
$this->post('register', 'Auth\RegisterController#register');
but I cannot find this register function in RegisterController file. What is happening here ? Am I missing something? I am new to laravel.
The RegisterController uses a trait named Illuminate\Foundation\Auth\RegistersUsers in which you will find your register() method.
Check out in the Laravel's source code here.
Read more about trait here.
Related
In my Symfony 2.8 based project I use FOSUserBundle and extended it with a custom MyUserBundle using bundle inheritance.
When trying to update FOSUserBundle from 2.0.2 to 2.1.2 I came across several problems.
Since Bundle inheritance is deprecated in Symfony 3.4 and completely dropped in Symfony 4.0 I am now trying to achieve the same result without using bundle inheritance.
I found many information that shows, that bundle resources can be overridden by simply placing the files in the app/Resources/<BundleName>/.... Thus the FOSUserBundle templates could be overridden by placing them in app/Resources/FOSUserBundle/views/<template.html.twig>
While this will work, it does not deliver the same result as bundle inheritance. I can use my inherited bundle in different projects and thus reuse the same code over and over again. Using the app/Resources/<BundleName>/... solution would only work for the current project.
Question 1: How to override templates (and other resources) within a custom bundle which can be used in different projects rather than within a project specific app/Resources folder?
Question 2: How to override the behavior of controllers which to not offer event to to do so?
Currently I am using bundle inheritance to override the confirmedAction to send the user to a custom setup page rather than to the default page:
// Original FOSUserBundle code
public function confirmedAction(Request $request) {
$user = $this->getUser();
if (!is_object($user) || !$user instanceof UserInterface) {
throw new AccessDeniedException('This user does not have access to this section.');
}
return $this->render('#FOSUser/Registration/confirmed.html.twig', array(
'user' => $user,
'targetUrl' => $this->getTargetUrlFromSession($request->getSession()),
));
}
// MyUserBundle codes which should override the default behavior
public function confirmedAction(Request $request) {
$user = $this->getUser();
if (!is_object($user) || !$user instanceof UserInterface) {
throw new AccessDeniedException('This user does not have access to this section.');
}
// Send user to setup-page
return $this->redirectToRoute('app_user_setup');
}
How can I control the behavior in the same way and send the user to a setup page instead of to the default confirmation page without using bundle inheritance?
As far as I know FOSUserBundle does not provide an option to specify the confirmation target. Of course I could intercept the request to the confirmed-route using some request event listener and re-route it. But this would be quite hacky. Would this be the right solution to do this or is there a cleaner way to achieve the same?
Overriding resources within a bundle since Symfony 4.0 without bundle inheritance
About Controllers
Routes! is the way to achieve it now, "the first route found wins" so make sure to define the same route before the original one, with your custom controller. e.g.:
<route id="fos_user_registration_confirmed" path="/confirmed" methods="GET">
<default key="_controller">MyUserBundle\Controller\RegistrationController::confirmedAction</default>
</route>
Then, your routing file MyUserBundle/Resources/config/routing/registration.xml must be imported before the FOSUserBundle routing file. This way, your custom action will be executed instead of the original fos_user.registration.controller:confirmedAction.
About Templates
Again, "the first template found wins" so make sure your bundle views path is defined before the one in FOSUser Twig namespace. You can achieve it by creating a compiler pass:
// MyUserBundle/DependencyInjection/Compiler/TwigPass.php
$path = dirname(__DIR__, 2).'/Resources/views';
$twigFilesystemLoaderDefinition = $container->findDefinition('twig.loader.native_filesystem');
$twigFilesystemLoaderDefinition->addMethodCall('prependPath', array($path, 'FOSUser'));
Check the Twig loader paths by running bin/console debug:twig, it should look like this:
#FOSUser - vendor/acme/my-user-bundle/Resources/views
- vendor/friendsofsymfony/user-bundle/Resources/views
From here, you're able to override any template of FOSUserBundle like Registration/confirmed.html.twig when #FOSUser/Registration/confirmed.html.twig is called.
I'm using the Symfony CMF Routing Bundle to create dynamic routes (I'm using one example here):
$route = new Route('/dynamic-url');
$route->setMethods("GET");
$route->setDefault('_controller', 'AppBundle:MyRoute:getResponse');
$routeCollection->add('my-dynamic-route', $route);
The response is loaded from the getResponseAction() function inside the MyRouteController:
/**
* No annotations here, because I want the url to be dynamic from the database
*/
public function getResponseAction(Request $request) {
return $this->render('dynamic-page-template.html.twig');
}
When I go to '/dynamic-url', it works.
When in another controller, I want to redirect to this dynamic route, like this:
return $this->redirectToRoute('my-dynamic-route');
But I get this error: "None of the chained routers were able to generate route: Route 'my-dynamic-route' not found"
Also interesting: when I go to '/dynamic-url', the dev bar actually says that the Route name is 'my-dynamic-route'.
Edit
When I load all the routes, I don't see my dynamic route names:
$this->get('router')->getRouteCollection();
I think they should be in this list.
Since it's a dynamic route, which wasn't saved anywhere (like routing.yml ) it will be only availabe for Request where it has been defined. So at the end of Request your app will immediately "forget" about new Route generated at runtime.
When I load all the routes, I don't see my dynamic route names:
$this->get('router')->getRouteCollection();
I think they should be in this list.
Actualy No. It depends on where you call $this->get('router')->getRouteCollection();
Just try to call
dump($this->get('router')->getRouteCollection();)
right before the return statement in your Action where you're adding the my-dynamic-route route. I'm sure you'll see your my-dynamic-route in the list of routes, but if you call it anywhere else - you won't see it.
It's less about symfony rather about stateless nature of web (see Why say that HTTP is a stateless protocol?)
I started to think about this and pointed your question to an routing issue on symfony-cmf. You tagged with #symfony-cmf and i think this would be important feature for us.
I also think, when you persist your route with /my-route you should also ask the router for that name (or in case of the CMF with an content object with that a route.)
If you use the CmfRoutingBundle dynamic router, you should persist your routes to doctrine. The idea of dynamic here is that they can be created at runtime, e.g. in an admin interface or elsewhere by code. The DynamicRouter loads routes from the database.
If you use PHPCR-ODM, the route name is the repository id, typically something like /cms/routes/my-route and you can generate it with that name. If you have access to the route object loaded from the database, you can also generate from that, rather than the path. If you have to hardcode a path in your application, its an indication that probably a normally configured route would be better.
If you just add a route to the route collection on the fly, you would have to make sure that happens in each request, its only available when you add it. With the CMF ChainRouter you could register your own router that does that, but i would not know of a good use case for that. Either you know the route, then you can configure it in the routing.xml|yml|php config file. Or routes are loaded dynamically, in which point you should use DynamicRouter, potentially with a custom route loader.
I am looking through properties of $kernel, $loader, $request and $response but cannot find anything related to controller and action that were actually called as a result of accessing specific URL. Is there a way to find out this info inside app.php, without manual analysis of route configuration files?
I'm working on creating an authentication provider for Symfony 2 that allows users to authenticate with the single sign on protocol called CAS.
My Authentication Listener extends from AbstractAuthenticationListener. One of the config params is check_path, which is the path/route that triggers the authentication listener to authenticate the request.
I need check_path when I construct the URL to the CAS server (so CAS server knows where to return the user to), which is easy, since my custom Entry Point class is passed the configuration array when it's constructed in my security Factory.
The hard part is that I also need check_path outside of the listener, like during authentication inside my Authentication Provider class. I need it because when CAS server sends the user back to the app, it passes a "ticket" parameter that must be validated. To validate it, I send a curl request to CAS server that must contain the ticket as well as the original check_path that was used.
As a wrote this, I realized that I could get the current URL of the page request when I'm inside the Authentication Provider (since it's check_path that triggers it anyway), but that seems off, and I'd rather get the config value directly to re-construct the service URL. It also doesn't help me when I want to use check_path elsewhere, like when constructing a logout URL to the CAS server which also required the check_path.
EDIT: The createAuthProvider method of AbstractFactory is passed both the config and the container, but I cannot modify any of my services in here because they are not yet part of the container. Perhaps if I had a way to add a compiler pass after my services are loaded and somehow having access to the listener config?
Can you pass check_path as parameter to your listener?
If it defined in your config or parameters file you can pass it to your listener like this:
your_authentication_listener:
class: YourBundle\Listener\AuthenticationListener
arguments: ['%check_path%']
tags:
...
(If I understood you correct.)
You can make %check_path%(or a namespaced version of it) a 'normal' parameter:
Inside of DependencyInjection, there are (by default) two classes responsible for defining and loading your bundle's configuration. In there you can also inject your configuration into your service container.
DependencyInjection\Configuration is where you define which configurations are available in your bundle, what type they should be etc.
DependencyInjection\YourBundleNameExtension is where you can load your configuration and also add them to the service container.
If you have not done anything in there yet, your Extension's load()-method should look something like this:
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$loader = new Loader\YamlFileLoader(
$container,
new FileLocator(__DIR__.'/../Resources/config')
);
$loader->load('services.yml');
}
$config holds your bundle's configuration in the form of an array, so if we imagine your YAML config file looks like this:
your_bundle_name:
check_path: foo
Your $config will look like that:
array( 'check_path' => 'foo' )
So now, all you have to do is add this configuration to the container. Inside your load()-method simply add something like:
$container->setParameter(
'my_bundle_name.check_path',
$config['check_path']
);
Inside your services.yml you can now use %my_bundle_name.check_path% like every other parameter:
my_bundle_name.security.authentication.provider:
class: MyBundleName\Security\Core\Authentication\Provider\MyAuthenticationProvider
arguments: ['%my_bundle_name.check_path%']
For more details, have a look at Symfony's documentation [1,
2]
I'm building a CMS style application with dynamic routing. So far it seems to work fine but the output doesn't honor the environment for WDT, assets and links... it always links to /whatever instead of /app_dev.php/whatever.
Dynamic routing is implemented via kernel.request listener. The relevant code is on gist. Do I need to pass the current environment to Twig at some moment?
Edit:
The problem appears when in DEV mode... no problem when in production mode.
Thanks to #AdrienBrault I finally solved the issue by using a Controller to do the rendering.
In the RequestListener I added a new route to the RouteCollection of the router indicating the controller which will handle the request.
$route = new Route($path, array(
'_controller' => 'CmsBundle:Routing:routing',
));
$this->router->getRouteCollection()->add('cms', $route);
In the controller it was a bit harder to get the original URL, but finally I solved it by querying the routers RouteCollection with the name assigned in the previous add() method.