Comments (9)
Howdy @raffcioo! I believe make:entity
is working as intended. If I create a new Me
entity with 2 properties:
I end up with (redacted non-relevant parts):
#[ORM\Entity(repositoryClass: MeRepository::class)]
class Me
{
#[ORM\Column(length: 255)]
private ?string $name = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $occupation = null;
public function getName(): ?string { }
public function setName(string $name): static
{
$this->name = $name;
return $this;
}
public function getOccupation(): ?string { }
public function setOccupation(?string $occupation): static
{
$this->occupation = $occupation;
return $this;
}
}
As you can see for name
the property itself is null
able (this is intended) by the column definition is basically the same as Column(nullable: false)
. As compared to the occupation
property - both the property type && the column definition are null
able.
Because both of the properties are private
and the only way to set or change the value of the properties is via the set
methods. Adding the argument type ?
to a setName(string $name)
wouldn't make much sense here - the property cannot be null when persisting the entity. But on the other hand, setOccupation(?string $occupation)
is perfectly acceptable because the column definition allows nullable: true
.
Just a "pro tip" - for simple forms & entities - adding the assertions to the entity directly can help alot. Symfony's form validator is able to look at the entity and see this assertion when a user submits a form. By doing it like this - the property declaration, column definition, and form validation are all in the same spot
// Entity
#[Assert\NotBlank()]
#[ORM\Column(length: 255)]
private ?string $name = null;
I hope this helps, let me know if you are still having issues are need any further help!
Sidenote: checkout https://symfonycasts.com/ - we have a gazillion tips, tricks, and awesome tutorials over there on how to be a Symfony Jedi Master :D
from maker-bundle.
Hi @jrushlow, thank you for response. It is corrent that make:entity
do setters correctly according to what we select, nullable or not. But the question is is it correct in general. To reproduce what I meant...
- using make:entity make simple entity with one field string, not nullable
- make simple form with NotBlank validator attached to this field
- submit this form with empty value
result:
HTTP 500. InvalidArgumentException. Expected argument of type "string", "null" given.
expected result:
HTTP 422, page loads and user can see the form with a message that this field cannot be blank.
fix:
add ?
so method can accept null so the validator can work... I just think/thought that this ?
is just missing and should be there by default added by make:entity.
from maker-bundle.
Hmm, I'm not seeing a 500
error when submitting a form with missing, blank, or null values when a string
is expected. - I'm getting the expected 422
response & associated validation error.
I have a simple app that I use for testing - https://github.com/jrushlow/app-linked/tree/maker/1513 which recreates what is described above. Try creating a PR (based of off the maker/1513
branch) that reproduces the error you're seeing. I think there is something else going one that is causing the 500
error for you. Without seeing the code and the associated stack trace for the error - it's hard to pin point whats going on.
But to answer your question - for setter methods - the only time null
should be accepted is if null
can be persisted on the entity. (Granted there are edge cases when your entity logic allows for null
- but that's outside the scope of this simple example)
private ?string $notNullableInDatabase = null;
public function setNotNullableInDatabase(string $value);
private ?string $canBeNullInDatabase = null;
public function setCanBeNullInDatabase(?string $value);
As an afterthought - double check your migrations are up to do.. bin/console d:m:status
-> bin/console m:migration
-> bin/console d:m:m
from maker-bundle.
I just made the testing :) created myself what I wrote above, trying to reproduce, in clean environment, and surprise... I got HTTP422. Wow... thats imposible I thought :) So... I kept digging... And... try in Controller firstly load existing entity, then put it into that form, and then show to the user. When user cleans that field and submit that field empty then the HTTP500 occurs.
from maker-bundle.
So updated how to reproduce list looks like this:
- create Symfony project
- using make:entity make simple entity with one field string, not nullable
- make migration, migrate, add one example record to the database
- make form with NotBlank validator attached to that field
- in Controller load that created test entity from database, put it into that form, and show to the user
- clear original form field data and submit it empty
result:
HTTP500, expected HTTP422
from maker-bundle.
It is thrown in: $form->handleRequest($request);
Using symfony console make:entity I have created Test entity which has only one field name (not nullable string) and in database I have one record with id 1 where that name has example value. In this example below I am autowiring but it does not matter. When I get just int id and do ->find(1) myself it is the same result. I also have TestType form where at name field I have NotBlank constraint set and that form has defaults 'data_class' => Test::class.
#[Route('/edit/{id<\d+>}')]
public function edit(Test $test, Request $request): Response
{
$form = $this->createForm(TestType::class, $test);
$form->handleRequest($request); // here is that exception thrown on POST request after form submit
//that is not even executed
if ($form->isSubmitted()) {
if ($form->isValid()) {
//...
- I run in web brower /edit/1
- I have form with one field with some tekst
- I clear that form field
- I click submit
- I am getting HTTP500 response
from maker-bundle.
This is happening only on edit/update so to notice it we have to send existing (not new) Entity object in form to the user with correct not null data (field string, not nullable) and wait for user to return it empty.
User submits form and sends POST request with that field data (null) on field (string, not nullable). Symfony firstly instantiates that form and tries to populate received POST data to attached underlying Entity object which previously had a different value (taken from db vs taken from request). So it tries to change that and put NULL there. But how Symfony can populate NULL if setter of that object that it tries to use do not accept NULL? It can't and it throws HTTP500 string expected, got null.
When we add ?
to the setter then HTTP500 is not happening. Validators can work. And we get correct in that case HTTP422 response.
from maker-bundle.
For me this is clearly a kind of bug because if someone new came to Symfony and do everything correctly and according to official documentation he shouldn't but eventually will get this HTTP500 and probably this will happen on production because he do not catch this earlier. I hope someone can reproduce it and write here because that thing does not want leave me alone :) I may be wrong with details about internal Symfony workings I wrote above because I am not that much into it yet, and in general I am new, sorry for my buggy English. Regards.
from maker-bundle.
This is what I am doing exacly. I can't describe it better:
-
symfony new test_project --version="7.0.*" --webapp
-
open this project in editor and run: symfony serve
-
symfony console make:entity
- Class name of the entity to create or update: Test
- Add the ability to broadcast entity updates using Symfony UX Turbo? no
- New property name: name
- Field type: string
- Field length: 255
- Can this field be null in the database (nullable): no
(press enter to quit, no more fields, just this one above)
- symfony console make:form
- The name of the form class: TestType
- The name of Entity or fully qualified model class name that the new form will be bound to (empty for none): Test
It generated form class:
class TestType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('name')
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Test::class,
]);
}
}
I add constraint to name field because it cannot be blank, so:
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('name', TextType::class, [
'constraints' => [
new NotBlank(),
],
])
;
}
-
In .env file I set up correct DATABASE_URL with database name: test.
-
symfony console doctrine:database:create
-
symfony console make:migration
-
symfony console doctrine:migrations:migrate
-
I insert into test database test table one row where name is raffcioo, so I have one record with id 1.
-
symfony console make:controller
- Choose a name for your controller class: MainController
I update created controller, i need only one method to edit my existing in database entity:
namespace App\Controller;
use App\Entity\Test;
use App\Form\TestType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class MainController extends AbstractController
{
#[Route('/edit/{id<\d+>}', name: 'app_main_edit', methods: ['GET', 'POST'])]
public function edit(Test $test, Request $request): Response
{
$form = $this->createForm(TestType::class, $test);
$form->handleRequest($request);
// here normally are $form->isSubmitted() and $form->isValid() checks
// but I do not even write them here in this example because that unwanted exception
// is happening on POST request in that method above and this would not be executed anyway
return $this->render('main/edit.html.twig', [
'form' => $form,
]);
}
}
I also update main/edit.html.twig view. It have only this in that template:
{{ form_start(form, {'attr': {'novalidate': 'novalidate'} }) }}
{{ form_row(form.name) }}
<button type="submit">Submit</button>
{{ form_end(form) }}
NOW:
-
I go to web browser and try to edit that existing entity I added before, so i run /edit/1 and I have on screen form with one name field with value raffcioo.
-
I clear that field, so it is empty.
-
I hit submit button.
RESULT:
HTTP 500 Internal Server Error
TypeError InvalidArgumentException
Expected argument of type "string", "null" given at property path "name".
in: $form->handleRequest($request);
When I add ? to Test entity setName setter, so I allow null, this above exception do not happen, I have correct behaviour with HTTP422 response with: This value should not be blank.
from maker-bundle.
Related Issues (20)
- [make:entity] addGetter on boolean field that starts with "is" HOT 1
- [make:entity] `generate()` call to `is_string()` appears to always evaluate to `false`
- Critical error: ClassSourceManipulator HOT 4
- [make:entity] Exception in DoctrineHelper.php HOT 2
- Why is the registration confirmation link (verify-email-bundle) not working in Symfony 6 ? HOT 8
- [make:auth] V1.59 - Deprecated classes causes deprecated message on each page HOT 1
- [make:entity] no more autocompletion on repository methods HOT 1
- Use final classes
- Deprecation : symfony/maker-bundle v1.59.0 HOT 1
- PHPStan - User::getPassword()
- PHPStan - ResetPasswordRequest::getUser()
- [make:crud] Add support for dynamic CSRF id with Expression in `#[IsCsrfTokenValid]`
- [make:crud] Allow `EntityValueResolver` to return a list of entities
- [make:registration-form] Add `hash_property_path` option to `PasswordType` HOT 1
- [make:reset-password] Add `hash_property_path` option to `PasswordType` HOT 1
- [make:entity] Entity Names Should Be Allowed to Have Digits (i.e. v1) HOT 1
- [make:entity] default value
- [make:entity] Maker modifies vendor files if FQCN covers up local alias HOT 2
- Feature Request: Allow custom Generator class in MakerInterface
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from maker-bundle.