Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add transformation support #156

Merged
merged 4 commits into from
Aug 7, 2024
Merged

Conversation

emenkens
Copy link
Contributor

@emenkens emenkens commented Jul 29, 2024

I thought it would be nice to be able to make changes to input before it gets validated.

Problem

Suppose you want to trim user input before it's validated. We start off with a basic prompt to ask for a username:

$username = text(
    label: 'Please select a username:',
    required: true,
);

If I enter string(8) " " (8 spaces), that's a totally valid username. This could of course be solved with validation, so let's add a validation rule to make sure that the username, when trimmed, is at least 4 characters:

$username = text(
    label: 'Please select a username:',
    required: true,
    validate: fn (string $value) => strlen(trim($value)) < 4 ? 'Too short!' : '',
);

And enter string(8) " ssss " (2 spaces, and the letter s 4 times, followed by 2 more spaces). The validation logic above trims the string and agrees that string(4) "ssss" is a valid username. However, that's not the input we entered...

The trim function was called inside the validation logic, which means the value of $username will still be string(8) " ssss ". This could be resolved with more advanced validation logic, like not allowing a string to start and end with a space etc., but this can become unmanageable pretty fast.

We could of course wrap all of the code above in a trim():

$username = trim(text(
    ...
));

but now I have repeated myself and have to remember to change the code every time the validation logic changes. This can be tedious when working with large form sets, especially if there are multiple developers working on the same codebase.

Solution

In this PR, I have added a transform option, which accepts a Closure and can be used like this:

$username = text(
    label: 'Please select a username:',
    transform: fn ($value) => trim($value),
    validate: fn (string $value) => strlen($value) < 4 ? 'Too short!' : '',
);

This will alter the value before validation takes place, which means I don't need to repeat myself, and I know for sure that the value that is assigned to $username is the same value that was being validated.

This could be super useful not only for trimming strings, but also to filter out other kinds of unwanted characters, like spaces in a phone number or hyphens in a UUID. It can also be used with the Str helpers:

use Illuminate\Support\Str;

$slug = text(
    label: 'Please enter a slug for your blog post:',
    transform: fn ($value) => Str::slug($value),
    validate: ...
);

All input types are supported and I've added tests for each type. Let me know what you think!

Thank you

Copy link

Thanks for submitting a PR!

Note that draft PR's are not reviewed. If you would like a review, please mark your pull request as ready for review in the GitHub user interface.

Pull requests that are abandoned in draft may be closed due to inactivity.

@emenkens emenkens marked this pull request as ready for review July 29, 2024 15:06
@taylorotwell taylorotwell marked this pull request as draft August 1, 2024 18:35
Copy link
Member

@jessarcher jessarcher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thanks!

@jessarcher jessarcher marked this pull request as ready for review August 1, 2024 23:40
@macocci7
Copy link
Contributor

macocci7 commented Aug 2, 2024

I think that src/FormBuilder.php also needs to be updated.

@taylorotwell
Copy link
Member

@emenkens does FormBuilder need to be updated? Please mark as ready for review when the requested changes have been made.

@taylorotwell taylorotwell marked this pull request as draft August 5, 2024 14:26
@emenkens
Copy link
Contributor Author

emenkens commented Aug 7, 2024

@taylorotwell it does indeed! Thank you @macocci7 for pointing that out. I've updated it now.

@emenkens emenkens marked this pull request as ready for review August 7, 2024 14:20
@taylorotwell taylorotwell merged commit 72e5035 into laravel:main Aug 7, 2024
4 checks passed
@emenkens emenkens deleted the transformations branch August 7, 2024 14:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants