Symfony exception bij serializen

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Pagina: 1 2 volgende »

Roel -

Roel -

11/09/2015 15:21:35
Quote Anchor link
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:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?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)
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<?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;
}

?>

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<?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
Gewijzigd op 11/09/2015 15:22:33 door Roel -
 
PHP hulp

PHP hulp

17/06/2024 21:07:43
 
Frank Nietbelangrijk

Frank Nietbelangrijk

11/09/2015 17:28:34
Quote Anchor link
Probeer eens in je Ride Entity:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
<?php
    /**
     * @ORM\ManyToOne(targetEntity="Route")
     * @ORM\JoinColumn(name="route_id", referencedColumnName="routenumber")
     **/

    private $route;
?>


p.s. Waarom heet routenumber niet gewoon id?
Gewijzigd op 11/09/2015 17:37:14 door Frank Nietbelangrijk
 
Roel -

Roel -

13/09/2015 22:33:54
Quote Anchor link
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. :-)
Gewijzigd op 13/09/2015 22:34:49 door Roel -
 
DavY -

DavY -

14/09/2015 11:50:19
Quote Anchor link
Kun je fetch="EAGER" eens toevoegen aan line 54 van Ride Entity, dus zo:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
* @ORM\ManyToOne(targetEntity="Route", fetch="EAGER")
 
Roel -

Roel -

14/09/2015 18:39:38
Quote Anchor link
Ook dat heeft helaas geen effect.
 
Frank Nietbelangrijk

Frank Nietbelangrijk

14/09/2015 19:49:12
Quote Anchor link
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

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
doctrine:schema:update --force geprobeerd?


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

Toevoeging op 14/09/2015 19:52:15:

Tevens even debuggen met een simpele echo om te zien welke code nog wel wordt uitgevoerd en welke niet.
 
Roel -

Roel -

16/09/2015 18:09:39
Quote Anchor link
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:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<?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;
}

?>

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
<?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;
}

?>
 
Frank Nietbelangrijk

Frank Nietbelangrijk

16/09/2015 20:44:28
Quote Anchor link
Goed. Ik heb jouw entities even in gelijknamige bestanden geplaats in de AppBundle/entity directory en de volgende commands uitgevoerd:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
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:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
<?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.
Gewijzigd op 16/09/2015 20:53:14 door Frank Nietbelangrijk
 
Roel -

Roel -

16/09/2015 21:27:00
Quote Anchor link
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.
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
<?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.

Toevoeging op 16/09/2015 21:29:09:

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.
 
DavY -

DavY -

16/09/2015 22:29:53
Quote Anchor link
@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.
Gewijzigd op 16/09/2015 22:31:02 door DavY -
 
Frank Nietbelangrijk

Frank Nietbelangrijk

16/09/2015 22:43:50
Quote Anchor link
Roel heb je mijn puntjes wel meegenomen want kolomnamen to en from gaan nooit werken!
Verder:
wat geeft

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
<?php
$entity
= $repository->find($id);
echo '<pre>';
print_r($entity);
exit;
?>
 
Roel -

Roel -

17/09/2015 15:22:45
Quote Anchor link
Ik heb de properties van zowel Ride als Route omgezet van 'private' naar 'protected'. Ook heb ik 'to' en 'fro' omgezet naar respectievelijk 'nameto' en 'fromto'. Daarna de cache geleegd. Nog steeds krijg ik de volgende foutmelding:
Runtime Notice: Accessing static property Proxies\__CG__\AppBundle\Entity\Route::$lazyPropertiesDefaults as non static
 
DavY -

DavY -

17/09/2015 15:26:25
Quote Anchor link
@Roel,

Heb je het ook geprobeerd met fetch="EAGER", nadat je properties omgezet had naar protected?
 
Roel -

Roel -

17/09/2015 16:07:29
Quote Anchor link
Hulde! Het werkt nu ik fetch="EAGER" heb toegevoegd. Eerder werkte dit niet. Ik ga straks uitzoeken wat er precies voor heeft gezorgd dat dit eerder niet werkte en nu wel.
Hartstikke bedankt allebei voor nu!
 
DavY -

DavY -

17/09/2015 16:32:24
Quote Anchor link
@Roel

Graag gedaan :) De reden waarom het niet werkte is omdat jij jouw properties op 'private' had staan.
 
Roel -

Roel -

17/09/2015 16:35:29
Quote Anchor link
Ik moet je helaas teleurstellen. Ik heb 'nameto' en 'fromto' teruggewijzigd naar'to' en 'from' en de protected properties weer private gemaakt. Het lijkt nog steeds te werken. Als ik fetch="EAGER" weghaal, dan gaat het weer fout. Zet ik het weer terug, dan gaat het weer goed.

Ik snap alleen nog steeds niet waarom het niet direct werkte toen ik fetch="EAGER" toevoegde. Dat ga ik straks nog eens nader onderzoeken.
 
DavY -

DavY -

17/09/2015 16:39:31
Quote Anchor link
@Roel,

Misschien omdat je eerst jouw cache niet opgeschoond had? Normaal hoort hij gewoon op 'protected' te staan, als je wilt serializen in Symfony, maar ik kan me natuurijk vergissen, want ik ben zelf eigenlijk nog maar een 'leerling' in Symfony :P. Het lukt nu in ieder geval en bleek fetch="EAGER" toch wel de juiste.
 
Roel -

Roel -

17/09/2015 17:21:54
Quote Anchor link
Ik heb het probleem gevonden! Deze stappen heb ik de eerste keer gevolgd:
http://symfony.com/doc/current/cookbook/doctrine/reverse_engineering.html

Toen kreeg ik dus een map Resources met mapping-informatie. Toen ik stap voor stap alles ging nalopen, kwam ik erachter dat nadat ik deze map verwijderde, het probleem ook niet meer voorkwam. Het blijkt dus dat ik in het bijbehorende XML-bestand ook fetch="EAGER" moest toevoegen aan de relatie met Route.

Kan iemand mij vertellen waarom ik dan nu nog steeds annotations bij m'n klassen heb?

Toevoeging op 17/09/2015 17:22:39:

Gelijk even geprobeerd de annotations weg te halen. Het lijkt nog steeds te werken. Wat is het nut van deze annotations nu nog?
 
Frank Nietbelangrijk

Frank Nietbelangrijk

17/09/2015 17:27:46
Quote Anchor link
Blijkbaar is er voor gekozen om XML en annotations aan te maken? Annotations worden het meest gebruikt icm met Doctrine maar je mag uiteindelijk zelf kiezen wat je prettig vindt. Ik vind zelf het fijne aan annotations dat je geen apart config file hoeft te openen maar dat ze gewoon bij je properties staan en zo ook met de routes bij je Action methods in de controllers.
 
Roel -

Roel -

17/09/2015 18:03:50
Quote Anchor link
Ik geef zelf ook de voorkeur aan annotations, om dezelfde reden als jij.
In de tutorial wordt echter standaard XML gebruikt en krijg je een tip als je YAML wil gebruiken. Hoe zit dit dan voor annotations? Weet jij of en hoe dat eventueel kan?
 
Frank Nietbelangrijk

Frank Nietbelangrijk

17/09/2015 18:20:48
Quote Anchor link
annotations voor de serializer?

in config.yml:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
framework:
    serializer:      { enable_annotations: true }
 

Pagina: 1 2 volgende »



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.