susanBuck / e15-spring22

0 stars 0 forks source link

How to Validate and Customize data in one Creation Statement? #54

Closed patrickgarsow-harvard closed 2 years ago

patrickgarsow-harvard commented 2 years ago

I am having a difficult time understanding how to complete two separate tasks rather in the same statement or in any way possible.

I have my form collect data and process through my controller/store function. To store I used the <method>::create() I also use the Request::validate() to make sure the required fields and structure is there. from within that I want to use Str::slug() to auto create my slug.

Does anyone have any idea how I would do this?

public function store(Request $request)
    {
        Article::create(
            Request::validate([
             'name' => ['required'],
             'slug' => **<What do I do here?>**

           ])
         );

         return redirect('admin/articles/index');
    }
susanBuck commented 2 years ago

Hi @patrickgarsow-harvard -

If I'm understanding correctly what you're aiming for, here's what I would suggest:

public function store(Request $request)
{
    Request::validate([
        'name' => ['required']
    ]);

    Article::create([
        'name' => $request->name,
        'slug' => Str::slug($request->slug),
    ]);

    return redirect('admin/articles/index');
}

Let me know if this is what you're looking for...

gkorodi commented 2 years ago

Perhaps you could break it into multiple statements, and wrap it into a DB::beginTransaction() and DB::commit() or just a try {} catch () {} block.

It is easier to test and better separation of concerns, I think.

The validation should come before you touch anything in the database anyway, and if you are generating a slug, you don't really need to validate it. If you are sending the slug back from your form/request and need to validate it, I would venture into custom validation rules: https://www.esparkinfo.com/blog/laravel-custom-validation-rules.html

In any case, I would do

public function store(Request $request) {

      // If validation fails, it will redirect back to 
      // calling page. So we should not start DB transaction
      $request->validate([
        'name' => ['required'],
        'slug' => ['required', new SlugValidationRule],
      ]);

      // Now it is safe to create the record/row
      Article::create($request->all());
      return redirect('admin/articles/index');
    }
patrickgarsow-harvard commented 2 years ago

@susanBuck Thank you. I was letting the nesting of the functions get into my head. Sometimes consolidation is not the best approach... a simpler solution of separating out the two actions (validation and creation) just makes more sense.

@gkorodi Thank you as well as you opened my mind up to something else that I wasn't even considering as a possibility which is to validate that the slug is a slug and therefore can allow users to pick their own "custom" slug and if they enter nothing then I can generate one for them based off of the title.