Handle AJAX requests in separated directory/files - php

I want to move my all methods from controller, which are executed by AJAX request, to separate folder. For example create file UserBundle/Ajax/Ajax.php and put in this file, my all AJAX request methods.
Is it the right approach, to separate ajax requests, from normal http requests? I can't find any examples how to do it. It is possible in Symfony? I must extend Symfony\Bundle\FrameworkBundle\Controller\Controller in this Ajax.php file? That will be okay, that will be exist two folders in bundle Ajax and Controller, contains controllers but first for ajax request and second for normal http request?
Do You know any architectural pattern, for this problem?

I don't think there is any problem to do that, only make sure to define the routing path correctly:
An example for annotation routing:
# app/config/routing.yml
app_bundle:
resource: "#AppBundle/Controller"
type: annotation
prefix: /
app_bundle_ajax:
resource: "#AppBundle/Ajax"
type: annotation
prefix: /
I must extend Symfony\Bundle\FrameworkBundle\Controller\Controller in this Ajax.php file?
It's not mandatory, but the Symfony\Bundle\FrameworkBundle\Controller\Controller provide you excellent shortcuts like $this->json(...); since Symfony 3.1

You can create simple AjaxController as a service which will receive the ajax requests. Then you can redirect each of the requests to different Controllers and they will return JsonResponces().

Related

Symfony2 Include Custom Configuration Variables

I'm using Symfony2 to access an API. I have a controller that initializes the Oauth and another that is for the Callback. Instead of manually typing out the api key, and other variables into these controllers, I want to have a single "configuration" file that I can include in all relevant locations (ie, the Oauth controller and OauthCallback controller).
How do I go about doing this? Should I add more lines to the config.yml or should I just create a new file called config.php and include it? With normal ol' php it'd be an easy require_once but since this is a framework, I want to make sure I'm doing it the "right" way.
Thanks!
Use parameters in parameters.yml or config.yml file.
parameters:
my_api_key: 1234
In controller get like that:
$apiKey = $this->container->getParameter('my_api_key');
IMO, you should write it in the config.yml. Remember that you can write other parameters and include it in the main config.yml with
imports:
- { resource: mi-file.extension}
In the controller, you can get this parameters with
$var= $this->container->getParameter('name_parameter');

Need Assistance with Symfony 2.7 creating first page

I am trying to learn the Symfony framework and struggling with it. The instructions are not very helpful or assume I know a lot more than I know. I am just trying to create a single web page with proper route and controller. I have been googling to find answers and made some progress but no luck yet. Right now I just have the standard install of Symfony with just default bundles etc. I created a project called "gtest3" and chose PHP for it...
I am not sure where I put the new route in (what file) or maybe it needs to be put in more than one file?
I found the "routing.yml" file which seems that is where I need to put it...
here is what is in there right now:
gtest3:
resource: "#gtest3Bundle/Resources/config/routing.php"
prefix: /
app:
resource: "#AppBundle/Controller/"
type: annotation
I am guessing I need to add something to this and put the location/filename of the controller? I have tried doing this a few ways and just get errors.
There is also the "routing.php" file that is referenced in the above code. I am not sure if this is the "controller" or if it is an additional piece of the "route". Here is the code from that file:
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
$collection = new RouteCollection();
$collection->add('gtest3_homepage', new Route('/hello/{name}', array(
'_controller' => 'gtest3Bundle:Default:index',
)));
return $collection;
I am not sure what if anything I would add here.
Finally - there is the "DefaultConroller.php" file I found as well which may also be the controller. I dont think I need to include the code of that file here.
So - all I am trying to do is create a route of maybe "/gman" and then have the controller just echo something on the page. Super basic stuff. And I cannot figure out how to get this going.
Can anyone help with this? Thanks so much...
You can define your routes in three ways, either by using yml files, xml files, or by using a php file. This is documented behaviour.
You are from the looks of your routing.yml trying to set up a php version. I would not recommend it, and instead use configuration over coding the routing.
The annotation example would look like:
Adding a controller:
namespace Gtest3Bundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class Gtest3Bundle extends Controller
{
/**
* #Route("/hello/{name}")
* #Template()
*/
public function indexAction($name)
{
return array('name' => $name);
}
}
And add in your app/config/routing.yml:
gtest3:
resource: "#Gtest3Rights/Controller/"
type: annotation
prefix: /what-ever-you-want
You can check what kind of routes you have defined by using:
./app/console router:debug
If it doesn't appear hear, you have something misconfigured.
Please be advised that your bundle names breaks the convention of how bundles should be named in the symfony2 context.
It is advised to use NamespaceProjectBundle. This also documented. If you are stuck, try generating a bundle via the ./app/console generate:bundle. This way you can create a whole symfony2 structure which should show the default page hello/foo page just fine.
If it doesn't seem to run at all, make sure you have registered your bundle at the in the app/AppKernel.php file in the registerBundles() method.
To configure routes you can use yml, php or xml file. You can specify it in app/config/config.yml
framework:
router:
resource: "%kernel.root_dir%/config/routing.yml"
It's where you can check which file is used now.
There are some manners to store the routes.
app:
resource: "#AppBundle/Controller/"
type: annotation
This is how you use routes by writing annotations above your actions (eg indexAction) inside your controller class. Read more.
Another common approach is to build one or more .yml files inside each Bundle.
in app/config/routing.yml you should write this:
app:
resource: "#AppBundle/Resources/config/routing.yml"
prefix: /
Then you need to create the file (and directories if necessary) src/AppBundle/Resources/config/routing.yml and add the following content:
app_homepage:
path: /
defaults: { _controller: AppBundle:Default:index }
It will then try to find the DefaultController and fires the indexAction in the AppBundle (src/AppBundle/Controller/DefaultController.php).
To debug your routes simply type in your console from your projects directory:
app/console router:debug

Defining default routing for controller/action in symfony 2

If I wanted to make it so that every url call apart from ones I have defined after act upon /ExplicitControllerName/ExplicitActionToRun... how might the routing look like.
for example some pseudo code:
default_pathing:
pattern: /{controller}/{action}
defaults: { _controller: Bundle:Default:index }
So if I went to
www.example.com/Page/About
it would call my controller
class Page extends Controller
{
public AboutAction()
{
// Called by above URL
}
}
This question does not answer: Symfony2 / routing / use parameters as Controller or Action name
Imagine I have 100 pages with lots of sub routing pages doing pretty much the same routing every time. I want to do 1 routing for all those 100 controllers. How would we do this?
P.S I'm really going for something like the C#.NET MVC 4.0 routing in which it allows you to set a routing for a typical setup you might have even if at the very least its for development
Your question is not totally clear but here are some hints.
I can imagine two use cases you're trying to solve:
1) You've a lot of some sort of CMS page, like your about example, these pages don't have much logic and just render some view, in such case you would something like:
class CMSPageController
{
public function renderPage($pageSlug)
{
$page = $this->cmsPageRepository->findBySlug($pageSlug);
// your logic to render the view
}
}
And the according routing configuration:
<route id="cms_page_view" pattern="/cms/{pageSlug}">
<default key="_controller">cms_page.controller.page:renderPage</default>
<requirement key="_method">GET</requirement>
<requirement key="slug">[0-9a-zA-Z\-\.\/]+</requirement>
</route>
2) You have much more complex requirements, and/or follow a specific pattern to name your controller/action, therefore you need to write a custom UrlMatcherInterface implementation. Take a look at the native implementation to know where to start. It would allow you define a fallback.
This can be achieved using either SensioFrameworkExtraBundle's #Route annotation on class- and method-level excessively...
... or more elegant with less annotations using FOSRestBundle's automatic route generation with implicit resource names. Maybe you'll need to correct some of the generated routes using some of FOSRestBundle's manual route definition annotations.
Both methods originally still leave the need to explicitly add the route resources to your app/config/routing.yml.
Example import for #Route
# import routes from a controller directory
blog:
resource: "#SensioBlogBundle/Controller"
type: annotation
Example import for FOSRestBundle
users:
type: rest
resource: Acme\HelloBundle\Controller\UsersController
You could work around having to import all the resources by:
introducing a custom annotation (class-level)
creating a compiler pass or a custom route loader in which you ...
use the Finder to find all controller classes in all bundles with that annotation
finally add all those as resources with type annotation/rest to the route collection in there
If you don't plan to use hundreds of controllers and don't have too much experience with compiler-passes, custom annotations, ... etc. you'll definitely be faster just registering the resources in the routing config.

Symfony2 routing: How to request that the route will be taken from only one template

I heve an embedded controller in my base template. It's a search bar.
For the search bar controller, I have a route "myProject/search".
What I would like is that this route will be taken only when the template where I am embedding the controller (base.html.twig) will call it, and not when i manually put in the browser: "myproject/search".
Any idea on how to do that.
I think, since some time you can't do it:
http://symfony.com/doc/current/book/templating.html#embedding-controllers
quote from the docs:
Even though this controller will only be used internally, you'll need
to create a route that points to the controller
(...)
Since Symfony 2.0.20/2.1.5, the Twig render tag now takes an absolute
url instead of a controller logical path. This fixes an important
security issue (CVE-2012-6431) reported on the official blog. If your
application uses an older version of Symfony or still uses the
previous render tag syntax, you should upgrade as soon as possible.
Anyway, I guess, you can try do it yourself by passing some "secret" argument to search action when you call it from your template. Next in the action you check if the argument was passed to it, and if not you throw 404.
Another way to achieve your goal is use .htaccess file.
You can restrict your route to a certain method by _method option in your routing configuration:
your_rote:
pattern: /myProject/search
defaults: { _controller: YourBundle:YourController:YourAction }
requirements:
_method: POST

Routing in Symfony2

How to setup default routing in Symfony2?
In Symfony1 it looked something like this:
homepage:
url: /
param: { module: default, action: index }
default_symfony:
url: /symfony/:action/...
param: { module: default }
default_index:
url: /:module
param: { action: index }
default:
url: /:module/:action/...
I was looking through the cookbook for an answer to this, and think I've found it here. By default, all route parameters have a hidden requirement that they match any character except the / character ([^/]+), but this behaviour can be overridden with the requirements keyword, by forcing it to match any character.
The following should create a default route that catches all others - and as such, should come last in your routing config, as any following routes will never match. To ensure it matches "/" as well, a default value for the url parameter is included.
default_route:
pattern: /{url}
defaults: { _controller: AcmeBundle:Default:index, url: "index" }
requirements:
url: ".+"
I don't think it's possible with the standard routing component.
Take a look to this bundle, it might help :
https://github.com/hidenorigoto/DefaultRouteBundle
// Symfony2 PR10
in routing.yml:
default:
pattern: /{_controller}
It enables you to use this kind of urls: http://localhost/MySuperBundle:MyController:myview
Symfony2 standard routing component does not support it, but this bundle fills the gap Symfony1 left:
https://github.com/LeaseWeb/LswDefaultRoutingBundle
It does what you expect. You can default route a bundle using this syntax:
FosUserBundle:
resource: "#FosUserBundle"
prefix: /
type: default
It scans your bundle and automatically adds routes to your router table that you can debug by executing:
app/console router:debug
Example of automatically added default routes:
[router] Current routes
Name Method Pattern
fos_user.user.login_check ANY /user/login_check.{_format}
fos_user.user.logout ANY /user/logout.{_format}
fos_user.user.login ANY /user/login.{_format}
...
You see that it also supports the automatic "format" selection by using a file extension (html, json or xml).
Here is an example: http://docs.symfony-reloaded.org/master/quick_tour/the_big_picture.html#routing
A route definition has only one mandatory parameter pattern and three optionals parameters defaults, requirements and options.
Here's a route from my own project:
video:
pattern: /watch/{id}/{slug}
defaults: { _controller: SiteBundle:Video:watch }
requirements: { id: "\d+", slug: "[\w-]+"
Alternatively, you can use #Route annotation directly in a controller file. see https://github.com/sensio/SensioFrameworkExtraBundle/blob/master/Resources/doc/annotations/routing.rst
As for the default routes, I think Symfony2 encourages explicit route mapping.
Create a default route is not a good way of programming. Why? Because for this reason was implemented Exception.
Symfony2 is built just to do right things in the right way.
If you want to redirect all "not found" routes you should use exception, like NotFound404 or something similar. You can even customise this page at your own.
One route is for one purpose. Always. Other think is bad.
You could create your own bundle that handled all requests and used URL parameters to construct a string to pass to the controller's forward method. But that's pretty crappy, I'd go with well defined routes, it keeps your URLs cleaner, and decouples the URL and controller names. If you rename a bundle or something, do you then have to refactor your URLs?
If you want to create a "catch all", your best bet would be to hook on the KernelEvents::EXCEPTION event. This event gets triggered whenever an Exception falls through to the HttpKernel, this includes the NotFoundHttpException thrown when the router cannot resolve a route to a Controller.
The effect would be similar to Symfony's stylized 404 page that gets rendered when you send the request through app_dev.php. Instead of returning a 404, you perform whatever logic you're looking to.
It depends... Some of mine look like this:
api_email:
resource: "#MApiBundle/Resources/config/routing_email.yml"
prefix: /
and some look like
api_images:
path: /images/{listingId}/{width}/{fileName}
defaults: { _controller: ApiBundle:Image:view, listingId: null, width: null, fileName: null }
methods: [GET]
requirements:
fileName: .+

Categories