Hoi,

Ik heb een nieuw Symfony2-project waarbij ik een bestaande database automatisch heb laten mappen naar entiteiten. Ik wil graag een RESTapi gaan maken met dit Symfony-project, dus heb ik de volgende controller:
<?php
namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;

class APIController extends Controller
{
    /**
     * @Route("/api/{type}/{id}", name="get")
     * @Method("GET")
     */
    public function getAction($type, $id, Request $request)
    {
        $response = null;

        $serializer = new Serializer(
            array(
                new ObjectNormalizer()
            ),
            array(
                new XmlEncoder(),
                new JsonEncoder()
            )
        );

        $repository = $this->getDoctrine()->getRepository('AppBundle:' . $type);

        $entity = $repository->find($id);
        $test = $serializer->serialize($entity, 'json');

        $response = new Response($serializer->serialize($entity, 'json'));
        $response->headers->set('Content-Type', 'application/json');

        return $response;
    }
}
?>

Ik heb wel een deel weggelaten, het gaat namelijk om het volgende. Als ik nu /api/Ride/1 opvraag, dan krijg ik de volgende exception:
Runtime Notice: Accessing static property Proxies\__CG__\AppBundle\Entity\Route::$lazyPropertiesDefaults as non static

Deze Ride heeft een referentie naar Route. Deze entiteiten zien er zo uit: (getters en setters weggelaten)
<?php
namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Ride
 *
 * @ORM\Table(name="ride", indexes={@ORM\Index(name="route", columns={"route"})})
 * @ORM\Entity
 */
class Ride
{
    /**
     * @var \DateTime
     *
     * @ORM\Column(name="date", type="date", nullable=false)
     */
    private $date;

    /**
     * @var string
     *
     * @ORM\Column(name="description", type="string", length=50, nullable=true)
     */
    private $description;

    /**
     * @var boolean
     *
     * @ORM\Column(name="retour", type="boolean", nullable=true)
     */
    private $retour;

    /**
     * @var boolean
     *
     * @ORM\Column(name="active", type="boolean", nullable=false)
     */
    private $active;

    /**
     * @var integer
     *
     * @ORM\Column(name="ridenumber", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $ridenumber;

    /**
     * @var \AppBundle\Entity\Route
     *
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Route")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="route", referencedColumnName="routenumber")
     * })
     */
    private $route;
}
?>

<?php
namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Route
 *
 * @ORM\Table(name="route")
 * @ORM\Entity
 */
class Route
{
    /**
     * @var string
     *
     * @ORM\Column(name="from", type="string", length=50, nullable=false)
     */
    private $from;

    /**
     * @var string
     *
     * @ORM\Column(name="addressfrom", type="string", length=50, nullable=false)
     */
    private $addressfrom;

    /**
     * @var string
     *
     * @ORM\Column(name="postalcodefrom", type="string", length=7, nullable=false)
     */
    private $postalcodefrom;

    /**
     * @var string
     *
     * @ORM\Column(name="to", type="string", length=50, nullable=false)
     */
    private $to;

    /**
     * @var string
     *
     * @ORM\Column(name="addressto", type="string", length=50, nullable=false)
     */
    private $addressto;

    /**
     * @var string
     *
     * @ORM\Column(name="postalcodeto", type="string", length=7, nullable=false)
     */
    private $postalcodeto;

    /**
     * @var string
     *
     * @ORM\Column(name="distance", type="decimal", precision=5, scale=2, nullable=false)
     */
    private $distance;

    /**
     * @var boolean
     *
     * @ORM\Column(name="active", type="boolean", nullable=false)
     */
    private $active;

    /**
     * @var integer
     *
     * @ORM\Column(name="routenumber", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $routenumber;
}
?>

Ik vind het vooral een vage foutmelding aangezien deze uit Symfony zelf komt. Deze foutmelding krijg ik bij andere entiteiten ook (zoals Cursist die een Person is).

Weet iemand wat ik moet doen om dit op te lossen?

Roel
Probeer eens in je Ride Entity:
<?php
/**
* @ORM\ManyToOne(targetEntity="Route")
* @ORM\JoinColumn(name="route_id", referencedColumnName="routenumber")
**/
private $route;
?>

p.s. Waarom heet routenumber niet gewoon id?
Bedankt voor je reactie. Dan krijg ik dezelfde foutmelding, maar ik krijg niet goed achterhaald waarom.
Wat betreft routenumber in plaats van ID: ik doe dit project samen met een klasgenoot en die is zelf na jaren overtuigd door een docent dat het soms beter is om ...number te gebruiken in plaats van ID. Ik ben het er ook niet echt mee eens, maar soms krijg je iemand niet overtuigd om een bepaalde naamgeving te volgen, haha. :-)
Kun je fetch="EAGER" eens toevoegen aan line 54 van Ride Entity, dus zo:


* @ORM\ManyToOne(targetEntity="Route", fetch="EAGER")
Ook dat heeft helaas geen effect.
Ik zou toch eens beginnen om de standaard werkwijze aan te houden. Beiden entities voorzien van een $id met de juiste annotations. Heb je al eens het commando


doctrine:schema:update --force geprobeerd?


Voordat je dat doet wel even een backup maken van je database.

[size=xsmall]Toevoeging op 14/09/2015 19:52:15:[/size]

Tevens even debuggen met een simpele echo om te zien welke code nog wel wordt uitgevoerd en welke niet.
Voor de overzichtelijkheid heb ik voor nu alle entiteiten weggegooid en alleen Ride en Route overgehouden. Zelfs na de volgende structuur krijg ik dezelfde foutmelding:
<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Ride
 *
 * @ORM\Table(name="rides")
 * @ORM\Entity
 */
class Ride
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="date", type="date", nullable=false)
     */
    private $date;

    /**
     * @var string
     *
     * @ORM\Column(name="description", type="string", length=50, nullable=true)
     */
    private $description;

    /**
     * @var boolean
     *
     * @ORM\Column(name="retour", type="boolean", nullable=true)
     */
    private $retour;

    /**
     * @var boolean
     *
     * @ORM\Column(name="active", type="boolean", nullable=false)
     */
    private $active;

    /**
     * @ORM\ManyToOne(targetEntity="Route")
     * @ORM\JoinColumn(name="route_id", referencedColumnName="id")
     **/
    private $route;
}
?>

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Route
 *
 * @ORM\Table(name="routes")
 * @ORM\Entity
 */
class Route
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="from", type="string", length=50, nullable=false)
     */
    private $from;

    /**
     * @var string
     *
     * @ORM\Column(name="addressfrom", type="string", length=50, nullable=false)
     */
    private $addressfrom;

    /**
     * @var string
     *
     * @ORM\Column(name="postalcodefrom", type="string", length=7, nullable=false)
     */
    private $postalcodefrom;

    /**
     * @var string
     *
     * @ORM\Column(name="to", type="string", length=50, nullable=false)
     */
    private $to;

    /**
     * @var string
     *
     * @ORM\Column(name="addressto", type="string", length=50, nullable=false)
     */
    private $addressto;

    /**
     * @var string
     *
     * @ORM\Column(name="postalcodeto", type="string", length=7, nullable=false)
     */
    private $postalcodeto;

    /**
     * @var string
     *
     * @ORM\Column(name="distance", type="decimal", precision=5, scale=2, nullable=false)
     */
    private $distance;

    /**
     * @var boolean
     *
     * @ORM\Column(name="active", type="boolean", nullable=false)
     */
    private $active;
}
?>
Goed. Ik heb jouw entities even in gelijknamige bestanden geplaats in de AppBundle/entity directory en de volgende commands uitgevoerd:


app/console doctrine:generate:entities AppBundle:Ride
app/console doctrine:generate:entities AppBundle:Route
app/console doctrine:update:schema --force
app/console doctrine:generate:crud AppBundle:Ride
app/console doctrine:generate:crud AppBundle:Route


Dat lukte allemaal nog maar toen wilde ik om te beginnen de aangemaakte RouteController testen door naar ../app_dev.php/route te surfen en toen kreeg ik de eerste foutmelding:

De Entity Route bestond al en kon niet nog een keer aangemaakt worden. (even vrij vertaald)

Deze naam 'Route' voor de entity is dus erg ongelukkig gekozen en die moet je dus een andere naam geven.

Daarna Kon ik wel de lijst met 'Routes' opvragen, die overigens nog leeg was dus probeerde ik er een aan te maken. Het formulier verscheen gewoon ik ik alle velden even iets ingevuld en op 'Create' gedrukt.
Toen kreeg ik weer een foutmelding dat de query mislukt was. Even nagezocht en blijkt dat 'from' en 'to' gereserveerde woorden zijn in MySQL. Die kolomnamen moet je dus veranderen in de annotations.

Daarna werkte het wel en ging ik kijken of RideController werkte. Ook hier ging het heel even fout.

MyRoute zoals ik de entity inmiddels genoemd had, had geen __toString() method. Dus die heb ik even aangemaakt:

<?php
public function __toString() {
return $this->addressfrom . ' - ' . $this->addressto;
}
?>

Daarna ging het wel goed. En dat verbaasde mij enigzins omdat 'date' een keyword is. Ik wil je dus adviseren om ook deze kolomnaam te wijzigen.

Ik kreeg overigens niet jouw foutmelding.


Ik heb zowel Route als Ride opgevraagd via Doctrine en dit gaat allemaal goed. Het gaat fout wanneer ik wil serializen.
Als ik met Xdebug door het proces loop, dan zie ik dat de entity nog goed opgehaald wordt, maar wanneer ik hem serialize, dan krijg ik de exception.
<?php
$entity = $repository->find($id);
$test = $serializer->serialize($entity, 'json');
?>

Regel 1 (38 in de controller, bovenaan deze pagina) gaat nog goed. De regel erna geeft de fout.
Googelen op deze foutmelding levert ook weinig zinnigs op; fetch="EAGER" heb ik ook geprobeerd, tevergeefs.

[size=xsmall]Toevoeging op 16/09/2015 21:29:09:[/size]

Het heeft sowieso te maken met de referentie naar een andere klasse, want Ride ophalen en serializen werkt namelijk wel. Het lijkt wel een fout in Symfony of Doctrine.
@Roel,

Ik betwijfel of dat het probleem is. Ik gok eerder dat je beter 'private' naar 'protected' kunt omzetten, zou je dat willen proberen?

Edit: Vergeet niet erna je cache op te schonen.
Roel heb je mijn puntjes wel meegenomen want kolomnamen to en from gaan nooit werken!
Verder:
wat geeft

<?php
$entity = $repository->find($id);
echo '<pre>';
print_r($entity);
exit;
?>

Reageren