I wanted to get views from the symfony community about how one would achieve using backbone.js to create a one paged application.
Is it even possible to call the functions in symfony (e.g public function executeCreate()) through backbone.js) has anyone done it?
Can you give me some resources? thanks in advance.
Why not? Symfony easily can return JSON data on request by backbone clientside app. For Symfony2 it can be like this:
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class MyController extends Controller {
public function createAction($requestParam1, $requestParam2)
$response = new Response(json_encode(array(
'requestParam1' => $requestParam1,
'requestParam2' => $requestParam2
)));
$response->headers->set('Content-Type', 'application/json');
return $response;
}
}
I would recommend you to have a look at the FOSRestBundle. Another attempt could be to handle the requests yourself, and return the date from the orm/odm via Serializer
the only thing bothered me so far, was the form handling (used backbone-forms), where I simply not was able to keep my code DRY (had duplicate data for the form+validation in symfony and in the frontend-part).
If you want to start a new Symfony2 + backbone app, I would recommend this bundle:
https://github.com/gigo6000/DevtimeBackboneBundle
There's also a demo app that can be helpful to see the backbone.js and Symfony2 interaction:
https://github.com/gigo6000/DevtimeRafflerBundle
Related
I want to be able to retrieve the token from the http_request_body as for annoying reasons where I need to send the data from, the token is too long to send as part of the query string, and they don't accept sending headers.
Anyway, I've managed to edit the jwt.auth GetUserFromToken middleware to the following:
if (! $token = $this->auth->setRequest($request)->getToken()) {
if(! $token = $request->get('token') ) {
return $this->respond('tymon.jwt.absent', 'token_not_provided', 400);
}
}
This works, but I am wondering if there is a better way that would be more permanent?
Obviously when I deploy or the package is updated this will be over-ridden.
Is there a way to extend to extend or over-ride this class from within my app, rather than directly in the vendor Middleware?
Thanks!
With the help of #Moeen Basra #apokryfos and this How to override vendor class file?
Managed to extend the Middleware so that it overrides the existing Class and won't be impacted when the app is deployed or the package updated.
Added MyGetUserFromToken.php
namespace App\Overrides\Tymon;
use Tymon\JWTAuth\Middleware\GetUserFromToken;
class MyGetUserFromToken extends GetUserFromToken {
And then in the Kernel
//use Tymon\JWTAuth\Middleware\GetUserFromToken;
use App\Overrides\Tymon\MyGetUserFromToken;
...
'jwt.auth' => MyGetUserFromToken::class,
Hopefully this will then help others also.
This is my long quest to develop web apps using core PHP and follow the best possible practices and not using a framework. I have achieved many things by structuring my project a better way. However ...getting a clean URL is often a problem for large apps.
Till now...I have used the Slim Framework only for creating RESTFUL services outside my web apps.
I am using Slim Framework to create APIs for a PHP project. Now, I have an install of Slim up and running fine. I have my routes talking to the database and doing what they're supposed to do, generally. My question has to do with modularizing the code. At the moment, all my routes are defined in my index.php file in the root directory. I would very much like to separate these out, say into a /controllers folder.
As I liked the way Slim makes pretty good URLs...I am wondering if it is possible to use Slim as my app architecture ...and let all my pages or APIs be accessible through the Slim index.php.
Yes pretty easily here are the steps I have taken on a recent project.
First lets say your have a HomeActionController
class HomeActionController {
//The below line I have moved into an abstract Controller class
public $view = null;
//This is using Slim Views PhpRenderer
//This allows for a controller to render views can be whatever you need
//I did not like the idea of passing the whole DC it seemed overkill
//The below method I have moved into an abstract Controller class
public function __construct(\Slim\Views\PhpRenderer $view = null){
if($view != null){
$this->view = $view;
}
}
//View could be any action method you want to call it.
public function view(Request $request, Response $response, array $args){
$data['user'] = "John Doe";
return $this->view->render($response, 'templates/home.php', $data);
}
}
Now you need to be able to call an instance of this controller from a route so you need to add the controllers you have to the DC
Where ever you are creating your instance of slim you will need to get the DC and add an instance of your controller:
$app = new \Slim\App($config['slim']);
// Get Dependency Container for Slim
$container = $app->getContainer();
$container['HomeActionController'] = new Controller\HomeActionController($container['view']); //Notice passing the view
As a note the above instantiations could have been a closures but I did not see the point at the time or making them. Also, there are ways to lazy load that I have not explored yet see here for more information.
Now the last thing you need to do is be able to call these on the routes which is not a huge challenge.
$app->get('/home', 'HomeActionController:view');
Granted you cannot have an action with parameters but I have not had an issue just passing them along in the request and then getting them from there.
If you want to create a app with no framework, then i would recommend looking through this small github repo:
https://github.com/PatrickLouys/no-framework-tutorial
It goes through with you settings everything up in terms of routing, plus would make everything go through the index.php in a public folder like your asking.
is theoretically possible use more services for routing?
For example if somebody use Silex and has this code:
$app = new Silex\Application();
$app->get('/test/{id}', function ($id) {
// ...
});
$app->run();
And i create api using Slim like that:
$app = new \Slim\Slim();
$app->get('/api/' . $version . 'something', function () use ($app){
$data = $app->request->params();
});
$app->run();
How user could implement my API withou rewrite Slim route function to Silex route function?
Thank you very much.
Giving a quick though, the way I see it you have 3 options:
Refactor controller closures to a named function
Both, Silex and Slim[1] can use any form of callable, so instead of passing a closure just pass a function name (or an array with class name, method name) or any other callable. This way with 1 declaration you'll be able to call it from both Slim and Silex (yes, you have to define the routes on both sides).
This has its drawbacks as the controller signature is different for the 2 frameworks, so you'll need to hook into silex flow and change the parameters (you have the Kernel.controller event to do that).
Also you'll need to redefine all your services and use the container wisely (i.e, don't use it as a service locator in your controllers).
This is probably the most inflexible way.
Define the routes in Silex and instatiate a Slim APP inside to call and return that
You'll need to define the api routes again in Silex and in each route you can try to instatiate the Slim APP (using something as require "path/to/the/slim/app/php/file.php") and then force the run method with the silent option on[2]
You'll probably need to refactor your Slim application a bit, you'll have to define your app in a file and call the run method in another.
Create a Silex middleware to handle all the /api/ calls
The easiest (?) way that I can think of is redefine the second option and create a catch all incoming request to the /api/ mount point by creating a Silex middleware that checks for each incoming request if the request has the /api/ string inside the request. Then you'll simply forawrd the request to the Slim application as I've told you in the second option.
Using this method you don't need to redefine the routes in Silex as everything under the /api/ point will be forwarded to the Slim application.
NOTE
In all cases you'll probably need to transform the response given from Slim to a Symfony response. Slim 3 uses the new PSR-7 HTTP interface so you have a solution here already. Slim 2 echos the response directly so you'll need to catch that and put it inside a Symfony response (new Response(ob_get_clean())
[1] This is for the Slim3, Slim2 may also be able to do that but I'm not sure (and the signature is different!)
[2] Again this is for Slim3, Slim2 does not has this option, so you'll need to figure something to get the response (maybe ob_get_clean()?)
i want to use fullcalendar.io with my Symfony2 project.
The Fullcalendar sends such requests for getting Event data:
/myfeed.php?start=2013-12-01&end=2014-01-12&_=1386054751381
Symfony2 usally routes with Slashes in the URl, it only exists this route:
/myfeed/start=2013-12-01/end=2014-01-12/_=1386054751381
How can I use the Feature of Fullcalendar for Symfony2?
Here my Test-Controller:
<?php
namespace Chris\KfzBuchungBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
class AjaxGetWeekController extends Controller
{
public function indexAction(Request $request, $start)
{
$response = new Response(json_encode(array("title" => 'blub',"start" =>$start)));
$response->headers->set('Content-Type', 'application/json');
return $response;
}
}
Thank you!
Even though Symfony routes are typically set up differently, you can still very easily retrieve the query string parameters. See the following:
http://symfony.com/doc/current/quick_tour/the_controller.html#getting-information-from-the-request
So in your controller all you have to do is:
$start = $request->query->get('start');
$end = $request->query->get('start');
$timestamp = $request->query->get('_');
I encourage you to read the Symfony documentation as it is very thorough with many examples. Also this question has been answered already on StackOverflow with many more examples here: How to get the request parameters in symfony2
I have a simple silex application and using a lot of different externals controllers.
I am using register and mount to connect it to my application.
$app->register($externalController = new ExternalController());
$app->mount('/control', $externalController );
It adds the routes login, logout, etc in its service provider class:
$controllers->get('/start', 'user.controller:loginAction')
->bind('control.start');
I want to add an event or middleware listener to actions provided by it.
I have searched the silex and symfony documentation, but I didn't find an easy way.
I have tried to use $app['controllers'], but this returns a ControllerCollection without any possibility to change something (or I didn't understand it).
What is the recommended way to add a new listener to an existing non self written controller?
I have found one possible way in the meantime to flush the controllers to create the RouteCollection and retrieve it via binding name.
You will receive a Route instance and can use there the normal middleware listener methods like before, after and so on.
$app->flush();
$route = $app['routes']->get('control.start');
$route->before(function(Symfony\Component\HttpFoundation\Request $request) use ($app) {
throw new RuntimeException('You should see me.');
});