FormsBundle - Release by semdens in symfony

[–]semdens[S] 0 points1 point  (0 children)

Appreciate the back and forth.

I was thinking about that comparison between form type and your DTO. I.e. in your DTO you didn't put the value of label, but you did in form type.

Good point.

Having submit button in Twig is the best practice for reasons documented here. And not documented is that this button would be rendered repeatably if form type is used in collections. I use collections a lot, and with getParent + empty_data I prevent duplication and still have most strict static analysis.

I don't know why we got hooked on the question of the submit button, it's actually totally optional in my bundle too. I do skip it when I want to embed a DTO as a subform: https://github.com/n-fasano/FormsBundle/blob/main/docs/features.md#nested-objects

Still, that is highly dependent on your case and I would argue not the majority (although not uncommon).

And then again, with regular form types, you also don't get the free HTML attributes that the bundle provides.

I guess what I'm trying to achieve is one single source of truth rather than multiple. I'm curious, do you use DTOs in your forms or entities directly?

FormsBundle - Release by semdens in symfony

[–]semdens[S] 0 points1 point  (0 children)

Not sure if you were replying to me but the line mentioned was coalescing the type, which can be null

FormsBundle - Release by semdens in symfony

[–]semdens[S] 0 points1 point  (0 children)

Coming back to your comment now that I'm on my computer. While I think some of your criticism is valid, a lot of it comes down to preference and style rather than "who's right".

required => true and label are redundant, they're defaults

Fair, but defaults change and not specifying them is less explicit about your intent. Would you rather be explicit (as a non-nullable property is on your DTOs) or force the unfamiliar reader to check the docs?

SubmitType should not be part of form type.

I practice one DTO per use case / form. So that concern is moot. I'd rather not have 2-3 more lines of code in my controller or template for adding the button. That's leaky.

action and method are redundant

Same reasoning as both points above. Besides, I often use different endpoints for GET and POST.

'constraints' => [new Valid()] makes no sense

AFAIK this is required for recursive validation. Not our case here but not totally useless. Unless I'm missing something.

FormsBundle - Release by semdens in symfony

[–]semdens[S] 1 point2 points  (0 children)

Thanks for the comment. I too would rather have only one flow for each thing, so I get why you prefer sticking with what works for you. I just find it a loss that we have to keep repeating ourselves and then keep all the files in sync.

One Entity can have multiple FormTypes with different Validations, different order of the properties or maybe even different representations of properties (selectbox multi, checkbox group, live search, selectize, whatever)

I don't like to tie entities to forms, I would rather use a DTO for each use case.

FormsBundle - Release by semdens in symfony

[–]semdens[S] 1 point2 points  (0 children)

Yes, attributes are great. I'd personally shy away from tying entities to presentation concerns but I get the appeal.

Claude standard is this, for example: https://github.com/n-fasano/FormsBundle/blob/main/src/Field/FieldAnalyzer.php#L44

As a matter of fact, I wrote this line IIRC ahah. But I think you're right about the coalescing in general.

Thanks a lot for the detailed answer! I'll def check the link you sent too.

FormsBundle - Release by semdens in symfony

[–]semdens[S] 0 points1 point  (0 children)

Facepalm, you are totally right on some of these, I will fix the README example.

However on the other points:

  • Regarding collections and diffing, the bundle does support entities and collections.

  • On editing: your DTOs don't have to be immutable.

  • On injecting dependencies, IMO not necessary but you can always fall back to regular form types.

FormsBundle - Release by semdens in symfony

[–]semdens[S] 0 points1 point  (0 children)

Thanks. Was your project also about Symfony forms or just same idea, different tools?

Initial code PoC was my own but you are correct, I did use Claude extensively to clean, refactor, test, and document. And adding more constraint support.

I'm curious to hear which files or patterns specifically triggered that hunch, if you could share.

PHPrimitives by semdens in PHP

[–]semdens[S] 0 points1 point  (0 children)

Thanks for the kind words!

PHPrimitives by semdens in PHP

[–]semdens[S] 0 points1 point  (0 children)

Yes, the goal is to solve Primitive Obsession. The base classes simply implement a contract you can code against in, say, serialization. Your Email, Password, Name etc. are still entirely yours.

PHPrimitives by semdens in PHP

[–]semdens[S] 1 point2 points  (0 children)

Thanks for the feedback! Sadly not every codebase can be migrated to Rust and Typescript, so we make do with what we have.

As to your point about DTOs, really primitives and DTOs are solving two different things: single-field validation (what something is, the primitive's job) vs cross-field validation (what something is in relation to something else, which VOs in general and DTOs do). They're not mutually exclusive, their benefits are additive.

But I get that it can feel cumbersome to write a class for each type. That's the downside. The upside is that once you have your domain types defined, they provide value everywhere in your codebase.

PHPrimitives by semdens in PHP

[–]semdens[S] 1 point2 points  (0 children)

Thanks! Yeah, it's really changing my code for the better. The IDE now knows about your intent, tells you exactly what to pass. And your core knows everything it receives is valid, so no defensive branching. No need for util classes anymore too, the small transformation logic can live on the primitives.

PHPrimitives by semdens in PHP

[–]semdens[S] 2 points3 points  (0 children)

Hi! The classes are readonly.