Skip to content

Commit 0f91e24

Browse files
committed
ep 44 working
1 parent 6fcf1ba commit 0f91e24

File tree

5 files changed

+144
-26
lines changed

5 files changed

+144
-26
lines changed

Core/ValidationException.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
namespace Core;
4+
5+
class ValidationException extends \Exception
6+
{
7+
// protected $errors = [];
8+
// protected $old = [];
9+
// we cant directly access protected properties from outside the class
10+
// option 1 make it public
11+
// option 2 so we need to create a getter method to access the old data
12+
// public function errors()
13+
// {
14+
// return $this->errors;
15+
// }
16+
// another option is declare it public but you can also say readonly
17+
// public readonly array $errors;
18+
// which means we can assign it only once and we can never update its value
19+
public readonly array $errors;
20+
public readonly array $old;
21+
22+
public static function throw($errors, $old)
23+
{
24+
$instance = new static;
25+
26+
$instance->errors = $errors;
27+
$instance->old = $old;
28+
29+
throw $instance;
30+
}
31+
32+
}

Core/router.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,13 @@ public function route($uri, $method)
112112
$this->abort();
113113
}
114114

115+
public function previousUrl()
116+
{
117+
// option 1 is Router knows previous url
118+
// or router can perform a redirect itself
119+
return $_SERVER['HTTP_REFERER'];
120+
}
121+
115122
protected function abort($code = 404)
116123
{
117124
http_response_code($code);

Http/Forms/LoginForm.php

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,59 @@
22

33
namespace Http\Forms;
44

5+
use Core\ValidationException;
56
use Core\Validator;
67

78
class LoginForm
89
{
10+
// public $attributes;
911
protected $errors = [];
1012

11-
public function validate($email, $password)
12-
{
13-
// validate the form inputs.
1413

15-
if (!Validator::email($email)) {
14+
// we have a way to perform validation
15+
public function __construct(public array $attributes)
16+
{
17+
// $this->attributes = $attributes;
18+
// or in php 8 we can directly assign the attributes from the constructor
19+
// you can also do it like this too
20+
// if (!Validator::email($this->attributes['email'])) {
21+
if (!Validator::email($attributes['email'])) {
1622
$this->errors['email'] = 'Please enter a valid email address.';
1723
}
1824

19-
if (!Validator::string($password)) {
25+
if (!Validator::string($attributes['password'])) {
2026
$this->errors['password'] = 'Please provide a valid password.';
2127
}
2228

23-
// this return $errors array but we want boolean value
24-
return empty($this->errors);
29+
}
30+
31+
public static function validate($attributes)
32+
{
33+
$instance = new static($attributes);
34+
35+
return $instance->failed() ? $instance->throw() : $instance;
36+
37+
// these two can be combined
38+
// if ($instance->failed()) {
39+
// // throw new ValidationException();
40+
// // ValidationException::throw($instance->errors(), $instance->attributes);
41+
// $instance->throw();
42+
// }
43+
44+
// // what if the form is valid?
45+
// return $instance;
46+
47+
}
48+
49+
// now we have a way to throw the validation exception
50+
public function throw()
51+
{
52+
ValidationException::throw($this->errors(), $this->attributes);
53+
}
54+
55+
public function failed()
56+
{
57+
return count($this->errors);
2558
}
2659

2760
// this is a getter method to access the errors
@@ -31,8 +64,11 @@ public function errors()
3164
return $this->errors;
3265
}
3366

67+
// we have a way to manually add an error to the validation errors list
3468
public function error($field, $message)
3569
{
3670
$this->errors[$field] = $message;
71+
72+
return $this;
3773
}
3874
}

Http/controllers/session/store.php

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,46 +4,70 @@
44

55
// use Core\App;
66
use Core\Authenticator;
7-
use Core\Session;
7+
// use Core\Session;
8+
// use Core\ValidationException;
89
// use Core\Database;
910
// use Core\Validator;
1011
use Http\Forms\LoginForm;
1112

1213
// $db = App::resolve(Database::class);
1314

1415
// var_dump('I have been posted!');
16+
// $email = $_POST['email'];
17+
// $password = $_POST['password'];
18+
19+
// tray catch is move to the public/index.php file
20+
// try {
21+
$form = LoginForm::validate($attributes = [
22+
'email' => $_POST['email'],
23+
'password' => $_POST['password']
24+
]);
25+
// } catch (ValidationException $exception) {
26+
// Session::flash('errors', $exception->errors);
27+
// Session::flash('old', $exception->old);
1528

16-
$email = $_POST['email'];
17-
$password = $_POST['password'];
29+
// return redirect('/login');
30+
// }
1831

19-
$form = new LoginForm();
32+
$signedIn = (new Authenticator())
33+
->attempt(
34+
$attributes['email'],
35+
$attributes['password']
36+
);
37+
38+
if (!$signedIn) {
39+
$form->error(
40+
'email',
41+
'No matching account found for that email address and password.'
42+
)->throw();
43+
}
2044

21-
if ($form->validate($email, $password)) {
22-
// $auth = new Authenticator();
23-
// if you are not passing constructor parameters then you can omit the ()
24-
// if ((new Authenticator)->attempt($email, $password)) {
25-
if ((new Authenticator())->attempt($email, $password)) {
26-
redirect('/');
27-
}
45+
redirect('/');
2846

29-
$form->error('email', 'No matching account found for that email address and password.');
30-
}
47+
// and finally lets reverse it i often like to do my guard clauses before the happy path
48+
// in this case we are doing the happy path first and then the guard clause
49+
// if ((new Authenticator())->attempt($attributes['email'], $attributes['password'])) {
50+
// redirect('/');
51+
// }
52+
53+
// $form->error('email', 'No matching account found for that email address and password.')
54+
// ->throw();
3155

3256
// $_SESSION['errors'] = $form->errors();
3357
// we need to expire above thing after one page load
3458

3559
// $_SESSION['_flash']['errors'] = $form->errors();
3660

37-
Session::flash('errors', $form->errors());
61+
// Session::flash('errors', $form->errors());
3862

3963
// old form data old is really common convention
4064
// you probably notice this many times there is never a situation where we should manually populate
4165
// that password input, you always have to reenter it yourself
42-
Session::flash('old', [
43-
'email' => $_POST['email']
44-
]);
66+
// Session::flash('old', [
67+
// 'email' => $_POST['email']
68+
// ]);
4569

46-
return redirect('/login');
70+
// return redirect('/login');
4771

4872
// return view('session/create.view.php', [
4973
// 'errors' => $form->errors()

public/index.php

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?php
22

33
use Core\Session;
4+
use Core\ValidationException;
45

56
session_start();
67

@@ -22,7 +23,25 @@
2223
$uri = parse_url($_SERVER['REQUEST_URI'])['path'];
2324
$method = $_POST['_method'] ?? $_SERVER['REQUEST_METHOD'];
2425

25-
$router->route($uri, $method);
26+
try {
27+
// try to the route to the controller
28+
$router->route($uri, $method);
29+
} catch (ValidationException $exception) {
30+
// but catch any validation exceptions that might be thrown
31+
// and here in a single place not every controller
32+
// but a single place we can flash the errors and old data
33+
// and then redirect back
34+
// thats one way we can solve this problem
35+
// dd($_SERVER);
36+
// $_SERVER['HTTP_REFERER']
37+
Session::flash('errors', $exception->errors);
38+
Session::flash('old', $exception->old);
39+
40+
// this needs to be dynamic
41+
// return redirect('/login');
42+
return redirect($router->previousUrl());
43+
}
44+
2645

2746
// right here we can clear out any _flash session data
2847
// later we will refactor this and organize it better

0 commit comments

Comments
 (0)