# How to create a form with validation?

**URL:** <https://discourse.slimframework.com/t/how-to-create-a-form-with-validation/1456>\
**Category:** Questions\
**Created:** [April 30, 2017, 11:15am UTC](https://discourse.slimframework.com/t/how-to-create-a-form-with-validation/1456 "2017-04-30T11:15:41Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ctwx](https://avatars.discourse-cdn.com/v4/letter/c/71c47a/32.png) [@Ctwx](https://discourse.slimframework.com/u/Ctwx)\
**Post date:** [April 30, 2017, 11:15am UTC](https://discourse.slimframework.com/t/how-to-create-a-form-with-validation/1456/1 "2017-04-30T11:15:41Z")

</div>

Hello,

I am trying to create a form with Slim. I have These routes:

```
$app->get('/cats/new', '\CatController:new');
$app->post('/cats', '\CatController:create');

```

So the first one shows the input form and the second takes its input. The create method validates the input and should redirect back to the `new` route on errors.

I am not yet sure how to redirect those error Messages to the new route. As far as I know there’s `$response->withRedirect(<TARGET>)` but no way to add data.

How do I ideally structure those two methods? Should I just Show the form from within the create method? How do I pass the errors to `new` (to show them inside the form)?

Thank you in advance.

---

<div class="post-metadata">

**Author:** ![tflight](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/tflight/32/1205_2.png) [@tflight](https://discourse.slimframework.com/u/tflight)\
**Post date:** [April 30, 2017, 11:33am UTC](https://discourse.slimframework.com/t/how-to-create-a-form-with-validation/1456/2 "2017-04-30T11:33:46Z")

</div>

My method would look something like this:

```php
$cat = new Cat;
$cat->name = $request->getParsedBodyParam('name');
$cat->color = $request->getParsedBodyParam('color');
// in my Cat model, I have a validator method I'm calling in this example, but you could put it here instead
$validator = $cat->getValidator($cat);
if (!$validator->validate()) {
    $data [
      'cat' => $cat,
      'errors' => $validator->errors()
    ];
    return $this->view->render($response, 'cat/create.html.twig', $data); // errors available in view as `errors`
}
// All looks good, save the cat and redirect somewhere...

```

You can see another example of this in [akrabat’s slim-bookshelf example](https://github.com/akrabat/slim-bookshelf/blob/master/app/src/Bookshelf/AuthorController.php).

---

<div class="post-metadata">

**Author:** ![Ctwx](https://avatars.discourse-cdn.com/v4/letter/c/71c47a/32.png) [@Ctwx](https://discourse.slimframework.com/u/Ctwx)\
**Post date:** [April 30, 2017, 6:23pm UTC](https://discourse.slimframework.com/t/how-to-create-a-form-with-validation/1456/3 "2017-04-30T18:23:38Z")

</div>

Thanks for you Reply. So you put post and get in one method? Hmm… I was used to put them in different methods when I used Laravel. That’s why I thought I should Redirect.

OK, I’ll try that Approach. I combined get and post in my routes with `$app->map(['GET', 'POST'], '/cats/new', '\CatController:new');`

Thank you so far!

---

<div class="post-metadata">

**Author:** ![tflight](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/tflight/32/1205_2.png) [@tflight](https://discourse.slimframework.com/u/tflight)\
**Post date:** [April 30, 2017, 7:46pm UTC](https://discourse.slimframework.com/t/how-to-create-a-form-with-validation/1456/4 "2017-04-30T19:46:35Z")

</div>

No I don’t put both routes in one method. I do it pretty similar to Laravel with index, create, store, show, edit, update, and destroy methods.

I define my routes/controllers for a resource kind of like this.

```php
    $this->get('/users', ['App\Controllers\UsersController', 'index'])->setName('users.index');
    $this->get('/users/create', ['App\Controllers\UsersController', 'create'])->setName('users.create');
    $this->post('/users', ['App\Controllers\UsersController', 'store'])->setName('users.store');
    $this->get('/users/{userId}', ['App\Controllers\UsersController', 'show'])->setName('users.show');
    $this->get('/users/{userId}/edit', ['App\Controllers\UsersController', 'edit'])->setName('users.edit');
    $this->patch('/users/{userId}', ['App\Controllers\UsersController', 'update'])->setName('users.update');
    $this->delete('/users/{userId}', ['App\Controllers\UsersController', 'destroy'])->setName('users.destroy');

```

---

<div class="post-metadata">

**Author:** ![Ctwx](https://avatars.discourse-cdn.com/v4/letter/c/71c47a/32.png) [@Ctwx](https://discourse.slimframework.com/u/Ctwx)\
**Post date:** [April 30, 2017, 8:10pm UTC](https://discourse.slimframework.com/t/how-to-create-a-form-with-validation/1456/5 "2017-04-30T20:10:03Z")

</div>

Thank you for your answer.

Okay, so your code in your first answer was inside the store (POST) method? So you just show the create.html.twig in your create and store method? Like this:

```
public function create($request, $response)
{
    return $this->view->render($response, 'cat/create.html.twig', $data);
}

public function store($request, $response) 
{
    // your code from your first answer...
}

```

Right? I wasn’t sure if you called the template in both methods.

Thanks!

---

<div class="post-metadata">

**Author:** ![tflight](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/tflight/32/1205_2.png) [@tflight](https://discourse.slimframework.com/u/tflight)\
**Post date:** [April 30, 2017, 8:31pm UTC](https://discourse.slimframework.com/t/how-to-create-a-form-with-validation/1456/6 "2017-04-30T20:31:33Z")

</div>

I think so. 🙂 In my `create` method I call the create view like you showed. In my `store` method, if validation fails I return the create view with the (valid) old views as well as the error message. If validation passes I will redirect to various places depending on what is appropriate for the app… sometimes the index view, sometimes the show view, etc.

---

<div class="post-metadata">

**Author:** ![Ctwx](https://avatars.discourse-cdn.com/v4/letter/c/71c47a/32.png) [@Ctwx](https://discourse.slimframework.com/u/Ctwx)\
**Post date:** [April 30, 2017, 8:45pm UTC](https://discourse.slimframework.com/t/how-to-create-a-form-with-validation/1456/7 "2017-04-30T20:45:38Z")

</div>

Okay, thanks for clarification.

I now do it the same, but I don’t use `/cats` for the post route. I think it looks a bit weird if you where at `/cats/new` and suddenly you’re at ``/cats`.

---

<div class="post-metadata">

**Author:** ![tflight](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/tflight/32/1205_2.png) [@tflight](https://discourse.slimframework.com/u/tflight)\
**Post date:** [April 30, 2017, 9:29pm UTC](https://discourse.slimframework.com/t/how-to-create-a-form-with-validation/1456/8 "2017-04-30T21:29:58Z")

</div>

> [@Ctwx](#):
>
> I think it looks a bit weird if you where at /cats/new and suddenly you’re at /cats`.

I don’t think most users would notice, but I completely agree. Just haven’t changed the pattern in most of my apps.

---

<div class="post-metadata">

**Author:** ![Bibek](https://avatars.discourse-cdn.com/v4/letter/b/4491bb/32.png) [@Bibek](https://discourse.slimframework.com/u/Bibek)\
**Post date:** [October 8, 2017, 6:59am UTC](https://discourse.slimframework.com/t/how-to-create-a-form-with-validation/1456/9 "2017-10-08T06:59:36Z")

</div>

Hi tflight;

I have still a problem , how can I redirect to same page if validation failed. I am using a main.php which have two sections for login and for signup. I have used pagination for moving 1 to 2 or 2 to 1 section. In this case how can I redirect to same page if validation failed. I have used like this for log in :

$app-\>post(’/login’, function ($request, $response, $args) {  
// Sample log message  
$this-\>logger-\>info(“Slim-Skeleton ‘/’ route”);

// TODO:verify login information

// login validatuon page  
include\_once ‘lib/loginValidation.php’;

if ($validation){

```
  return $this->renderer->render($response, 'main.phtml', $args);

}else

return $this->renderer->render($response, 'index.phtml', $args);

```

});

validation codes are in loginValidation.php  
Thank you  
Regards

---

<div class="post-metadata">

**Author:** ![tflight](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/tflight/32/1205_2.png) [@tflight](https://discourse.slimframework.com/u/tflight)\
**Post date:** [October 8, 2017, 5:12pm UTC](https://discourse.slimframework.com/t/how-to-create-a-form-with-validation/1456/10 "2017-10-08T17:12:41Z")

</div>

> [@Bibek](#):
>
> how can I redirect to same page if validation failed.

I do something like this.

```php
if (!$validation) {
    return $response->withRedirect($this->router->pathFor('login'), 403);
}

```

---

<div class="post-metadata">

**Author:** ![Bibek](https://avatars.discourse-cdn.com/v4/letter/b/4491bb/32.png) [@Bibek](https://discourse.slimframework.com/u/Bibek)\
**Post date:** [October 9, 2017, 7:11am UTC](https://discourse.slimframework.com/t/how-to-create-a-form-with-validation/1456/11 "2017-10-09T07:11:06Z")

</div>

> [@tflight](#):
>
> pathFor

Thank you tflight ,

But I have single page with two section , how i redirect to same page same section of page if validation failed. it means I am using main.php which includes one section for login and other for signup , now i want to redirect the page to login if login validation failed . Could you please send me sample of files and structure.

Thank you

---

<div class="post-metadata">

**Author:** ![tflight](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/tflight/32/1205_2.png) [@tflight](https://discourse.slimframework.com/u/tflight)\
**Post date:** [October 9, 2017, 12:13pm UTC](https://discourse.slimframework.com/t/how-to-create-a-form-with-validation/1456/12 "2017-10-09T12:13:12Z")

</div>

You can route to different methods within a class in a couple of different ways, consult the [Container Resolution](https://www.slimframework.com/docs/objects/router.html#container-resolution) section of the documentation for full info, but here are some examples.

```php
$app->get('/', '\HomeController:home');
// routes to the home method of the HomeController class

$app->get('/', \HomeController::class . ':home');
// same as above, but in a different format

```

So in your example it might look something like this

```php
$app->get('/', '\MainController:login')->setName('login');
$app->get('/', '\MainController:signup')->setName('signup');

// or maybe you like this better

$app->get('/', \MainController::class . ':login'->setName('login'));
$app->get('/', \MainController::class . ':signup')->setName('signup');

```

---

<div class="post-metadata">

**Author:** ![Bibek](https://avatars.discourse-cdn.com/v4/letter/b/4491bb/32.png) [@Bibek](https://discourse.slimframework.com/u/Bibek)\
**Post date:** [October 18, 2017, 5:12am UTC](https://discourse.slimframework.com/t/how-to-create-a-form-with-validation/1456/13 "2017-10-18T05:12:06Z")

</div>

Dear tFlight

I am using respect/validation in my project , the following fatal error found :

Fatal error: Call to a member function setName() on string in C:\myproject\app\Validation\Validator.php on line 29

with codes

\<?php namespace App\Validation; use Respect\Validation\Validator as Respect; use Respect\Validation\Exceptions\NestedValidationException; class Validator { protected $errors; public function validate($request, array $rules) { foreach ($rules as $field =\> $rule) { try { $rule-\>setName(ucfirst($field))-\>assert($request-\>getParam($field)); } catch(NestedValidationException $e){ $this-\>errors[$field] = $e-\>getMessages(); } } When I try to remove setName(), it display same error for assert(), how can I Solve this . what happen in line 29? Please, have any solution ? Thank you . ![](https://canada1.discourse-cdn.com/flex030/uploads/slimframework/original/1X/677f06bdf711468707faf594c72c7993f90d2513.png)

---

<div class="post-metadata">

**Author:** ![tflight](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/tflight/32/1205_2.png) [@tflight](https://discourse.slimframework.com/u/tflight)\
**Post date:** [October 18, 2017, 12:19pm UTC](https://discourse.slimframework.com/t/how-to-create-a-form-with-validation/1456/14 "2017-10-18T12:19:40Z")

</div>

How are you instantiating the Validator class?
