Skip to content

Commit 3866286

Browse files
authored
Merge pull request #1 from hexlet-components/db
add work with database
2 parents dbdfb5f + bde680d commit 3866286

File tree

12 files changed

+375
-10
lines changed

12 files changed

+375
-10
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
vendor/
22
users.json
33
.vscode
4+
database.sqlite

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{ "autoload": {
22
"psr-4": {
3-
"App\\": "src"
3+
"App\\": "src/"
44
}
55
},
66
"require": {

init.sql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
CREATE TABLE IF NOT EXISTS cars (
2+
id INTEGER PRIMARY KEY AUTOINCREMENT,
3+
make VARCHAR(255) NOT NULL,
4+
model VARCHAR(255) NOT NULL
5+
);

public/index.php

Lines changed: 133 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,18 @@
44
require __DIR__ . '/../vendor/autoload.php';
55

66
// Контейнеры в этом курсе не рассматриваются (это тема связанная с самим ООП), но если вам интересно, то посмотрите DI Container
7+
8+
use App\Car;
9+
use App\CarRepository;
10+
use App\CarValidator;
711
use Slim\Factory\AppFactory;
812
use Slim\Middleware\MethodOverrideMiddleware;
913
use DI\Container;
10-
use App\Validator;
14+
use App\UserValidator;
1115

1216
// Старт PHP сессии
1317
session_start();
1418

15-
const FILE_PATH = __DIR__ . '/../users.json';
1619
const ADMIN_EMAIL = '[email protected]';
1720

1821
function getUsers($request)
@@ -26,13 +29,26 @@ function filterUsersByName($users, $term)
2629
}
2730

2831
$container = new Container();
32+
2933
$container->set('renderer', function () {
3034
// Параметром передается базовая директория, в которой будут храниться шаблоны
3135
return new \Slim\Views\PhpRenderer(__DIR__ . '/../templates');
3236
});
37+
3338
$container->set('flash', function () {
3439
return new \Slim\Flash\Messages();
3540
});
41+
42+
$container->set(\PDO::class, function () {
43+
$conn = new \PDO('sqlite:database.sqlite');
44+
$conn->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC);
45+
return $conn;
46+
});
47+
48+
$initFilePath = implode('/', [dirname(__DIR__), 'init.sql']);
49+
$initSql = file_get_contents($initFilePath);
50+
$container->get(\PDO::class)->exec($initSql);
51+
3652
$app = AppFactory::createFromContainer($container);
3753

3854
$router = $app->getRouteCollector()->getRouteParser();
@@ -74,7 +90,7 @@ function filterUsersByName($users, $term)
7490
return $response->withRedirect($router->urlFor('home'));
7591
});
7692

77-
$app->get('/users', function ($request, $response) {
93+
$app->get('/users', function ($request, $response) use ($router) {
7894
if (!isset($_SESSION['isAdmin'])) {
7995
$this->get('flash')->addMessage('error', 'Access Denied! Please login!');
8096

@@ -100,7 +116,7 @@ function filterUsersByName($users, $term)
100116
$users = getUsers($request);
101117
$userData = $request->getParsedBodyParam('user');
102118

103-
$validator = new Validator();
119+
$validator = new UserValidator();
104120
$errors = $validator->validate($userData);
105121

106122
if (count($errors) === 0) {
@@ -123,7 +139,7 @@ function filterUsersByName($users, $term)
123139
return $this->get('renderer')->render($response->withStatus(422), 'users/new.phtml', $params);
124140
})->setName('users.store');
125141

126-
$app->get('/users/new', function ($request, $response) {
142+
$app->get('/users/new', function ($request, $response) use ($router){
127143
if (!isset($_SESSION['isAdmin'])) {
128144
$this->get('flash')->addMessage('error', 'Access Denied! Please login!');
129145

@@ -143,7 +159,7 @@ function filterUsersByName($users, $term)
143159
return $response->write("Course id: {$id}");
144160
})->setName('courses.show');
145161

146-
$app->get('/users/{id}', function ($request, $response, $args) {
162+
$app->get('/users/{id}', function ($request, $response, $args) use ($router) {
147163
if (!isset($_SESSION['isAdmin'])) {
148164
$this->get('flash')->addMessage('error', 'Access Denied! Please login!');
149165

@@ -168,7 +184,7 @@ function filterUsersByName($users, $term)
168184
return $this->get('renderer')->render($response, 'users/show.phtml', $params);
169185
})->setName('users.show');
170186

171-
$app->get('/users/{id}/edit', function ($request, $response, $args) {
187+
$app->get('/users/{id}/edit', function ($request, $response, $args) use ($router) {
172188
if (!isset($_SESSION['isAdmin'])) {
173189
$this->get('flash')->addMessage('error', 'Access Denied! Please login!');
174190

@@ -195,7 +211,7 @@ function filterUsersByName($users, $term)
195211
$user = $users[$id];
196212
$userData = $request->getParsedBodyParam('user');
197213

198-
$validator = new Validator();
214+
$validator = new UserValidator();
199215
$errors = $validator->validate($userData);
200216

201217
if (count($errors) === 0) {
@@ -233,4 +249,113 @@ function filterUsersByName($users, $term)
233249
->withRedirect($router->urlFor('users.index'));
234250
});
235251

252+
$app->get('/cars', function ($request, $response) {
253+
$carRepository = $this->get(CarRepository::class);
254+
$cars = $carRepository->getEntities();
255+
256+
$messages = $this->get('flash')->getMessages();
257+
258+
$params = [
259+
'cars' => $cars,
260+
'flash' => $messages
261+
];
262+
263+
return $this->get('renderer')->render($response, 'cars/index.phtml', $params);
264+
})->setName('cars.index');
265+
266+
$app->post('/cars', function ($request, $response) use ($router) {
267+
$carRepository = $this->get(CarRepository::class);
268+
$carData = $request->getParsedBodyParam('car');
269+
270+
$validator = new CarValidator();
271+
$errors = $validator->validate($carData);
272+
273+
if (count($errors) === 0) {
274+
$car = Car::fromArray([$carData['make'], $carData['model']]);
275+
$carRepository->save($car);
276+
$this->get('flash')->addMessage('success', 'Car was added successfully');
277+
return $response->withRedirect($router->urlFor('cars.index'));
278+
}
279+
280+
$params = [
281+
'car' => $carData,
282+
'errors' => $errors
283+
];
284+
285+
return $this->get('renderer')->render($response->withStatus(422), 'cars/new.phtml', $params);
286+
})->setName('cars.store');
287+
288+
$app->get('/cars/new', function ($request, $response) {
289+
$params = [
290+
'car' => new Car(),
291+
'errors' => []
292+
];
293+
294+
return $this->get('renderer')->render($response, 'cars/new.phtml', $params);
295+
})->setName('cars.create');
296+
297+
$app->get('/cars/{id}', function ($request, $response, $args) {
298+
$carRepository = $this->get(CarRepository::class);
299+
$id = $args['id'];
300+
$car = $carRepository->find($id);
301+
302+
if (is_null($car)) {
303+
return $response->write('Page not found')->withStatus(404);
304+
}
305+
306+
$messages = $this->get('flash')->getMessages();
307+
308+
$params = [
309+
'car' => $car,
310+
'flash' => $messages
311+
];
312+
313+
return $this->get('renderer')->render($response, 'cars/show.phtml', $params);
314+
})->setName('cars.show');
315+
316+
$app->get('/cars/{id}/edit', function ($request, $response, $args) {
317+
$carRepository = $this->get(CarRepository::class);
318+
$messages = $this->get('flash')->getMessages();
319+
$id = $args['id'];
320+
$car = $carRepository->find($id);
321+
322+
$params = [
323+
'car' => $car,
324+
'errors' => [],
325+
'flash' => $messages
326+
];
327+
328+
return $this->get('renderer')->render($response, 'cars/edit.phtml', $params);
329+
})->setName('cars.edit');
330+
331+
$app->patch('/cars/{id}', function ($request, $response, $args) use ($router) {
332+
$carRepository = $this->get(CarRepository::class);
333+
$id = $args['id'];
334+
335+
$car = $carRepository->find($id);
336+
337+
if (is_null($car)) {
338+
return $response->write('Page not found')->withStatus(404);
339+
}
340+
341+
$carData = $request->getParsedBodyParam('car');
342+
$validator = new CarValidator();
343+
$errors = $validator->validate($carData);
344+
345+
if (count($errors) === 0) {
346+
$car->setMake($carData['make']);
347+
$car->setModel($carData['model']);
348+
$carRepository->save($car);
349+
$this->get('flash')->addMessage('success', "Car was updated successfully");
350+
return $response->withRedirect($router->urlFor('cars.show', $args));
351+
}
352+
353+
$params = [
354+
'car' => $car,
355+
'errors' => $errors
356+
];
357+
358+
return $this->get('renderer')->render($response->withStatus(422), 'cars/edit.phtml', $params);
359+
});
360+
236361
$app->run();

src/Car.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
namespace App;
4+
5+
class Car
6+
{
7+
private ?int $id = null;
8+
private ?string $make = null;
9+
private ?string $model = null;
10+
11+
public static function fromArray(array $carData): Car
12+
{
13+
[$make, $model] = $carData;
14+
$car = new Car();
15+
$car->setMake($make);
16+
$car->setModel($model);
17+
return $car;
18+
}
19+
20+
public function getId(): ?int
21+
{
22+
return $this->id;
23+
}
24+
25+
public function getMake(): ?string
26+
{
27+
return $this->make;
28+
}
29+
30+
public function getModel(): ?string
31+
{
32+
return $this->model;
33+
}
34+
35+
public function setId(int $id): void
36+
{
37+
$this->id = $id;
38+
}
39+
40+
public function setMake(string $make): void
41+
{
42+
$this->make = $make;
43+
}
44+
45+
public function setModel(string $model): void
46+
{
47+
$this->model = $model;
48+
}
49+
50+
public function exists(): bool
51+
{
52+
return !is_null($this->getId());
53+
}
54+
}

src/CarRepository.php

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
namespace App;
4+
5+
class CarRepository
6+
{
7+
private \PDO $conn;
8+
9+
public function __construct(\PDO $conn)
10+
{
11+
$this->conn = $conn;
12+
}
13+
14+
public function getEntities(): array
15+
{
16+
$cars = [];
17+
$sql = "SELECT * FROM cars";
18+
$stmt = $this->conn->query($sql);
19+
20+
while ($row = $stmt->fetch()) {
21+
$car = Car::fromArray([$row['make'], $row['model']]);
22+
$car->setId($row['id']);
23+
$cars[] = $car;
24+
}
25+
26+
return $cars;
27+
}
28+
29+
public function find(int $id): ?Car
30+
{
31+
$sql = "SELECT * FROM cars WHERE id = ?";
32+
$stmt = $this->conn->prepare($sql);
33+
$stmt->execute([$id]);
34+
if ($row = $stmt->fetch()) {
35+
$car = Car::fromArray([$row['make'], $row['model']]);
36+
$car->setId($row['id']);
37+
return $car;
38+
}
39+
40+
return null;
41+
}
42+
43+
public function save(Car $car): void {
44+
if ($car->exists()) {
45+
$this->update($car);
46+
} else {
47+
$this->create($car);
48+
}
49+
}
50+
51+
private function update(Car $car): void
52+
{
53+
$sql = "UPDATE cars SET make = :make, model = :model WHERE id = :id";
54+
$stmt = $this->conn->prepare($sql);
55+
$id = $car->getId();
56+
$make = $car->getMake();
57+
$model = $car->getModel();
58+
$stmt->bindParam(':make', $make);
59+
$stmt->bindParam(':model', $model);
60+
$stmt->bindParam(':id', $id);
61+
$stmt->execute();
62+
}
63+
64+
private function create(Car $car): void
65+
{
66+
$sql = "INSERT INTO cars (make, model) VALUES (:make, :model)";
67+
$stmt = $this->conn->prepare($sql);
68+
$make = $car->getMake();
69+
$model = $car->getModel();
70+
$stmt->bindParam(':make', $make);
71+
$stmt->bindParam(':model', $model);
72+
$stmt->execute();
73+
$id = (int) $this->conn->lastInsertId();
74+
$car->setId($id);
75+
}
76+
}

src/CarValidator.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
namespace App;
4+
5+
class CarValidator
6+
{
7+
public function validate(array $car): array
8+
{
9+
$errors = [];
10+
if (empty($car['make'])) {
11+
$errors['make'] = "Make can not be empty";
12+
}
13+
14+
if (empty($car['model'])) {
15+
$errors['model'] = "Model can not be empty";
16+
}
17+
18+
return $errors;
19+
}
20+
}

src/Validator.php renamed to src/UserValidator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace App;
44

5-
class Validator
5+
class UserValidator
66
{
77
public function validate(array $user): array
88
{

0 commit comments

Comments
 (0)