[Symfony] Beoordelen van Registerpagina

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

DavY -

DavY -

12/09/2015 15:39:23
Quote Anchor link
Ik ben Symfony al een tijdje aan het leren en ik heb de basis redelijk goed te pakken, dus ben ik gaan oefenen met een 'register' pagina en dat verloopt naar behoren. Toch zou ik graag mijn code willen laten beoordelen door Symfony-kenners, want het kan namelijk altijd beter of hoort er iets niet op zijn plaats, dus kritiek en tips zijn van harte welkom, al is het natuurlijk niet helemaal af.

Signup.php (Entity):
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
<?php
// src/AppBundle/Entity/Signup.php
namespace AppBundle\Entity;

use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use EWZ\Bundle\RecaptchaBundle\Validator\Constraints as Recaptcha;
use Doctrine\ORM\Mapping as ORM;
/**
 * @ORM\Entity
 * @ORM\Table(name="users")
 * @UniqueEntity("username", message = "Gebruikersnaam is al in gebruik.")
 * @UniqueEntity("email", message = "Emailadres is al in gebruik.")
 */

class Signup
{
   /**
    * @ORM\id
    * @ORM\Column(type="integer")
    * @ORM\GeneratedValue(strategy="AUTO")
    */

    protected $id;
    /**
     * @var string $username
     * @ORM\Column(name="username", type="string", length=100, nullable=false, unique=true)
     */

    protected $username;
    /**
     * @var string $email
     * @ORM\Column(name="email", type="string", length=255, nullable=false, unique=true)
     */

    protected $email;
    /**
     * @var string $firstname
     * @ORM\Column(name="firstname", type="string", length=255, nullable=false)
     */

    protected $firstname;
    /**
     * @var string $lastname
     * @ORM\Column(name="lastname", type="string", length=255, nullable=false)
     */

    protected $lastname;
    /**
     * @var string $gender
     * @ORM\Column(name="gender", type="string", length=100, nullable=false)
     */

    protected $gender;
    /**
     * @var date $birthday
     * @ORM\Column(name="birthday", type="date", length=100, nullable=false)
     */

    protected $birthday;
    /**
     * @var string $password
     * @ORM\Column(name="password", type="string", length=255, nullable=false)
     */

    protected $password;
    /**
     * @var \DateTime $regdate
     * @ORM\Column(name="regdate", type="datetime", length=255, nullable=false)
     */

    protected $regdate;
    /**
    * @Recaptcha\IsTrue
    */

    public $recaptcha;
    
    public static function loadValidatorMetadata(ClassMetadata $metadata)
    {

        // Gebruikersnaam
        $metadata->addPropertyConstraint('username', new Assert\NotBlank(array(
            'message' => 'Gebruikersnaam is verplicht.'
            ))
        );

        $metadata->addPropertyConstraint('username', new Assert\Length(array(
            'min' => 2,
            'max' => 20,
            'minMessage' => 'Gebruikersnaam moet minimaal {{ limit }} karakters lang zijn.',
            'maxMessage' => 'Gebruikersnaam mag maximaal {{ limit }} karakters lang zijn.'
            ))
        );

        $metadata->addPropertyConstraint('username', new Assert\Regex(array(
            'pattern' => '/^[a-zA-Z0-9_-|]+$/i',
            'message' => '{{ value }} is niet geldig. Toegestane karakters: _ - |'
            ))
        );

        
        // Email
        $metadata->addPropertyConstraint('email', new Assert\NotBlank(array(
            'message' => 'Emailadres is verplicht.'
            ))
        );

        $metadata->addPropertyConstraint('email', new Assert\Email(array(
            'message' => "{{ value }} is geen geldige emailadres.",
            'checkMX' => true
            ))
        );

        
        // Voornaam
        $metadata->addPropertyConstraint('firstname', new Assert\NotBlank(array(
            'message' => 'Voornaam is verplicht.'
            ))
        );

        $metadata->addPropertyConstraint('firstname', new Assert\Length(array(
            'min' => 2,
            'max' => 25,
            'minMessage' => 'Voornaam moet minimaal {{ limit }} karakters lang zijn.',
            'maxMessage' => 'Voornaam mag maximaal {{ limit }} karakters lang zijn.'
            ))
        );

        $metadata->addPropertyConstraint('firstname', new Assert\Regex(array(
            'pattern' => '/^[a-zA-Z0-9_-|]+$/i',
            'message' => '{{ value }} is niet geldig. Toegestane karakters: _ - |'
            ))
        );

        
        // Achternaam
        $metadata->addPropertyConstraint('lastname', new Assert\NotBlank(array(
            'message' => 'Achternaam is verplicht.'
            ))
        );

        $metadata->addPropertyConstraint('lastname', new Assert\Length(array(
            'min' => 2,
            'max' => 25,
            'minMessage' => 'Achternaam moet minimaal {{ limit }} karakters lang zijn.',
            'maxMessage' => 'Achternaam mag maximaal {{ limit }} karakters lang zijn.'
            ))
        );

        $metadata->addPropertyConstraint('lastname', new Assert\Regex(array(
            'pattern' => '/^[a-zA-Z0-9_-| ]+$/i',
            'message' => '{{ value }} is niet geldig. Toegestane karakters: _ - |'
            ))
        );

        
        // Geslacht
        $metadata->addPropertyConstraint('gender', new Assert\Choice(array(
            'message' => 'Kies een geldige geslacht.',
            'choices' => array('male', 'female')
            ))
        );

        
        // Geboortedatum
        $metadata->addPropertyConstraint('birthday', new Assert\Date(array(
            'message' => 'Deze geboortedatum is niet geldig'
            ))
        );

        
        // Wachtwoord
        $metadata->addPropertyConstraint('password', new Assert\NotBlank(array(
            'message' => 'Wachtwoord is verplicht.'
            ))
        );

        $metadata->addPropertyConstraint('password', new Assert\Length(array(
            'min' => 5,
            'max' => 25,
            'minMessage' => 'Wachtwoord moet minimaal {{ limit }} karakters lang zijn.',
            'maxMessage' => 'Wachtwoord mag maximaal {{ limit }} karakters lang zijn.'
            ))
        );

        $metadata->addPropertyConstraint('password', new Assert\Regex(array(
            'pattern' => '/^[a-zA-Z0-9_-|]+$/i',
            'message' => 'Wachtwoord is niet geldig. Toegestane karakters: _ - |'
            ))
        );
    }


    public function getId()
    {

        return $this->id;
    }

    
    public function setId($id)
    {

        $this->id = $id;
    }

    
    public function getUsername()
    {

        return $this->username;
    }


    public function setUsername($username)
    {

        $this->username = $username;
    }


    public function getEmail()
    {

        return $this->email;
    }


    public function setEmail($email)
    {

        $this->email = strtolower($email);
        return $this;
    }

    
    public function getFirstname()
    {

        return $this->firstname;
    }

    
    public function setFirstname($firstname)
    {

        $this->firstname = $firstname;
    }

    
    public function getLastname()
    {

        return $this->lastname;
    }

    
    public function setLastname($lastname)
    {

        $this->lastname = $lastname;
    }

    
    public function getGender()
    {

        return $this->gender;
    }

    
    public function setGender($gender)
    {

        $this->gender = $gender;
    }

    
    public function getBirthday()
    {

        return $this->birthday;
    }

    
    public function setBirthday(\DateTime $birthday = null)
    {

        $this->birthday = $birthday;
    }

    
    public function getPassword()
    {

        return $this->password;
    }

    
    public function setPassword($password)
    {

        $this->password = $password;
    }

    
    public function getRegdate()
    {

        return $this->regdate;
    }

    
    public function setRegdate(\DateTime $regdate = null)
    {

        $this->regdate = $regdate;
    }
}

?>


SignupController.php (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
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<?php
// src/AppBundle/Controller/SignupController.php
namespace AppBundle\Controller;

use AppBundle\Entity\Signup;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use EWZ\Bundle\RecaptchaBundle\EWZRecaptchaBundle;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;

class SignupController extends Controller
{
    /**
    * @Route("/signup/", name="signup")
    */

    public function indexAction(Request $request)
    {

        $signup = new Signup();

        $form = $this->createFormBuilder($signup, array('required' => false))
            ->
add('username', 'text', array('label' => 'Gebruikersnaam'))
            ->
add('email', 'email', array('label' => 'Emailadres'))
            ->
add('firstname', 'text', array('label' => 'Voornaam'))
            ->
add('lastname', 'text', array('label' => 'Achternaam'))
            ->
add('gender', 'choice', array(
                    'choices'  => array(
                        'male' => 'Man',
                        'female' => 'Vrouw'
                        )
                    )
                )
            ->
add('birthday', 'date', array(
                    'label' => 'Geboortedatum',
                    'format' => 'dd-MMM-yyyy',
                    'years' => range(date('Y')-16, 120)
                    )
                )
            ->
add('password', 'repeated', array(
                  'type' => 'password',
                  'invalid_message' => 'Wachtwoord komen niet overeen.',
                  'options' => array('attr' => array('class' => 'password-field')),
                  'first_options'  => array('label' => 'Wachtwoord'),
                  'second_options' => array('label' => 'Bevestig wachtwoord')))
            ->
add('recaptcha', 'ewz_recaptcha', array(
                    'label' => 'Beveiligingscode',
                    'attr' => array(
                        'options' => array(
                            'theme' => 'white',
                            'type' => 'image'
                            )
                        )
                    )
                )
            ->
add('save', 'submit', array('label' => 'Opslaan'))
            ->
getForm();
            
        $form->handleRequest($request);
        
        if($request->isMethod('POST'))
        {

            if ($form->isValid())
            {

                $hash = new MessageDigestPasswordEncoder('sha512', true, 5000);
                
                $signup->setUsername($form["username"]->getData());
                $signup->setEmail($form["email"]->getData());
                $signup->setFirstname($form["firstname"]->getData());
                $signup->setLastname($form["lastname"]->getData());
                $signup->setGender($form["gender"]->getData());
                $signup->setBirthday($form["birthday"]->getData());
                $signup->setPassword($hash->encodePassword($signup->getPassword(), $signup->getUsername()));
                $signup->setRegdate(new \DateTime('now'));
                
                $em = $this->getDoctrine()->getManager();
                $em->persist($signup);
                $em->flush();
                
                return $this->redirectToRoute('success');
            }    
        }

        return $this->render('signup/signup.html.twig', array('form' => $form->createView()));
    }

    
    /**
    * @Route("signup/success/", name="success")
    */

    public function successAction(Request $request)
    {

        return new Response('Dit was een success!');
    }
}

?>


Twig:
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
{# app/Resources/views/signup/signup.html.twig #}
{% extends 'base.html.twig' %}
{% block body %}
<fieldset>
<legend>Registreren</legend>
    {{ form_start(form) }}
    {{form_label(form.username)}} {{form_widget(form.username)}}<br />
    {{ form_errors(form.username) }}
    {{form_label(form.email)}} {{ form_widget(form.email) }}<br />
    {{ form_errors(form.email) }}
    {{form_label(form.firstname)}} {{ form_widget(form.firstname) }}<br />
    {{ form_errors(form.firstname) }}
    {{form_label(form.lastname)}} {{ form_widget(form.lastname) }}<br />
    {{ form_errors(form.lastname) }}
    {{form_label(form.gender)}} {{ form_widget(form.gender) }}<br />
    {{ form_errors(form.gender) }}
    {{form_label(form.birthday)}}
    {{ form_widget(form.birthday.day) }}
    {{ form_widget(form.birthday.month) }}
    {{ form_widget(form.birthday.year) }}<br />
    {{ form_errors(form.birthday) }}
    {% for passwordField in form.password %}
        {{ form_label(passwordField, null, { 'attr': {'class': 'form-label'} }) }}
        {{ form_widget(passwordField, { 'attr': {'class': 'form-input'} }) }}<br />
        {{ form_errors(passwordField) }}
    {% endfor %}
    {{ form_label(form.recaptcha) }} {{form_widget(form.recaptcha)}}<br />
    {{ form_widget(form.save) }}
    {{ form_end(form) }}
</fieldset>
{% endblock %}


Alvast bedankt iig!
 
PHP hulp

PHP hulp

11/12/2018 18:12:33
 
Frank Nietbelangrijk

Frank Nietbelangrijk

12/09/2015 20:58:05
Quote Anchor link
Ziet er zeker gezond uit Davy.

De dingetjes die mij opvallen zijn niet al te ernstig. Hier komen ze:

- Jammer dat je geen annotations gebruikt voor de validatie :-). Volgens mij zijn die toch min of meer wel de standaard geworden. (Ben benieuwd wat anderen hier van vinden)
- Noem die entity gewoon User en geen Signup
- Maak van email een type="email" in plaats van string
- bij Gender heb je aan een length=1 genoeg en zou je gewoon een M of een F kunnen wegschrijven in de database. (bij een Formulier gewoon even fieldtype="choice" gebruiken en de Entity een hulpfunctie geven die de volledige benamingen teruggeeft en die vanuit Twig gebruiken)
- Maak van $birthday liever $born (geboren op). Je wilt namelijk geboortedatums opslaan in je database.
- Ook hoeft een date of datetime geen length="" te hebben. Daarbij mis ik je constructor die alvast een DateTime object aanmaakt voor deze variabelen. Zeker bij regdate is dat wel heel erg handig.
- if($request->isMethod('POST')) is onnodig. if ($form->isValid()) Regelt dit al voor je.

p.s. Leuk dat je dit met ons deelt. Ik zie ook weer dingen die nieuw zijn voor mij.


Toevoeging op 12/09/2015 21:10:41:

Ook bouw je je formulier helemaal in je controller op. Het advies is om hier een aparte Class voor te gebruiken in de AppBundle/Form directory zoals hier beschreven.

Ook kun je een hoop van deze zaken een aanvang geven met de commandline.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
app/console doctrine:generate:entity // maak een nieuwe entity aan
app/console doctrine:generate:entities AppBundle // creert alle getters en setters voor je
app/console doctrine:schema:update --force // maak tabellen aan of wijzig deze in je database
app/console doctrine:generate:crud AppBundle:User // maakt een controller met CRUD (create, read, update en delete) Actions, formulieren en Twig templates.


De automatisch gegenereerde code is tevens ook erg leerzaam.
 
Wouter J

Wouter J

12/09/2015 22:31:51
Quote Anchor link
Offtopic:
Leuk al die Symfony topics tegenwoordig. Ik wordt er helemaal happy van :)


Ook ik heb een lijstje met dingetjes:

  • Zoals al genoemd door Frank zie ik geen rede waarom je de (toch wel minst gewaardeerde) PHP method gebruikt voor validatie, ipv annotations, Yaml of XML.
  • "@ORM\id" hoewel dit alles hoofdletter-ongevoelig is raad ik toch aan gewoon de hoofdletters te gebruiken zoals ze zijn: @ORM\Id
  • Naar mijn weten is nullable standaard false, dus het is overbodig dit telkens te herhalen.
  • Je bent een beetje dingen door elkaar aan het halen wat betreft het wachtwoord. Allereerst moet je niet zelf de password encoder gaan aanmaken, maar ipv de service gebuiken van symfony (zie docs). Op deze manier moet je de encoder configureren in je security.yml config.

    Daarnaast klopt het lengte verhaal niet helemaal. Ik raad je aan een "plainPassword" property in je entity toe te voegen. Deze property map je dan niet in Doctrine, zodat het niet wordt opgeslagen in de database. Je laat het formulier het wachtwoord in de plainPassword property stoppen en je doet dan de validatie die je nu hebt (al vraag ik me altijd af waarom je een max length zou willen). Vervolgens ga je na valideren plainPassword encoden en stop je deze in password, welke wordt opgeslagen in de database.

    Als laatst gebruik je nu een text column met string length 255. Dit is veel meer dan nodig, omdat sha512 max 128 characters lang is (dus length=128).
  • Je hebt nu setters en getters voor alle properties in de entity. Ik raad je aan om af te vragen of dit eigenlijk wel zo handig is. Zo lijkt het me helemaal niet wenselijk om het id aan te passen. T lijkt me ook dat de meeste properties verplicht zijn en dus eigenlijk in een constructor thuis horen. Je code lijkt je nu gemaakt te hebben om te werken met de Form component, maar wees er van bewust dat de Form component hele handige features heeft om met praktisch elk type model te kunnen werken (zie deze geweldige blogpost voor een uitleg).
  • Omdat je je $signup entity aan het formulier bind is het niet nodig om alle velden zelf naar een property te mappen na het verzenden. De Form component regelt dit voor je (moet je wel zorgen dat de eerste argument van ->add() overeen komt met de naam van de property, of je moet de property_path optie gebruiken)
  • <fieldset> wordt naar mijn idee gebruikt binnen een formulier, nu gebruik je hem erbuiten. Plaats dit na form_start() en t zal werken.
  • Ipv elk input veld apart te renderen raad ik aan een Form thema te gebruiken, veel makkelijker
  • Vergeet ook {{ form_rest(form) }} niet, je mist nu een heel belangrijke security feature: CSRF protection
  • successAction() heeft geen Request nodig, dus zou m ook gewoon uit je argumenten lijst halen
  • $recaptcha als onderdeel van je property lijkt me niet helemaal gewenst. Recaptcha is een functionaliteit van je formulier, niet van je User. Je User staat helemaal los van het form (een User wordt bijv. ook gewoon gemaakt vanuit de DB of gewoon als test data).
 
Frank Nietbelangrijk

Frank Nietbelangrijk

13/09/2015 09:31:03
Quote Anchor link
Wouter J op 12/09/2015 22:31:51:
Offtopic:
Leuk al die Symfony topics tegenwoordig. Ik wordt er helemaal happy van :)


Ik ook en zeer zeker ook met jouw feedback Wouter. Dank daar voor.

Offtopic:
Over die getters en setters moet ik nog wel even verwerken ben ik bang voor :-). Lijkt mij dat Davy dat nog wel even mag vergeten, met uitzondering van de setId() want die moet er gewoon uit.
Gewijzigd op 13/09/2015 09:31:36 door Frank Nietbelangrijk
 
DavY -

DavY -

13/09/2015 10:52:19
Quote Anchor link
Frank:
- Jammer dat je geen annotations gebruikt voor de validatie :-). Volgens mij zijn die toch min of meer wel de standaard geworden. (Ben benieuwd wat anderen hier van vinden)


Ik had eerst ook annotations gebruikt, maar dat ging me beetje te gemakkelijk en aangezien ik nog symfony aan het leren ben, wou ik ook goed begrijpen hoe Symfony werkte, dus koos ik ervoor om in php validaties te gaan schrijven, omdat ik dan in een soort 'ritme' komt, waardoor het lekker denkt en ook sneller leert begrijpen.

Frank:
- Noem die entity gewoon User en geen Signup


Ik had dat ook eerst overwogen, maar ik dacht dat ik dat beter kon doen voor login of kan ik voor login gewoon 'class in een class' schrijven, dus voor Entity en Controller?

Frank:
- Maak van email een type="email" in plaats van string
- bij Gender heb je aan een length=1 genoeg en zou je gewoon een M of een F kunnen wegschrijven in de database. (bij een Formulier gewoon even fieldtype="choice" gebruiken en de Entity een hulpfunctie geven die de volledige benamingen teruggeeft en die vanuit Twig gebruiken)
- Maak van $birthday liever $born (geboren op). Je wilt namelijk geboortedatums opslaan in je database.


Bedankt! Die tips zal ik zeker meenemen.

Frank:
- Ook hoeft een date of datetime geen length="" te hebben. Daarbij mis ik je constructor die alvast een DateTime object aanmaakt voor deze variabelen. Zeker bij regdate is dat wel heel erg handig.


Daar heb je inderdaad een punt! Zoals ik mijn code bekijkt, is al die 'set' eigenlijk onhandig, want dat zou ik even goed in een Constructor kunnen schrijven.

Frank:
Ook bouw je je formulier helemaal in je controller op. Het advies is om hier een aparte Class voor te gebruiken in de AppBundle/Form directory zoals hier beschreven.


Ik heb me nog niet helemeel verdiept in form opties van Symfony en wou fieldset erin hebben, wat dus eerst niet lukte, maar nu ik tips van Wouter daarover leest, ga ik me er eens meer in verdiepen, want het zou toch echt veel fijner zijn, als ik mijn form helemaal in Controller kan opbouwen.

Qua Commandline, moet ik me er ook meer in verdiepen, want dat heb ik nog niet helemaal te pakken.

Wouter:
"@ORM\id" hoewel dit alles hoofdletter-ongevoelig is raad ik toch aan gewoon de hoofdletters te gebruiken zoals ze zijn: @ORM\Id


Bedankt voor de tip! Maar wat voor de rest? Bijv, username, wachtwoord, etc? Moeten die dan ook allemaal in hoofdletters?

Wouter:
Naar mijn weten is nullable standaard false, dus het is overbodig dit telkens te herhalen.


Dat wist ik nog niet!

Wouter:
Je bent een beetje dingen door elkaar aan het halen wat betreft het wachtwoord. Allereerst moet je niet zelf de password encoder gaan aanmaken, maar ipv de service gebuiken van symfony (zie docs). Op deze manier moet je de encoder configureren in je security.yml config.

Daarnaast klopt het lengte verhaal niet helemaal. Ik raad je aan een "plainPassword" property in je entity toe te voegen. Deze property map je dan niet in Doctrine, zodat het niet wordt opgeslagen in de database. Je laat het formulier het wachtwoord in de plainPassword property stoppen en je doet dan de validatie die je nu hebt (al vraag ik me altijd af waarom je een max length zou willen). Vervolgens ga je na valideren plainPassword encoden en stop je deze in password, welke wordt opgeslagen in de database.

Als laatst gebruik je nu een text column met string length 255. Dit is veel meer dan nodig, omdat sha512 max 128 characters lang is (dus length=128).


Bedankt voor de tips! Ik had het eerst ook geprobeerd met plainPassword, maar daar kwam ik niet helemaal mee uit. Echter na je uitleg, begrijp ik nu beter hoe het werkt en ga ik me er straks meer in verdiepen.

Wouter:
Je hebt nu setters en getters voor alle properties in de entity. Ik raad je aan om af te vragen of dit eigenlijk wel zo handig is. Zo lijkt het me helemaal niet wenselijk om het id aan te passen. T lijkt me ook dat de meeste properties verplicht zijn en dus eigenlijk in een constructor thuis horen. Je code lijkt je nu gemaakt te hebben om te werken met de Form component, maar wees er van bewust dat de Form component hele handige features heeft om met praktisch elk type model te kunnen werken (zie deze geweldige blogpost voor een uitleg).
Omdat je je $signup entity aan het formulier bind is het niet nodig om alle velden zelf naar een property te mappen na het verzenden. De Form component regelt dit voor je (moet je wel zorgen dat de eerste argument van ->add() overeen komt met de naam van de property, of je moet de property_path optie gebruiken)
<fieldset> wordt naar mijn idee gebruikt binnen een formulier, nu gebruik je hem erbuiten. Plaats dit na form_start() en t zal werken.
Ipv elk input veld apart te renderen raad ik aan een Form thema te gebruiken, veel makkelijker


Klopt, constructor lijkt me in dit geval ook veel handiger. Ik was inderdaad teveel gericht op forms om alles op zijn plaats te krijgen, zoals ik het wou, maar ik heb me ook niet helemaal verdiept in form en mijn bedoeling is evengoed ook om forms helemaal op te bouwen vanuit controller. Bedankt voor de link Wouter, daar kan ik zeker heel wat mee!

Wouter:
Vergeet ook {{ form_rest(form) }} niet, je mist nu een heel belangrijke security feature: CSRF protection


Die kende ik nog niet en heb er ook niks overgelezen in docs van Symfony of ik moet hem gemist hebben. Uitgaande van de naam 'rest', print dat toch de rest van de forms uit of zie ik het verkeerd?

Wouter:
successAction() heeft geen Request nodig, dus zou m ook gewoon uit je argumenten lijst halen
$recaptcha als onderdeel van je property lijkt me niet helemaal gewenst. Recaptcha is een functionaliteit van je formulier, niet van je User. Je User staat helemaal los van het form (een User wordt bijv. ook gewoon gemaakt vanuit de DB of gewoon als test data).


Die tips neem ik mee, bedankt!

Offtopic:
Ik vind symfony zelf erg leuk om te leren en het is vrijwel snel te leren, mits je begrijpt hoe symfony werkt. Er zijn echter niet veel Nederlandse forums met gebruikers, die kennis hebben van Symfony en dat is best wel jammer, want het heeft toch de toekomst en op deze forum zie ik hooguit 3 personen die er wel kennis van hebben. Zo te zien heb je er al meer ervaring mee Wouter en is frank zelf ook nog aan het leren, maar frank is al wat verder dan ik, zo te merken :P. Bedankt dat jullie meedenken en opmerkingen plaatst. Die zijn altijd welkom!
 
Frank Nietbelangrijk

Frank Nietbelangrijk

13/09/2015 11:48:59
Quote Anchor link
>>Ik had dat ook eerst overwogen, maar ik dacht dat ik dat beter kon doen voor login of kan ik voor login gewoon 'class in een class' schrijven, dus voor Entity en Controller?

Ik zie nog niet wat je hier precies mee bedoelt. Ik heb zelf niet zo veel ervaring met een eigen loginsysteem voor symfony. Ik gebruik altijd de FOSUserBundle. Maar die Entity van jou slaat de gegevens op van één User dus noem je die dan toch ook gewoon zo? FosUserBundel gebruikt daarnaast een UserManager class..

>> Daar heb je inderdaad een punt! Zoals ik mijn code bekijkt, is al die 'set' eigenlijk onhandig, want dat zou ik even goed in een Constructor kunnen schrijven.

Voor regdate hoef je helemaal geen setter te hebben als ik er van uit mag gaan dat deze nooit meer veranderd.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
<?php
    function __construct()
    {

        $this->regdate = new \DateTime();   // zo de registratie datum is alvast ingevuld
        $this->born = new \DateTime('01-01-' . date('Y') - 20); // startpunt voor geboortedatum
    }
?>


>>Ik heb me nog niet helemeel verdiept in form opties van Symfony en wou fieldset erin hebben, wat dus eerst niet lukte, maar nu ik tips van Wouter daarover leest, ga ik me er eens meer in verdiepen, want het zou toch echt veel fijner zijn, als ik mijn form helemaal in Controller kan opbouwen.

Niet in de controller maar in een eigen class. Veel forms worden meer dan één keer gebruikt in je website. denk maar aan een NIEUW product toevoegen en een BESTAAND product bewerken.

>>Qua Commandline, moet ik me er ook meer in verdiepen, want dat heb ik nog niet helemaal te pakken.

Maak maar gewoon een nieuw project aan en kijk eens hoever je kan komen met de commandline om bovenstaande te maken. Echt een aanrader. Als je problemen ondervindt waardoor je de commando's niet kunt uitvoeren laat het dan even weten.

>>Bedankt voor de tip! Maar wat voor de rest? Bijv, username, wachtwoord, etc? Moeten die dan ook allemaal in hoofdletters?

Je zult in je meeste entities maar één Id (primary key) hebben ...


Offtopic:

Het aantal gebruikers groeit gestaagd...
 
Wouter J

Wouter J

13/09/2015 12:24:23
Quote Anchor link
DavY Blaat op 13/09/2015 10:52:19:
Ik had dat ook eerst overwogen, maar ik dacht dat ik dat beter kon doen voor login of kan ik voor login gewoon 'class in een class' schrijven, dus voor Entity en Controller?

Waarom niet gewoon dezelfde class hergebruiken? Zorg dan wel dat je Symfony\Component\Security\Core\User\UserInterface implement in je User entity, zodat Symfony Security er mee om kan gaan. Zie ook How to Load Security Users from the Database.

DavY Blaat op 13/09/2015 10:52:19:
Bedankt voor de tip! Maar wat voor de rest? Bijv, username, wachtwoord, etc? Moeten die dan ook allemaal in hoofdletters?

T ging hier om de annotation (@ORM\id vs @ORM\Id), properties kun je gewoon doen zoals je zelf wilt.

DavY Blaat op 13/09/2015 10:52:19:
Die kende ik nog niet en heb er ook niks overgelezen in docs van Symfony of ik moet hem gemist hebben. Uitgaande van de naam 'rest', print dat toch de rest van de forms uit of zie ik het verkeerd?

Inderdaad. De form builder, mits enabled, voegt een extra csrf token veld toe. Dit veld voorkomt CSRF attacks. Deze render je op het moment niet, dit wordt dan opgevangen door form_rest.
 
DavY -

DavY -

13/09/2015 12:52:32
Quote Anchor link
>>> Ik zie nog niet wat je hier precies mee bedoelt. Ik heb zelf niet zo veel ervaring met een eigen loginsysteem voor symfony. Ik gebruik altijd de FOSUserBundle. Maar die Entity van jou slaat de gegevens op van één User dus noem je die dan toch ook gewoon zo? FosUserBundel gebruikt daarnaast een UserManager class..

Ik ben bekend met FOSUserBundle, maar ik wil het zelf liever leren in plaats van andermans bundles te gebruiken, al is dat in sommige gevallen wel handig, echter, ik wil dus zelf uiteindelijk leren om eigen bundles te schrijven. De link wat Wouter gaf is daarmee dus perfect voor mij en er staat ook op dat pagina:

"Before you start, you should check out FOSUserBundle. This external bundle allows you to load users from the database (like you'll learn here) and gives you built-in routes & controllers for things like login, registration and forgot password. But, if you need to heavily customize your user system or if you want to learn how things work, this tutorial is even better."

Ik kies dus graag voor de laatste :P.

Qua commandline ga ik eens deze middag ermee oefenen, nog bedankt daarvoor.

>>> Waarom niet gewoon dezelfde class hergebruiken? Zorg dan wel dat je Symfony\Component\Security\Core\User\UserInterface implement in je User entity, zodat Symfony Security er mee om kan gaan. Zie ook How to Load Security Users from the Database.

Dat bedoelde ik met 'class in een class', dus zowel registeren, login, logout in 1 class. Dat pagina is echt super en dat zijn juist dat soort pagina's wat ik zoek, zodat ik de basis ervan zelf leert!

>> Inderdaad. De form builder, mits enabled, voegt een extra csrf token veld toe. Dit veld voorkomt CSRF attacks. Deze render je op het moment niet, dit wordt dan opgevangen door form_rest.

Als ik in firebug kijkt en ik doe het even zonder form_rest, dan zie ik alsnog csrf token, ook met form_rest, hoe kan dat dan?

Toevoeging op 13/09/2015 16:47:06:

Ik zit trouwens met een vervelend probleempje, waar ik niet mee uitkomt. Als ik secuirty.yml wilt wijzigen voor wachtwoord, zie: http://symfony.com/doc/current/book/security.html#security-encoding-password

Dan krijg ik steeds deze melding:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
Invalid type for path "security.encoders.cost". Expected array, but got integer


Het verwacht dus een array, maar mijn kennis met YAML is beperkt, waar ligt dit aan?
 



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.