├── .gitignore
├── gula.png
├── src
├── G5Model.php
├── Traits
│ ├── BelongToG5Board.php
│ ├── BelongToG5ShopItem.php
│ ├── BelongToG5ShopOrder.php
│ └── BelongToG5Member.php
├── Console
│ ├── stubs
│ │ ├── G5CustomModel.php.stub
│ │ └── G5WriteModel.php.stub
│ ├── AutoGenerateG5WriteModels.php
│ ├── GenerateG5CustomModel.php
│ └── GenerateG5WriteModel.php
├── G5ModelFactory.php
├── Models
│ ├── Gnu
│ │ ├── G5Uniqid.php
│ │ ├── G5VisitSum.php
│ │ ├── G5Auth.php
│ │ ├── G5Login.php
│ │ ├── G5Faq.php
│ │ ├── G5Popular.php
│ │ ├── G5GroupMember.php
│ │ ├── G5Mail.php
│ │ ├── G5Autosave.php
│ │ ├── G5Menu.php
│ │ ├── G5Visit.php
│ │ ├── G5FaqMaster.php
│ │ ├── G5CertHistory.php
│ │ ├── G5Scrap.php
│ │ ├── G5Content.php
│ │ ├── G5BoardGood.php
│ │ ├── G5BoardNew.php
│ │ ├── G5NewWin.php
│ │ ├── G5MemberSocialProfiles.php
│ │ ├── G5Point.php
│ │ ├── G5PollEtc.php
│ │ ├── G5Poll.php
│ │ ├── G5QaConfig.php
│ │ ├── G5BoardFile.php
│ │ ├── G5Memo.php
│ │ ├── G5QaContent.php
│ │ ├── G5Group.php
│ │ ├── G5Board.php
│ │ ├── G5Config.php
│ │ └── G5Member.php
│ └── Young
│ │ ├── G5ShopItemRelation.php
│ │ ├── G5ShopEventItem.php
│ │ ├── G5ShopSendcost.php
│ │ ├── G5ShopOrderDelete.php
│ │ ├── G5ShopInicisLog.php
│ │ ├── G5ShopWish.php
│ │ ├── G5ShopItemOption.php
│ │ ├── G5ShopOrderPostLog.php
│ │ ├── G5ShopItemStocksms.php
│ │ ├── G5ShopOrderData.php
│ │ ├── G5ShopBanner.php
│ │ ├── G5ShopOrderAddress.php
│ │ ├── G5ShopItemUse.php
│ │ ├── G5ShopCouponZone.php
│ │ ├── G5ShopItemQa.php
│ │ ├── G5ShopCouponLog.php
│ │ ├── G5ShopPersonalpay.php
│ │ ├── G5ShopEvent.php
│ │ ├── G5ShopCart.php
│ │ ├── G5ShopCoupon.php
│ │ ├── G5ShopCategory.php
│ │ ├── G5ShopOrder.php
│ │ ├── G5ShopItem.php
│ │ └── G5ShopDefault.php
├── config
│ └── gula.php
└── GuLaServiceProvider.php
├── tests
├── TestCase.php
├── Unit
│ ├── G5RelationTest.php
│ ├── G5ModelFactoryTest.php
│ └── G5MemberWriteTableTest.php
└── Feature
│ ├── G5ModelTest.php
│ ├── AutoGenerateG5WriteModelsTest.php
│ ├── GenerateG5CustomModelTest.php
│ └── GenerateG5WriteModelTest.php
├── composer.json
├── CHANGELOG.md
├── phpunit.xml
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | vendor/
2 | .env
--------------------------------------------------------------------------------
/gula.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/silnex/GuLa/HEAD/gula.png
--------------------------------------------------------------------------------
/src/G5Model.php:
--------------------------------------------------------------------------------
1 | belongsTo(G5Board::class, 'bo_table', 'bo_table');
12 | }
13 | }
--------------------------------------------------------------------------------
/src/Traits/BelongToG5ShopItem.php:
--------------------------------------------------------------------------------
1 | belongsTo(G5ShopItem::class, 'it_id', 'it_id');
12 | }
13 | }
--------------------------------------------------------------------------------
/src/Traits/BelongToG5ShopOrder.php:
--------------------------------------------------------------------------------
1 | belongsTo(G5ShopOrder::class, 'od_id', 'od_id');
12 | }
13 | }
--------------------------------------------------------------------------------
/src/Traits/BelongToG5Member.php:
--------------------------------------------------------------------------------
1 | belongsTo(G5Member::class, $this->g5MemberForeignKey ?? 'mb_id', 'mb_id');
12 | }
13 | }
--------------------------------------------------------------------------------
/tests/TestCase.php:
--------------------------------------------------------------------------------
1 | where('mb_id', '=', 'admin')->first();
14 |
15 | $admin->g5Points()->first();
16 |
17 | $this->assertTrue(true);
18 | }
19 | }
--------------------------------------------------------------------------------
/src/Console/stubs/G5CustomModel.php.stub:
--------------------------------------------------------------------------------
1 | assertNotSame($g5Member->getConnectionName(), $dummy->getConnectionName());
15 | }
16 |
17 | public function test_connection_test()
18 | {
19 | $g5Member = new G5Member();
20 | $g5Member->all();
21 |
22 | $this->assertTrue(true);
23 | }
24 | }
25 |
26 | class DummyModel extends Model
27 | {
28 | }
29 |
--------------------------------------------------------------------------------
/src/G5ModelFactory.php:
--------------------------------------------------------------------------------
1 | newConnection = $data[0] ?? $this->newConnection;
13 | $this->newTable = $data[1] ?? $this->newTable;
14 | $this->setConnection($this->newConnection);
15 | $this->setTable($this->newTable);
16 | parent::__construct([]);
17 | }
18 |
19 | public function newInstance($attributes = [], $exists = false)
20 | {
21 | $model = parent::newInstance($attributes, $exists);
22 | $model->setTable($this->table);
23 |
24 | return $model;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/Console/AutoGenerateG5WriteModels.php:
--------------------------------------------------------------------------------
1 | get()->toArray());
18 |
19 | foreach ($boards as $board) {
20 | $this->info(" {$board} 게시판 모델을 생성합니다.");
21 | $this->call('g5model:write', ['name' => $board]);
22 | }
23 |
24 | $this->info(" 모든 게시판 모델이 생성되었습니다.");
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/Models/Gnu/G5Uniqid.php:
--------------------------------------------------------------------------------
1 | 'mysql',
5 | 'url' => env('GULA_DATABASE_URL'),
6 | 'host' => env('GULA_DB_HOST', '127.0.0.1'),
7 | 'port' => env('GULA_DB_PORT', '3306'),
8 | 'database' => env('GULA_DB_DATABASE', 'forge'),
9 | 'username' => env('GULA_DB_USERNAME', 'forge'),
10 | 'password' => env('GULA_DB_PASSWORD', ''),
11 | 'unix_socket' => env('GULA_DB_SOCKET', ''),
12 | 'charset' => env('GULA_CHARSET', 'utf8mb4'),
13 | 'collation' => env('GULA_COLLATION', 'utf8mb4_unicode_ci'),
14 | 'prefix' => '',
15 | 'prefix_indexes' => true,
16 | 'strict' => true,
17 | 'engine' => null,
18 | 'options' => extension_loaded('pdo_mysql') ? array_filter([
19 | PDO::MYSQL_ATTR_SSL_CA => env('GULA_MYSQL_ATTR_SSL_CA'),
20 | ]) : [],
21 | ];
22 |
--------------------------------------------------------------------------------
/src/Models/Young/G5ShopItemRelation.php:
--------------------------------------------------------------------------------
1 | assertTrue($G5WriteFree->count() > 0);
15 | }
16 |
17 | public function test_g5model_auto()
18 | {
19 | $notExistsModel = "\SilNex\GuLa\Gnu\G5WriteFree";
20 |
21 | if (!class_exists($notExistsModel)) {
22 | $model = explode('\\', $notExistsModel);
23 | $table = Str::snake(end($model));
24 |
25 | $G5WriteFree = new G5ModelFactory(['gula', $table]);
26 |
27 | $this->assertTrue($G5WriteFree->count() > 0);
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "silnex/gula",
3 | "description": "Laravel for Gnuboard5",
4 | "license": "MIT",
5 | "authors": [
6 | {
7 | "name": "silnex",
8 | "email": "silnex@silnex.kr"
9 | }
10 | ],
11 | "require": {
12 | "laravel/framework": "^7.0"
13 | },
14 | "autoload": {
15 | "psr-4": {
16 | "SilNex\\GuLa\\": "src"
17 | }
18 | },
19 | "extra": {
20 | "laravel": {
21 | "providers": [
22 | "SilNex\\GuLa\\GuLaServiceProvider"
23 | ]
24 | }
25 | },
26 | "autoload-dev": {
27 | "psr-4": {
28 | "SilNex\\GuLa\\Tests\\": "tests",
29 | "App\\": "vendor/orchestra/testbench-core/laravel/app"
30 | }
31 | },
32 | "require-dev": {
33 | "orchestra/testbench": "^5.0"
34 | }
35 | }
--------------------------------------------------------------------------------
/src/Models/Gnu/G5Login.php:
--------------------------------------------------------------------------------
1 | get()->toArray());
16 |
17 | foreach ($boards as $board) {
18 | $g5MyModelFile = app_path('G5Models/G5Write' . Str::title($board) . '.php');
19 | if (File::exists($g5MyModelFile)) {
20 | unlink($g5MyModelFile);
21 | }
22 | }
23 |
24 | Artisan::call('g5model:write-all');
25 |
26 | foreach ($boards as $board) {
27 | $g5MyModelFile = app_path('G5Models/G5Write' . Str::title($board) . '.php');
28 | $this->assertTrue(File::exists($g5MyModelFile));
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Models/Gnu/G5CertHistory.php:
--------------------------------------------------------------------------------
1 |
2 |
그누보드로 RESTfull api 개발을 위한 Laravel Models
3 | 4 | ## Installation 5 | 1. 패키지 설치 `composer require silnex/gula` 6 | 2. `.env` 설정 7 | ```env 8 | GULA_DB_HOST=gnuboard.db.host 9 | GULA_DB_PORT=3306 # (default: 3306) 10 | GULA_DB_DATABASE=gnuboard_db 11 | GULA_DB_USERNAME=gnuboard_db_user 12 | GULA_DB_PASSWORD=gnuboard_db_pass 13 | GULA_CHARSET=utf8mb4 # DB 문자셋 (default: utf8mb4) 14 | GULA_COLLATION=utf8mb4_unicode_ci # DB 문자셋 (default: utf8mb4_unicode_ci) 15 | ``` 16 | 17 | ## How to use 18 | 19 | ### Laravel의 Eloquent 모델을 이용해 데이터 접근 20 | ```php 21 | where('mb_id', '=', 'admin')->get(); 26 | 27 | // 영카트 28 | use SilNex\GuLa\Models\Young\G5ShopItem; 29 | $g5ShopItem = new G5ShopItem; 30 | $g5ShopItem->get(); 31 | ``` 32 | 자세한 사용법은 [Laravel Eloquent](https://laravel.kr/docs/eloquent) 문서를 참고 33 | 34 | ### Relationships 35 | Laravel의 모델의 Relation을 사용해 다른 테이블의 내용을 쉽게 가져올 수 있습니다. 36 | ```php 37 | where('mb_id', '=', 'admin')->first(); 42 | $admin->g5Points()->get(); 43 | ``` 44 | 45 | ### G5ModelFactory 46 | 미리 생성된 Model이 없는 경우나, 다른 DB에서 가져올 경우 `G5ModelFactory`를 통해 Model 인스턴스를 생성할 수 있습니다. 47 | ```php 48 | get(); 56 | ``` 57 | 58 | 혹은 이를 응용해 다음과 같은 방법도 가능합니다. 59 | ```php 60 | get(); 74 | } 75 | ``` 76 | 77 | ### 자동 릴레이션 78 | 그누보드에선 새로운 게시판을 만들때 마다 `g5_write_`으로 시작하는 테이블이 생성됩니다. 79 | GuLa에선 이를 자동으로 릴레이션 해줍니다. 80 | ```테이블 이름이 소문자, _, 숫자인 경우에만 자동 인식이 가능합니다.``` 81 | ```php 82 | where('mb_id', '=', 'admin')->first(); 89 | $admin->g5WriteFree()->first(); // g5_write_free의 mb_id가 admin인 게시글을 가져옵니다. 90 | 91 | // 여러 테이블에서 가져올 수 있습니다. 92 | $admin->with('g5WriteFree', 'g5WriteNotice', 'g5WriteQa')->get(); 93 | ``` 94 | 95 | ### 커스텀 모델 (테이블) 96 | 커스텀 모델을 직접 만들지 않고 커맨드로 생성 할 수 있습니다. 97 | #### 모델 생성 98 | 커맨드 `php artisan g5model:write {table_name}`를 입력하면 `app/G5Models`에 모델이 생성 됩니다. 99 | ##### 예시 100 | ```bash 101 | php artisan g5model:write my_g5_custom_table 102 | ``` 103 | ```php 104 | /** app/G5Models/MyG5CustomTable.php */ 105 | 106 | hasMany(G5WriteFree::class, 'wr_parent', 'wr_id')->where('wr_is_comment', '=', '1');; 152 | } 153 | 154 | /** 155 | * 댓글이라면, 게시글을 보여줌 156 | */ 157 | public function parent() 158 | { 159 | if ($this->wr_is_comment) { 160 | return $this->belongsTo(G5WriteFree::class, 'wr_id', 'wr_parent')->where('wr_is_comment', '=', '0');; 161 | } else { 162 | throw new \Exception("해당 글은 댓글이 아닙니다."); 163 | } 164 | } 165 | 166 | /** 167 | * 게시판에 첨부된 파일을 가져옴 168 | */ 169 | public function files() 170 | { 171 | return $this->hasMany(G5BoardFile::class, 'wr_id', 'wr_id')->where('bo_table', $this->bo_table); 172 | } 173 | } 174 | 175 | // Using 176 | $g5WriteFree = new G5WriteFree; 177 | $g5WriteFree->comments(); 178 | $g5WriteFree->first()->files(); 179 | ``` 180 | 181 | #### g5_board테이블에 있는 모든 게시판 생성 182 | `php artisan g5model:write-all` 명령어를 통해 자동으로 그누보드의 게시판 모델을 생성해 줄수 있습니다. 183 | 184 | ### Todo 185 | - [x] 그누보드 모델 추가 186 | - [x] Mass Assignment 추가 187 | - [x] 그누보드 DB connection 분리 188 | - [x] 로고제작 (임시용) 189 | - [x] 로고제작 (정식용) 190 | - [x] 모델 인스턴스 팩토리 추가 191 | - [x] 모델별 릴레이션 추가 192 | - [x] g5_write 테이블 자동 릴레이션 193 | - [x] 커스텀 모델 artisan:make 커맨드 추가 194 | - [x] DB에 있는 g5_write_ 테이블 모델 일괄 생성 커맨드 추가 195 | - [x] 테이블별 primaryKey 설정 196 | - [x] G5Write Model과 G5BoardFile의 연결 -------------------------------------------------------------------------------- /src/Models/Gnu/G5Member.php: -------------------------------------------------------------------------------- 1 | hasMany(G5Auth::class, 'mb_id', 'mb_id'); 84 | } 85 | 86 | public function g5Boards() 87 | { 88 | return $this->hasMany(G5Board::class, 'bo_admin', 'mb_id');; 89 | } 90 | 91 | public function g5BoardGoods() 92 | { 93 | return $this->hasMany(G5BoardGood::class, 'mb_id', 'mb_id'); 94 | } 95 | 96 | public function g5BoardNews() 97 | { 98 | return $this->hasMany(G5BoardNew::class, 'mb_id', 'mb_id'); 99 | } 100 | 101 | public function g5CertHistorys() 102 | { 103 | return $this->hasMany(G5CertHistory::class, 'mb_id', 'mb_id'); 104 | } 105 | 106 | public function g5Groups() 107 | { 108 | return $this->belongsToMany(G5Group::class, 'g5_group_member', 'mb_id', 'gr_id'); 109 | } 110 | 111 | public function g5Logins() 112 | { 113 | return $this->hasMany(G5Login::class, 'mb_id', 'mb_id'); 114 | } 115 | 116 | public function g5MemoReceivers() 117 | { 118 | return $this->hasMany(G5Memo::class, 'me_recv_mb_id', 'mb_id'); 119 | } 120 | 121 | public function g5MemoSenders() 122 | { 123 | return $this->hasMany(G5Memo::class, 'me_send_mb_id', 'mb_id'); 124 | } 125 | 126 | public function g5Points() 127 | { 128 | return $this->hasMany(G5Point::class, 'mb_id', 'mb_id'); 129 | } 130 | 131 | public function g5PollEtcs() 132 | { 133 | return $this->hasMany(G5PollEtc::class, 'mb_id', 'mb_id'); 134 | } 135 | 136 | public function g5Scraps() 137 | { 138 | return $this->hasMany(G5Scrap::class, 'mb_id', 'mb_id'); 139 | } 140 | 141 | public function g5Autosaves() 142 | { 143 | return $this->hasMany(G5Autosave::class, 'mb_id', 'mb_id'); 144 | } 145 | 146 | public function g5QaContents() 147 | { 148 | return $this->hasMany(G5QaContent::class, 'mb_id', 'mb_id'); 149 | } 150 | 151 | public function g5MemberSocialProfiles() 152 | { 153 | return $this->hasMany(G5MemberSocialProfiles::class, 'mb_id', 'mb_id'); 154 | } 155 | 156 | /** 157 | * Youngcart relation 158 | */ 159 | 160 | public function g5ShopCarts() 161 | { 162 | return $this->hasMany(G5ShopCart::class, 'mb_id', 'mb_id'); 163 | } 164 | 165 | public function g5ShopCategorys() 166 | { 167 | return $this->hasMany(G5ShopCategory::class, 'ca_mb_id', 'mb_id'); 168 | } 169 | 170 | public function g5ShopCoupons() 171 | { 172 | return $this->hasMany(G5ShopCoupon::class, 'mb_id', 'mb_id'); 173 | } 174 | 175 | public function g5ShopCouponLogs() 176 | { 177 | return $this->hasMany(G5ShopCouponLog::class, 'mb_id', 'mb_id'); 178 | } 179 | 180 | public function g5ShopItemUses() 181 | { 182 | return $this->hasMany(G5ShopItemUse::class, 'mb_id', 'mb_id'); 183 | } 184 | 185 | public function g5ShopItemQas() 186 | { 187 | return $this->hasMany(G5ShopItemQa::class, 'mb_id', 'mb_id'); 188 | } 189 | 190 | public function g5ShopOrders() 191 | { 192 | return $this->hasMany(G5ShopOrder::class, 'mb_id', 'mb_id'); 193 | } 194 | 195 | public function g5ShopOrderAddress() 196 | { 197 | return $this->hasMany(G5ShopOrderAddress::class, 'mb_id', 'mb_id'); 198 | } 199 | 200 | public function g5ShopOrderDatas() 201 | { 202 | return $this->hasMany(G5ShopOrderData::class, 'mb_id', 'mb_id'); 203 | } 204 | 205 | public function g5ShopOrderDeletes() 206 | { 207 | return $this->hasMany(G5ShopOrderDelete::class, 'mb_id', 'mb_id'); 208 | } 209 | 210 | public function g5ShopWishs() 211 | { 212 | return $this->hasMany(G5ShopWish::class, 'mb_id', 'mb_id'); 213 | } 214 | 215 | public function g5ShopOrderPostLogs() 216 | { 217 | return $this->hasMany(G5ShopOrderPostLog::class, 'mb_id', 'mb_id'); 218 | } 219 | 220 | public function isG5Write($string) 221 | { 222 | return substr($string, 0, 7) === 'g5Write'; 223 | } 224 | 225 | public function __get($key) 226 | { 227 | if ($this->isG5Write($key)) { 228 | return $this->$key()->get(); 229 | } 230 | parent::__get($key); 231 | } 232 | 233 | public function __call($method, $parameters) 234 | { 235 | if ($this->isG5Write($method)) { 236 | global $silnexGuLaTempTable; 237 | $class = 'App\\G5Models\\' . Str::studly($method); 238 | $silnexGuLaTempTable = Str::snake($method); 239 | 240 | if (!class_exists($class)) { 241 | $anonymousClass = new class extends G5Model 242 | { 243 | use BelongToG5Member; 244 | 245 | protected $guarded = []; 246 | protected $dates = ['wr_datetime']; 247 | 248 | public function __construct() 249 | { 250 | global $silnexGuLaTempTable; 251 | 252 | $this->setTable($silnexGuLaTempTable); 253 | parent::__construct(); 254 | } 255 | 256 | public function comments() 257 | { 258 | return $this->hasMany(self::class, 'wr_parent', 'wr_id')->where('wr_is_comment', '=', '1'); 259 | } 260 | 261 | public function parent() 262 | { 263 | if ($this->wr_is_comment) { 264 | return $this->belongsTo(self::class, 'wr_id', 'wr_parent')->where('wr_is_comment', '=', '0'); 265 | } else { 266 | throw new \Exception("해당 글은 댓글이 아닙니다."); 267 | } 268 | } 269 | 270 | public function files() 271 | { 272 | $bo_table = strtolower(explode('g5Write', self::class)[1]); 273 | return $this->hasMany(G5BoardFile::class, 'wr_id', 'wr_id')->where('bo_table', $bo_table); 274 | } 275 | }; 276 | $class = get_class($anonymousClass); 277 | } 278 | 279 | $this->g5WriteRelationalMethods[$method] = \Closure::bind(function () use ($class) { 280 | return $this->hasMany($class, 'mb_id', 'mb_id'); 281 | }, $this, get_class()); 282 | 283 | if (is_callable($this->g5WriteRelationalMethods[$method])) { 284 | return call_user_func_array($this->g5WriteRelationalMethods[$method], $parameters); 285 | } else { 286 | throw new \Exception("Dynamic method append error"); 287 | } 288 | } 289 | 290 | // parent::__call($method, $parameters); not work 291 | if (in_array($method, ['increment', 'decrement'])) { 292 | return $this->$method(...$parameters); 293 | } 294 | 295 | if ($resolver = (static::$relationResolvers[get_class($this)][$method] ?? null)) { 296 | return $resolver($this); 297 | } 298 | 299 | return $this->forwardCallTo($this->newQuery(), $method, $parameters); 300 | } 301 | } 302 | --------------------------------------------------------------------------------