I'm in the process of creating a REST API with Symfony and the FOSRestBundle and am pretty much new to the both.
Now I wonder how to generate an URL to a resource I just created. Routes are setup like this:
# app/config/routing.yml
characters:
type: rest
prefix: /api
resource: "#Optc/Resources/config/routing/characters_routing.yml"
NelmioApiDocBundle:
prefix: /api/doc
resource: "#NelmioApiDocBundle/Resources/config/routing.yml"
# Resources/Optc/Resources/config/routing/characters_routing.yml
characters:
type: rest
resource: Optc\Controller\CharactersController
The part of the Characters controller that creates the resource:
$character = new Character();
$form = $this->createForm(new CharacterType(), $character);
$form->bind($data);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($character);
$em->flush();
$response->headers->set('Location', $this->generateUrl('get_characters', array('id' => $user->getId()), true));
$view = $this->view($character, 200);
return $this->handleView($view);
}
Update: Full controller code:
<?php
namespace Optc\Controller;
use FOS\RestBundle\Controller\Annotations\QueryParam;
use FOS\RestBundle\Controller\FOSRestController;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use Optc\Entity\Character;
use Optc\Form\CharacterType;
use Optc\HttpFoundation\File\Base64File;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\HttpException;
/**
* Characters Controller
*/
class CharactersController extends FOSRestController
{
/**
* Get the list of characters.
*
* #param string $page integer with the page number (requires param_fetcher_listener: force)
*
* #return array data
*
* #QueryParam(name="page", requirements="\d+", default="1", description="Page number of the overview.")
* #ApiDoc()
*/
public function getCharactersAction($page)
{
$characters = $this
->getDoctrine()
->getRepository('Optc:Character')
->findAll();
$view = $this->view($characters, 200);
return $this->handleView($view);
}
public function getCharacterAction($id)
{
$character = $this
->getDoctrine()
->getRepository('Optc:Character')
->findOneById($id);
if (!$character) {
throw new HttpException(404, sprintf('Character with id %d not found!', $id));
}
$view = $this->view($character, 200);
return $this->handleView($view);
}
/**
* Create a new character.
*
* #param Request $request
*
* #return View view instance
*
* #ApiDoc()
*/
public function postCharacterAction(Request $request)
{
$data = $request->request->all();
// If the request contains image date, first convert it from its base64 enconding to a real file
if ($request->request->has('image') && $request->request->get('id')) {
$imagePath = realpath($this->get('kernel')->getRootDir() . '/../web'.$this->container->getParameter('upload_path_characters')).'/'.$request->request->get('id');
$file = Base64File::create($imagePath, $request->request->get('image'));
$data['image'] = $file;
}
$character = new Character();
$form = $this->createForm(new CharacterType(), $character);
$form->bind($data);
var_dump($form->isValid());
var_dump($form->getErrorsAsString());
var_dump($this->generateUrl('get_characters', array('id' => $character->getId()), true));
die();
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($character);
$em->flush();
$response->headers->set('Location', $this->generateUrl('acme_demo_user_get', array('id' => $user->getId()), true));
$view = $this->view($character, 200);
return $this->handleView($view);
}
else {
}
}
}
The thing that isn't quite working like I expected is the generateUrl part to set the Location header. It spits out http://optc.local/api/characters?id=2. This will of course only list all resources instead. But what I want is http://optc.local/api/characters/2.
How would I do that? Seems like I'm missing something simple.
(By the way, the PHP part about returning the Location header is from http://williamdurand.fr/2012/08/02/rest-apis-with-symfony2-the-right-way/, so I expected this to be the "right" way.)
you should check app/console debug:router in terminal to see what name symfony has named the route
in my case it used a minus instead of an underscore
i.e get-character
You must use get_character route instead of get_characters route,
I suggest to you whether implement ClassResourceInterface or use RouteResource annotation, that can use method name as getAction, cgetAction(this is only a suggestion)
Related
I'm a beginner in symfony and I would like to inject my post entity into a method of my controller.
However, I've the following error fired :
Unable to guess how to get a Doctrine instance from the request information for parameter "post".
Here is my code :
/**
* #Route("/post/article/new", name="new.html.twig")
* #param Request $request
* #param Posts $posts
* #return Response
*/
public function newArticle(Request $request, Posts $posts): Response
{
$post = $posts;
$article = new Articles();
$post->setAuthor(1);
$form = $this->createForm(PostsType::class, $post);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$this->em->persist($post);
$this->em->flush();
$article->setPost($post->getId());
$themes = $form->get('themes')->getData();
$article->setThemes(implode(',', $themes));
$this->em->persist($post);
$this->em->flush();
return $this->redirectToRoute('home.html.twig');
}
return $this->render('post/article.html.twig', [
'formArticle' => $form->createView()
]);
}
You need a reference to the Post in the route, like a slug for the id or another unique field.
#Route("/post/{id}/article/new", ...
Otherwise Symfony has no idea which Post to load.
How to add image on push notification using brozot / Laravel-FCM ?
I'm sending notifications correctly, but I would like to know how can I send an image with the notification?
I tried this code but not working
$pushData = ['body' => $message, 'title'=>$title,'image'=>'image-url'];
$pushJsonData = json_encode($pushData);
if(count($tokens)>0)
{
$optionBuilder = new OptionsBuilder();
$optionBuilder->setTimeToLive(60*20);
$notificationBuilder = new PayloadNotificationBuilder($title);
$notificationBuilder->setClickAction('NOTIFICATION');
$notificationBuilder->setBody($message)->setSound('default');
$notificationBuilder->setTag(strtotime("now"));
$dataBuilder = new PayloadDataBuilder();
$dataBuilder->addData(['a_data' => $pushJsonData]);
$option = $optionBuilder->build();
$notification = $notificationBuilder->build();
$data = $dataBuilder->build();
$downstreamResponse = FCM::sendTo($tokens, $option, $notification, $data);
$downstreamResponse->numberSuccess();
$downstreamResponse->numberFailure();
$downstreamResponse->numberModification();
//return Array - you must remove all this tokens in your database
$downstreamResponse->tokensToDelete();
//return Array (key : oldToken, value : new token - you must change the token in your database )
$downstreamResponse->tokensToModify();
//return Array - you should try to resend the message to the tokens in the array
$downstreamResponse->tokensToRetry();
// return Array (key:token, value:errror) - in production you should remove from your database the tokens present in this array
$downstreamResponse->tokensWithError();
You need to create a custom script that herance the vendor script and add some properties on it.
Create a new path in app: app/Notifications/Message
Add a new script called CustomPayloadNotification.php
Here you need to:
Extends PayloadNotification (vendor);
Add a new variable $image;
Override __construct method, changing the parameter type to CustomPayloadNotificationBuilder. Set all the variables like is in PayloadNotification and also set the new variable $image.
Override toArray method, setting all the properties like is in PayloadNotification and also set a new property image with $image value.
Something like this:
<?php
namespace App\Notifications\Messages;
use LaravelFCM\Message\PayloadNotification;
use App\Notifications\Messages\CustomPayloadNotificationBuilder;
class CustomPayloadNotification extends PayloadNotification // Extends vendor script
{
protected $image; // New variable
/**
* CustomPayloadNotificationBuilder constructor.
*
* #param CustomPayloadNotificationBuilder $builder
*/
public function __construct(CustomPayloadNotificationBuilder $builder) // Change the type of parameter
{
$this->title = $builder->getTitle();
$this->body = $builder->getBody();
$this->icon = $builder->getIcon();
$this->sound = $builder->getSound();
$this->badge = $builder->getBadge();
$this->tag = $builder->getTag();
$this->color = $builder->getColor();
$this->clickAction = $builder->getClickAction();
$this->bodyLocationKey = $builder->getBodyLocationKey();
$this->bodyLocationArgs = $builder->getBodyLocationArgs();
$this->titleLocationKey = $builder->getTitleLocationKey();
$this->titleLocationArgs = $builder->getTitleLocationArgs();
$this->image = $builder->getImage(); // Set image
}
/**
* convert CustomPayloadNotification to array
*
* #return array
*/
function toArray()
{
$notification = [
'title' => $this->title,
'body' => $this->body,
'icon' => $this->icon,
'sound' => $this->sound,
'badge' => $this->badge,
'tag' => $this->tag,
'color' => $this->color,
'click_action' => $this->clickAction,
'body_loc_key' => $this->bodyLocationKey,
'body_loc_args' => $this->bodyLocationArgs,
'title_loc_key' => $this->titleLocationKey,
'title_loc_args' => $this->titleLocationArgs,
'image' => $this->image, // Set property image with $image value
];
// remove null values
$notification = array_filter($notification, function($value) {
return $value !== null;
});
return $notification;
}
}
Add a new script called CustomPayloadNotificationBuilder.php
Here you need to:
Extends PayloadNotificationBuild (vendor);
Add a new variable protected $image;
Create the set/get methods to $image;
Override build method, returning a new CustomPayloadNotification instead PayloadNotification.
Something like this:
<?php
namespace App\Notifications\Messages;
use LaravelFCM\Message\PayloadNotificationBuilder;
use App\Notifications\Messages\CustomPayloadNotification;
class CustomPayloadNotificationBuilder extends PayloadNotificationBuilder // Extends vendor script
{
protected $image; // New variable
/**
* Set image
*
* #param string $image
*
* #return CustomPayloadNotificationBuilder
*/
public function setImage($image)
{
$this->image = $image;
return $this;
}
/**
* Get image.
*
* #return null|string
*/
public function getImage()
{
return $this->image;
}
/**
* Build an CustomPayloadNotification
*
* #return CustomPayloadNotification
*/
public function build()
{
return new CustomPayloadNotification($this); // Change the object returned
}
}
Reference CustomPayloadNotificationBuilder instead PayloadNotificationBuilder scripts in your code.
Use the method setImage
Your code should be something like this:
use App\Notifications\Messages\CustomPayloadNotificationBuilder; // Add the reference on the top of your code
// No changes before here [...]
$notificationBuilder = new CustomPayloadNotificationBuilder($title); // Replace here
$notificationBuilder->setClickAction('NOTIFICATION');
$notificationBuilder->setBody($message)->setSound('default');
$notificationBuilder->setTag(strtotime("now"));
$notificationBuilder->setImage("Image URL here"); // Add an image
// No changes after here [...]
you need to do some change in vendor for this
Step-1 : Go to the following url I am sharing here-
Laravel-FCM-master\Laravel-FCM-master\src\Message\PayloadNotification.php
Step-2 : here you have to add a instance variable as
protected $image;
Step - 3 find the public function __construct(PayloadNotificationBuilder $builder)
step -4 add $this->image = $builder->getImage(); in this function.
step -5 find the public function toArray()
step -6 add here 'image' => $this->image,
step -7 save and exit.
step -8 then follow this url in vendor again Laravel-FCM-master\Laravel-FCM-master\src\Message\PayloadNotificationBuilder.php:
step -9 add in above page
/**
* Indicates the image that can be displayed in the notification
* Supports an url or internal image.
*
* #param string $image
*
* #return PayloadNotificationBuilder current instance of the builder
*/
public function setImage($image)
{
$this->image = $image;
return $this;
}
step - 10 then add
/**
* Get image.
*
* #return null|string
*/
public function getImage()
{
return $this->image;
}
step - 11 that's it, now you can easily able to add a new field in your controller where your code was written asked in question.
simply modify as
$notificationBuilder = new PayloadNotificationBuilder($title);
$notificationBuilder->setClickAction('NOTIFICATION');
$notificationBuilder->setBody($message)->setImage("https://yourdoamin.com/yourdesiredimage.jpeg")->setSound('default');
$notificationBuilder->setTag(strtotime("now"));
and send you will get exact what you are looking for.
I have problem saving entity trough form with ManyToMany relations.
I can not save fields that are on "mappedBy" side of relation.
Code below is not saving anything to database and not trowing any errors:
// Entity/Pet
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Customer", mappedBy="pet", cascade={"persist"})
*/
private $customer;
/**
* Set customer
*
* #param \AppBundle\Entity\Customer $customer
* #return Pet
*/
public function setCustomer($customer)
{
$this->customer = $customer;
return $this;
}
// Entity/Customer
/**
* #var Pet
*
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Pet", inversedBy="customer", cascade={"persist"})
* #ORM\JoinTable(name="customer_pet",
* joinColumns={
* #ORM\JoinColumn(name="customer_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="pet_id", referencedColumnName="id")
* }
* )
*/
private $pet;
// PetType.php
$builder->add('customer', 'entity',
array(
'class' => 'AppBundle:Customer',
'property' => 'firstname',
'empty_value' => 'Choose owner',
'multiple' => true
));
It is working the other way around. So if I am saving something from CustomerType everything works.
EDIT:
Solution below worked for me but after couple days I found a problem with that solution. If form will be submitted with value that has been already saved in the database then Symfony will trow an error. To prevent that I had to check if given customer has been already assigned to the pet.
Checking of currently assigned customers had to be done on the beginning of function and not after form submission because for some reason after submission Pet() object contains submitted values not only those present in the db.
So on the beginning I've putted all already assigned customers in to the array
$em = $this->getDoctrine()->getManager();
$pet = $em->getRepository('AppBundle:Pet')->find($id);
$petOriginalOwners = array();
foreach ($pet->getCustomer() as $petCustomer)
{
$petOriginalOwners[] = $petCustomer->getId();
}
And after form submission I've checked if submitted ID's are in the array
if ($form->isValid())
{
foreach ($form['customer']->getData()->getValues() as $v)
{
$customer = $em->getRepository('AppBundle:Customer')->find($v->getId());
if ($customer && !in_array($v->getId(), $petOriginalOwners) )
{
$customer->addPet($pet);
}
}
$em->persist($pet);
$em->flush();
return $this->redirect($this->generateUrl('path'));
}
In Symfony2 the entity with the property with the inversedBy doctrine comment is the one that is supposed to EDIT THE EXTRA TABLE CREATED BY THE MANYTOMANY RELATION. That is why when you create a customer it inserts the corresponding rows in that extra table, saving the corresponding pets.
If you want the same behavior to happen the other way around, I recommend:
//PetController.php
public function createAction(Request $request) {
$entity = new Pet();
$form = $this->createCreateForm($entity);
$form->submit($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
foreach ($form['customer']->getData()->getValues() as $v) {
$customer = $em->getRepository('AppBundle:Customer')->find($v->getId());
if ($customer) {
$customer->addPet($entity);
}
}
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('pet_show', array('id' => $entity->getId())));
}
return $this->render('AppBundle:pet:new.html.twig', array(
'entity' => $entity,
'form' => $form->createView(),
));
}
private function createCreateForm(Pet $entity) {
$form = $this->createForm(new PetType(), $entity, array(
'action' => $this->generateUrl('pet_create'),
'method' => 'POST',
));
return $form;
}
These two are but standard Symfony2 CRUD-generated actions in the controller corresponding to Pet entity.
The only tweak is the foreach structure inserted in the first action, that way you forcibly add the same pet to each customer you select in the form, thus getting the desired behavior.
Look, it is highly probable THIS is not the RIGHT WAY, or the PROPER WAY, but is A WAY and it works. Hope it helps.
In my case with a services <-> projects scenario, where services has "inversedBy" and projects has "mappedBy" I had to do this in my project controller's edit action so that when editing a project the services you checked would be persisted.
public function editAction(Request $request, Project $project = null)
{
// Check entity exists blurb, and get it from the repository, if you're inputting an entity ID instead of object ...
// << Many-to-many mappedBy hack
$servicesOriginal = new ArrayCollection();
foreach ($project->getServices() as $service) {
$servicesOriginal->add($service);
}
// >> Many-to-many mappedBy hack
$form = $this->createForm(ProjectType::class, $project);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
// << Many-to-many mappedBy hack
foreach ($servicesOriginal as $service) {
if (!$project->getServices()->contains($service)) {
$service->removeProject($project);
$em->persist($service);
}
}
foreach ($project->getServices() as $service) {
$service->addProject($project);
$em->persist($service);
}
// >> Many-to-many mappedBy hack
$em->persist($project);
$em->flush();
return; // I have a custom `redirectWithMessage()` here, use what you like ...
}
return $this->render("Your-template", [
$form => $form->createView(),
$project => $project,
]);
}
This works for both adding and removing entities in the many-to-many from the "mappedBy" side, so EntityType inputs should work as intended.
What's going on here is we're first building an "original" collection containing all of the service entities already linked to for this project. Then when the form is saving we're ensuring:
First that any unchecked services (those in the original collection but not the project object) have the project removed from their internal collection, then persisted.
Second that any newly checked services each add the project to their internal collection, then persisted.
Important: This depends on your entity's addService() and addProject() methods respectively check that each others' collections do not contain duplications. If you don't do this you'll end up with an SQL level error about a duplicate record insertion.
In the service entity I have:
/**
* Add project
*
* #param Project $project
*
* #return Service
*/
public function addProject(Project $project)
{
if (!$this->projects->contains($project)) {
$this->projects->add($project);
}
if (!$project->getServices()->contains($this)) {
$project->getServices()->add($this);
}
return $this;
}
In the project entity I have:
/**
* Add service
*
* #param Service $service
*
* #return Project
*/
public function addService(Service $service)
{
if (!$this->services->contains($service)) {
$this->services->add($service);
}
if (!$service->getProjects()->contains($this)) {
$service->getProjects()->add($this);
}
return $this;
}
You could alternatively check this in your controller instead, but makes sense if the model validates this itself when possible, as the model would break anyway if there were duplicates from any source.
Finally in your controller's create action you'll likely need this bit too just before $em->persist($project). (You won't need to work with an "original" collection as none will exist yet.)
// << Many-to-many mappedBy hack
foreach ($project->getServices() as $service) {
$service->addProject($project);
$em->persist($service);
}
// >> Many-to-many mappedBy hack
I just had the same problem and I solved it differently.
Changing the code in the controller is not the better way to do it.
In my case I have a GenericController that handle all my CRUDs so I can't put in it specific code.
The best way to do it is by adding in your PetType a listener like this :
// PetType.php
$builder->add('customer', 'entity',
array(
'class' => 'AppBundle:Customer',
'property' => 'firstname',
'empty_value' => 'Choose owner',
'multiple' => true
))
->addEventListener( FormEvents::SUBMIT, function( FormEvent $event ) {
/** #var Pet $pet */
$pet = $event->getData();
foreach ( $pet->getCustomers() as $customer ) {
$customer->addPet( $pet );
}
} );
That way you'll keep the mapping logic in the same place.
I have the 2 simple tables below:
CUSTOMERS
id, email
CLAIMS
id, customer_id(fk), description
I created the related models (Customers.php and Claims.php) and set-up relationships: hasOne() and belongsTo().
I also have my related RESTful controllers ready: CustomersController.php and ClaimsController.php.
What would be the best solution if I need to create/update records in both tables by submitting one form? Create one general controller? Mix models?
I have been searching in Laravel docs and on Google and still have no idea how to achieve this.
Customer model
public function claims(){
return $this->hasMany('App\Claims');
}
Claims model
public function customer(){
return $this->belongsTo('App\Customer');
}
Now in controller u need to send request in store action
Something like this
class CreateCustomerClaim extends Request {
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'email' => 'required',
'description'=> 'required'
];
}
}
Now in store action send your request, grab data from request and insert it in db
public function store(CreateCustomerClainsRextends $request)
{
//example
$customer= new Customer($request->all());
Auth::user()->claims()->save($customer);
}
if u need to update use same request in update function, when u grab data from request just use update. Here is example where i update 3 different tables from one request
public function update($id,ArtikalUpdateRequest $request)
{
$article = Artikal::findOrFail($id);
if($article !== null){
$article->update($request->all());
\DB::table('artikal_podkategorija')
->where('artikal_id', $article->id)
->update(array('podkategorija_id' => $request['podkategorija']));
\DB::table('arikalslike')
->where('artikal_id', $article->id)
->update(array('NazivSlike' => $request['NazivSlike']));
$slika = \DB::table('arikalslike')
->where('artikal_id', $article->id)->first();
$image = Request::file('image');
//dd($image);
if($image != null){
$destinationPath = 'uploads/artiklislike/';
$thumb = $slika->SifraSlike;
$fileName = $thumb;
$nazivthumb = $slika->NazivThumb;
$slika->NazivSlike = $request['NazivSlike'];
$slika->NazivThumb = $nazivthumb;
$slika->SifraSlike = $fileName;
$slika->artikal_id = $article->id;
//Snima sliku
$img = Image::make(Input::file('image'));
$destinationPath = $destinationPath.$fileName;
Image::make($img)->save($destinationPath);
// Snima sliku u manjem formatu thumb
$destinationPath = 'uploads/artiklislike/';
$img = Image::make(Input::file('image'));
$destinationPath = $destinationPath.$nazivthumb;
Image::make($img)->resize(300, 200)->save($destinationPath);
}
}
return redirect('artikli')->with(['flash_message' => 'Uspiješno ste obrisali artikal!']);
}
I am now using the FOSRestBundle in order to build a REST API within my Symfony application. The idea for now is to list some locations(hotels, restaurants...), I managed to configure the automatic routes with FOSRestBundle like:
/api/locations , /api/locations/{id} , /api/locations/{name}/detail
with this controller:
class LocationController extends FOSRestController implements ClassResourceInterface
{
/**
* GET /locations
*
* #return Array
*
*/
public function cgetAction()
{
$locations = $this->getDoctrine()
->getManager()
->getRepository('VisitBILocationsBundle:Location')
->findAll();
if (!$locations) {
return array(
'locations' => $locations,
'status' => 1
);
}
return array(
'locations' => $locations,
'status' => 0
);
}
/**
* GET /locations/{locationId}
*
* #return Array
*
*/
public function getAction($id)
{
$location = $this->getDoctrine()
->getManager()
->getRepository('VisitBILocationsBundle:Location')
->findBy(array('id' => $id));
if (!$location) {
return array(
'location' => $location,
'status' => 1
);
}
return array(
'location' => $location,
'status' => 0
);
}
/**
* GET /locations/{name}/detail
*
* #return Array
*/
public function getDetailAction($name)
{
$detail = $this->getDoctrine()
->getManager()
->getRepository('VisitBILocationsBundle:LocationDetail')
->findBy(array('name' => $name));
if (!$detail) {
return array(
'locationDetail' => $detail,
'status' => 1
);
}
return array(
'locationDetail' => $detail,
'status' => 0
);
}
}
I've been struggling with this, but would anyone know how should I proceed to generate one custom url like this:
/api/locations/nearby/{latitude}/{longitude}
The idea is that I would provide my own latitude and longitude, and the backend will calculate and provide the locations which are the closest to me.
Of course I've looked at the documentation of FOSRestBundle for manual route configuration, but since I spent some time trying to do it, I come here to ask for some help :)
If you want to manually define a route, it should just be as simple as adding the route to the existing routing configuration. How exactly you do it depends on how you're handling the routing configuration: annotation, yaml, or xml.
Option 1: YAML
In the routing.yml file (ex: src/Vendor/MyBundle/Resources/config/routing.yml) add something like:
location_nearby:
pattern: /api/locations/nearby/{latitude}/{longitude}
defaults: { _controller: "MyBundle:Location:nearby" }
requirements:
_method: GET
which would correspond to this method in LocationController:
public function nearbyAction($latitude, $longitude) { ... }
Option 2: Annotations
Add this use statement to the Controller file:
use FOS\RestBundle\Controller\Annotations\Get;
and then define the route above the controller method:
/**
* Return a nearby location
* #Get("/api/locations/nearby/{latitude}/{longitude}")
*/
public function nearbyAction($latitude, $longitude) { ... }
OK here is how to proceed, works fine for me:
I use the annotation system to route /locations/nearby/{latitude}/{longitude}
/**
* Return a nearby location
* #Get("/locations/nearby/{latitude}/{longitude}", requirements={"latitude" = "[-+]?(\d*[.])?\d+", "longitude" = "[-+]?(\d*[.])?\d+"})
*/
public function nearbyAction($latitude, $longitude) {...}
Then I have to specify float numbers with: requirements={"latitude" = "[-+]?(\d*[.])?\d+", "longitude" = "[-+]?(\d*[.])?\d+"}
Those will still be interpreted as string by the controller: "64.1333", I just have to use this in the controller:
floatval($latitude)
to get url parameters as float and then do my calculations!