Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit dafa21d

Browse files
Merge branch 'release-1.0.0'
2 parents 09d149c + bef7768 commit dafa21d

35 files changed

+807
-247
lines changed

‎.docker/install-php.sh‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,16 @@ docker-php-ext-install \
4242
pdo_mysql
4343

4444
# Install Xdebug
45-
# mac : docker.for.mac.localhost / win : host.docker.internal
45+
# ${HOST_IP} : mac : docker.for.mac.localhost / win : host.docker.internal
4646
pecl install xdebug-3.0.2
47-
echo "" >> /var/log/xdebug.log && chmod 777 /var/log/xdebug.log && echo -e "xdebug.log_level=1 \n xdebug.log=/var/log/xdebug.log \n zend_extension = xdebug.so \n xdebug.idekey=PHPSTORM \n xdebug.discover_client_host=0 \n xdebug.default_enable = 1 \n xdebug.remote_handler = "dbgp" \n xdebug.remote_port=9002 \n xdebug.client_host="host.docker.internal" \n xdebug.client_port=9002 \n xdebug.mode=debug" >> /usr/local/etc/php/conf.d/xdebug.ini
47+
echo "" >> /var/log/xdebug.log && chmod 777 /var/log/xdebug.log && echo -e "xdebug.log_level=1 \n xdebug.log=/var/log/xdebug.log \n zend_extension = xdebug.so \n xdebug.idekey=PHPSTORM \n xdebug.discover_client_host=0 \n xdebug.default_enable = 1 \n xdebug.remote_handler = "dbgp" \n xdebug.remote_port=9002 \n xdebug.client_host=${HOST_IP} \n xdebug.client_port=9002 \n xdebug.mode=debug" >> /usr/local/etc/php/conf.d/xdebug.ini
4848

4949
# Install composer
5050
cd /tmp && php -r "readfile('https://getcomposer.org/installer');" | php && \
5151
mv composer.phar /usr/bin/composer && \
5252
chmod +x /usr/bin/composer
5353

54-
#apk del $TMP
54+
apk del $TMP
5555

5656
# Install PHPUnit
5757
curl -sSL -o /usr/bin/phpunit https://phar.phpunit.de/phpunit.phar && chmod +x /usr/bin/phpunit

‎.env.docker‎ renamed to ‎.env.example.local‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# IMPORTANT - mac : docker.for.mac.localhost / win : host.docker.internal OR you can just type your host IP.
2+
HOST_IP=host.docker.internal
3+
14
APP_ENV=test
25
APP_KEY=key
36
APP_DEBUG=true

‎Dockerfile‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
FROM php:7.4-fpm-alpine
22

3-
# Comment this to improve stability on "auto deploy" environments
43
RUN apk update && apk upgrade
54

65
# Install basic dependencies
@@ -9,10 +8,13 @@ RUN apk -u add bash git
98
# Install PHP extensions
109
ADD ./.docker/install-php.sh /usr/sbin/install-php.sh
1110
RUN chmod +x /usr/sbin/install-php.sh
11+
1212
# [WARNING] Although the following script fails, this building process does NOT stop.
13+
ARG HOST_IP
14+
ENV HOST_IP=${HOST_IP}
1315
RUN /usr/sbin/install-php.sh
1416

15-
# Copy existing application directory contents
17+
# php.ini
1618
COPY ./.docker/*.ini /usr/local/etc/php/conf.d/
1719
#COPY . .
1820

‎README.md‎

Lines changed: 32 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,54 @@
1-
<palign="center"><imgsrc="https://laravel.com/assets/img/components/logo-laravel.svg"></p>
1+
# Laravel CRUD Boilerplate
22

3-
## Laravel 8 and React 17 boilerplate
4-
There are two different ways to run this demo
3+
## Overview & Installation
54

6-
Please follow the guide.
5+
Laravel CRUD Boilerplate is a modified version of a MIT licensed sample project, laravel-react ( https://github.com/moeen-basra/laravel-react ).
6+
I have removed front-end things and added some more convenient things, such as,
77

8-
## Prerequisite
8+
```shell
9+
# For Git cloning, if you use WIN WSL2, I strongly recommend cloning on a WSL folder `\\wsl$\Ubuntu\home` not `c:\`. You use Mac, I don't know, as I don't have one. T.T
910

10-
1. Make sure you have [composer](https://getcomposer.org/download/) installed.
11-
2. Make sure you have latest stable version of [node](https://nodejs.org/en/download/) installed.
11+
git clone https://github.com/Andrew-Kang-G/laravel-crud-boilerplate
12+
cp .env.example.local .env
1213

13-
### Option 1
14+
# on .env, you need to modify just one thing. "HOST_IP" (WIN WSL2 : host.docker.internal, Mac : docker.for.mac.localhost)
1415

15-
1. `git clone`
16-
2. `create a .env file copy content from .env.example and update the values`
17-
3. `composer install && composer update`
18-
4. `php artisan cron:refresh-database`
19-
5. if npm version < 7 `npm install && npm run dev` else `npm install --legacy-peer-deps && npm run dev`
20-
6. `php artisan key:gen`
21-
7. `php artisan serve`
16+
docker-compose build
17+
docker-compose up -d
2218

23-
### Option 2
19+
# You can see the building process by running 'docker logs -f lr_app'.
20+
# You can get into the App container by running 'docker exec -it lr_app bash'. (As Dockerfile has been built as a ROOT user, you can do anything inside the container. However, considering security, add USER www-data on Dockerfile on production environments.
21+
```
2422

2523
## Prerequisite
26-
Make sure you have [docker](https://docs.docker.com/install/) and [docker-compose](https://docs.docker.com/compose/install/) installed on you machine.
2724

28-
1. `git clone`
29-
2. `create a .env file copy content from .env.docker and do not make any change`
25+
For me, on WSL2,
3026

31-
run following command in terminal / power shell
32-
```
33-
docker-compose up -d
34-
```
27+
- Docker version 20.10.23
28+
- Docker Compose version v2.15.1
3529

36-
when docker will finish building the containers, access the "laravel-crud-boilerplate-app" container using following command
30+
## Database
3731

38-
`docker exec -it lr_app sh`
32+
- It is automatically up as running `docker-compose up -d` above.
33+
- If you need to persist data continually, just uncomment `# ./.docker/db/data:/var/lib/mysql` on the docker-compose.yml.
34+
- The transaction isolation level is at 'READ-COMMITTED' on the docker-compose.yml.
3935

40-
now you will be inside container
36+
## Debugging
37+
On the 'docker-compose.yml',
38+
`PHP_IDE_CONFIG: "serverName=laravel-crud-boilerplate"` And
39+
![img.png](/reference/readme/img.png)
4140

42-
run following commands
43-
1. `composer install && composer update`
44-
2. `php artisan cron:refresh-database`
45-
3. `php artisan key:gen`
46-
4. if npm version < 7 `npm install && npm run dev` else `npm install --legacy-peer-deps && npm run dev`
41+
must be the same, 'laravel-crud-boilerplate'.
4742

48-
open browser and check the following address
43+
Additionally, set the port to be 9002.
44+
![img2.png](/reference/readme/img2.png)
4945

50-
`http://localhost:8100`
46+
## Test APIs
47+
Postman API files are on `./reference/postman`
5148

52-
TODO:
49+
## Test Codes
5350

54-
- [x] Add Redux
55-
- [x] Add Laravel Sanctum for authentication
56-
- [x] User Login
57-
- [x] User Register
58-
- [x] Users Crud
59-
- [x] Articles Crud
60-
- [x] Form validation Client and Server
61-
- [x] Reset Password
62-
- [x] Tests
63-
- [x] Upgrade to Laravel 7
64-
- [x] Upgrade to React 16.13
65-
- [x] docker
51+
T.T. Not yet.
6652

6753

6854

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace App\Exceptions\database;
4+
5+
use Exception;
6+
7+
class ForeignKeyException extends \RuntimeException
8+
{
9+
public function __construct($message = null)
10+
{
11+
$message = $message ?: 'Foreign key constraint violation.';
12+
parent::__construct($message, 422);
13+
}
14+
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace App\Exceptions\database;
4+
5+
use Exception;
6+
7+
class RowNotFoundException extends \RuntimeException
8+
{
9+
public function __construct($message = null)
10+
{
11+
$message = $message ?: 'Row NOT found on DB.';
12+
parent::__construct($message, 404);
13+
}
14+
15+
}

‎app/Http/Controllers/Api/Auth/LoginController.php‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ class LoginController extends Controller
1414
{
1515
public function login(Request $request)
1616
{
17-
1817
$input = $this->validate($request, [
1918
'email' => 'required|email|exists:users,email',
2019
'password' => 'required|min:6',

‎app/Http/Controllers/Api/Auth/RegisterController.php‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Illuminate\Auth\Events\Registered;
88
use Illuminate\Http\Request;
99
use GuzzleHttp\Client;
10+
use Illuminate\Support\Facades\Log;
1011

1112
class RegisterController extends Controller
1213
{
@@ -40,7 +41,11 @@ public function register(Request $request)
4041

4142
return json_decode((string)$response->getBody(), true);
4243
} catch (\Exception $e) {
43-
dd($e->getMessage(), $e->getCode(), $e->getTrace());
44+
45+
// 다만 항상 invalid credential 오류라는 것을 보장하지 못하기 때문에... 다른 종류의 오류라면 서버에서 확인이 필요할 것으로 보임.
46+
Log::error($e->getMessage());
47+
48+
// 원작자가 보안을 고려해 이와 같이 처리한 것으로 보임.
4449
return response()->json([
4550
"error" => "invalid_credentials",
4651
"message" => "The user credentials were incorrect."

‎app/Http/Controllers/Api/CourseController.php‎

Lines changed: 43 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -2,135 +2,80 @@
22

33
namespace App\Http\Controllers\Api;
44

5-
use App\Models\Article;
6-
use Illuminate\Http\Request;
7-
use Illuminate\Support\Str;
5+
use App\Http\DTOs\CourseIndexDTO;
6+
use App\Http\Requests\CourseIndexRequest;
7+
use App\Models\Course;
88
use App\Http\Controllers\Controller;
9-
use App\Http\Requests\ArticleRequest;
9+
use App\Models\Enrollment;
10+
use App\Models\Lesson;
1011
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
12+
use Illuminate\Support\Facades\DB;
1113

1214
class CourseController extends Controller
1315
{
1416
/**
15-
* Display a listing of the resource.
17+
* Display a paginated listing of courses
1618
*
17-
* @param Request $request
18-
* @return LengthAwarePaginator|mixed
19+
* @param CourseIndexRequest $request
20+
* @return LengthAwarePaginator
1921
*/
20-
public function index(Request $request)
22+
public function index(CourseIndexRequest $request): LengthAwarePaginator
2123
{
22-
if ($request->user()->is_admin) {
23-
return Article::loadAll();
24-
}
25-
return Article::loadAllMine($request->user()->id);
26-
}
27-
28-
/**
29-
* get all published articles
30-
*
31-
* @return mixed
32-
*/
33-
public function publishedArticles()
34-
{
35-
return Article::loadAllPublished();
36-
}
37-
38-
/**
39-
* Get single published article
40-
*
41-
* @param $slug
42-
* @return mixed
43-
*/
44-
public function publishedArticle($slug)
45-
{
46-
return Article::loadPublished($slug);
24+
$courseIndexDTO = CourseIndexDTO::fromRequest($request);
25+
return Course::getAvailableCourses($courseIndexDTO->getLanguage(), $courseIndexDTO->getType());
4726
}
4827

49-
/**
50-
* Show the form for creating a new resource.
51-
*
52-
* @return \Illuminate\Http\Response
53-
*/
54-
public function create()
55-
{
56-
//
57-
}
5828

5929
/**
60-
* Store a newly created resource in storage.
6130
*
62-
* @param ArticleRequest $request
63-
* @return \Illuminate\Http\Response
31+
* 관리자가 Course 를 비활성화 할 경우. (Middleware 에서 현재 사용자가 Admin 으로 되어야 함.)
32+
* @param $id
33+
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
34+
* @throws \Throwable
6435
*/
65-
public function store(ArticleRequest$request)
36+
public function delete($id)
6637
{
67-
$user = $request->user();
38+
DB::beginTransaction();
6839

69-
$article = new Article($request->validated());
70-
$article->slug = Str::slug($request->get('title'));
40+
try {
7141

72-
$user->articles()->save($article);
42+
// These are all "Soft Delete".
43+
Course::find($id)->delete();
44+
Enrollment::where('course_id', $id)->delete();
45+
Lesson::whereIn('enrollment_id', Enrollment::where('course_id', $id)->get()->pluck('id')->toArray())->delete();
7346

74-
return response()->json($article, 201);
75-
}
47+
DB::commit();
7648

77-
/**
78-
* Display the specified resource.
79-
*
80-
* @param \Illuminate\Http\Request $request
81-
* @param int $id
82-
* @return \Illuminate\Http\Response
83-
*/
84-
public function show(Request $request, $id)
85-
{
86-
if (!$request->user()->is_admin) {
87-
return Article::mine($request->user()->id)->findOrFail($id);
49+
}catch (\Throwable $e){
50+
DB::rollBack();
51+
throw $e;
8852
}
89-
90-
return Article::findOrFail($id);
91-
}
92-
93-
/**
94-
* Show the form for editing the specified resource.
95-
*
96-
* @param int $id
97-
* @return \Illuminate\Http\Response
98-
*/
99-
public function edit($id)
100-
{
101-
//
53+
return response([], 200);
10254
}
10355

10456
/**
105-
* Update the specified resource in storage.
10657
*
107-
* @param ArticleRequest $request
108-
* @param int $id
109-
* @return \Illuminate\Http\Response
58+
* 관리자가 Course 를 활성화 할 경우. (Middleware 에서 현재 사용자가 Admin 으로 되어야 함.)
59+
* @param $id
60+
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
61+
* @throws \Throwable
11062
*/
111-
public function update(ArticleRequest$request, $id)
63+
public function restore($id)
11264
{
113-
$article = Article::findOrFail($id);
65+
DB::beginTransaction();
11466

115-
$data = $request->validated();
116-
$data['slug'] = Str::slug($data['title']);
117-
$article->update($data);
67+
try {
11868

119-
return response()->json($article, 200);
120-
}
121-
122-
/**
123-
* Remove the specified resource from storage.
124-
*
125-
* @param int $id
126-
* @return \Illuminate\Http\Response
127-
*/
128-
public function delete($id)
129-
{
130-
$article = Article::findOrFail($id);
69+
Course::find($id)->restore();
70+
Enrollment::where('course_id', $id)->restore();
71+
Lesson::whereIn('enrollment_id', Enrollment::where('course_id', $id)->get()->pluck('id')->toArray())->restore();
13172

132-
$article->delete();
73+
DB::commit();
13374

75+
}catch (\Throwable $e){
76+
DB::rollBack();
77+
throw $e;
78+
}
13479
return response([], 200);
13580
}
13681
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /