Beste php'ers,
Ik ben bezig met rest services opzetten binnen symfony 2. Ik ben begonnen met eerst volledig handmatig die services opzetten en dat gaat ok. Ben nu op het punt dat ik er toch iets verder mee wil en ben op de FOS restbundle uitgekomen. Nu ben ik een tutorial aan het volgen en het gaat overal goed m.u.v. het laatste gedeelte. Als ik de service aanroep krijg ik de volgende foutmelding:
The controller must return a response (Array(users => Array(0 => Object(Screenfony\DemoBundle\Entity\User), 1 => Object(Screenfony\DemoBundle\Entity\User))) given)
Ik heb alles exact 1 op 1 gevolgd (heb alleen pas 1 service i.p.v. 2) alleen bij het aanroepen gaat het niet goed.
userscontroller
namespace Screenfony\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use FOS\RestBundle\Controller\Annotations\View;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
class UsersController extends Controller{
//put your code here
/*
* @return array
* @View()
*/
public function getUsersAction()
{
$users= $this->getDoctrine()->getRepository('ScreenfonyDemoBundle:User')->findAll();
return (array('users' => $users));
}
}
Als ik mijn users dump na het ophalen met exit(\Doctrine\Common\Util\Debug::dump($users)); zie ik wel dat mijn gebruikers correct worden opgehaald.
Als ik dus alles zie wordt de service goed aangeroepen de gebruikers worden goed opgehaald alleen de response gaat niet goed. Heb met curl verschillende headers meegegeven maar geen resultaat.
Heb dus al een tijdje dingen zitten uitproberen maar loop nu toch echt vast met dit. Heeft iemand enige ideeen waar het aan kan liggen?
De foutmelding heeft niets met de restBundle te maken. (Ik zou je daar ook niet zo maar even mee kunnen helpen omdat ik deze bundle nog nooit gebruikt heb.)
De foutmelding is eigenlijk best wel duidelijk. Je roept een Action aan vanuit de browser. Dan moet er ook een antwoord verstuurd worden vanaf de server. In Symfony gebruik je hiervoor ALTIJD een Response object. voor iedere Action is dus een Response object vereist.
Jij retourneert vanuit getUsersAction() een array en geen Response object. Wat voor een beginner lastig te doorgronden is dat je een Response object kunt retourneren met statische content maar je kunt ook een Twig template gebruiken om je content op te bouwen. Het resultaat van deze template wordt echter gewoon weer aan het response object meegegeven. Daarnaast kun je de Controller::render functie laten weten welke template ze moet gebruiken aan de hand van een parameter of middels annotations. Deze render() functie geeft een compleet Response object terug.
Retourneer een response object zonder template:
<?php
use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class UsersController extends Controller
{
public function getUsersAction()
{
return new Response('<h1>All Users!</h1>');
}
}
?>
Retourneer een response object middels een template en zonder gebruik te maken van annotations:
<?php
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class UsersController extends Controller
{
public function getUsersAction()
{
return $this->render('AppBundle:Users:index.html.twig', array('users' => $users));
// Controller::render() geeft een Response object terug!
}
}
?>
Retourneer een response object middels een template met gebruik van annotations:
<?php
use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
class UsersController extends Controller
{
/**
* Lists all Users.
*
* @Route("/", name="app_users")
* @Method("GET")
* @Template("AppBundle:Default:index.html.twig")
*/
public function getUsersAction()
{
return array('users' => $users);
}
}
?>
Frank, dat is hier niet het geval. Als er geen response wordt geretourneerd zal Symfony het Kernel.VIEW event aanroepen, om 3rd party bundles de mogelijkheid te geven om er alsnog een response van te maken.
In dit geval zal de ViewResonseListener van FOSRestBundle de array moeten serializen (als het een XML/JSON request betreft) of de template renderen. Dit omdat deze action is getagged met de @FOS\RestBundle\Annotations\View() annotation.
Ik heb geen idee waarom dit hier niet werkt, al geprobeerd de cache te verschonen?
Ik heb al de cache geleegd en een volledig nieuw project geprobeerd aan te maken en opnieuw maar zonder succes. Ben nog steeds aan het zoeken naar de oplossing.
Als ik app/console route:debug doe zie ik dat de route wel correct wordt gevonden, alleen het response object retourneren niet.
Ik ga vanmiddag even kijken of ik het voor mekaar kan krijgen om het zonder de annotations te doen (dus de view in de functie aanmaken). Misschien dat om de 1 of andere reden de annotations niet goed gaan.
[size=xsmall]Toevoeging op 31/07/2015 13:39:34:[/size]
Heb inmiddels getest zonder de annotations en dan gaat het goed. Dus ga hier voorlopig even mee verder.
public function getTestAction()
{
$data = new TestClass();
$data->setTestVar("dit is een testvar");
$data2 = new TestClass();
$data2->setTestVar("dit is data 2");
$returnArray = array($data, $data2);
$view = View::create()->setData(array('gegevens' => $returnArray));
return $this->getViewHandler()->handle($view);
}
Heel raar zoek later wel uit waaorm het met annotations niet goed gaat. Loop nu weer tegen het probleem op dat hij nu bij 'elke' route die ik heb er een REST service van maakt (wat niet de bedoeling is aangezien sommige routes gewoon een webpagina moeten tonen).