Maurits van der Schee 6 years ago
parent
commit
067b93b799

+ 12
- 0
README.md View File

681
 
681
 
682
 You can parse this output to make form fields show up with a red border and their appropriate error message.
682
 You can parse this output to make form fields show up with a red border and their appropriate error message.
683
 
683
 
684
+### Multi Tenancy support
685
+
686
+You may use the "multiTenancy" middleware when you have a multi-tenant database. 
687
+If your tenants are identified by the "customer_id" column you can use the following handler:
688
+
689
+    'multiTenancy.handler' => function ($operation, $tableName) {
690
+        return ['customer_id' => 12];
691
+    },
692
+
693
+This construct adds a filter requiring "customer_id" to be "12" to every operation (except for "create").
694
+It also sets the column "customer_id" on "create" to "12" and removes the column from any other write operation.
695
+
684
 ## OpenAPI specification
696
 ## OpenAPI specification
685
 
697
 
686
 On the "/openapi" end-point the OpenAPI 3.0 (formerly called "Swagger") specification is served. 
698
 On the "/openapi" end-point the OpenAPI 3.0 (formerly called "Swagger") specification is served. 

+ 4
- 0
src/Tqdev/PhpCrudApi/Api.php View File

15
 use Tqdev\PhpCrudApi\Middleware\CorsMiddleware;
15
 use Tqdev\PhpCrudApi\Middleware\CorsMiddleware;
16
 use Tqdev\PhpCrudApi\Middleware\FirewallMiddleware;
16
 use Tqdev\PhpCrudApi\Middleware\FirewallMiddleware;
17
 use Tqdev\PhpCrudApi\Middleware\JwtAuthMiddleware;
17
 use Tqdev\PhpCrudApi\Middleware\JwtAuthMiddleware;
18
+use Tqdev\PhpCrudApi\Middleware\MultiTenancyMiddleware;
18
 use Tqdev\PhpCrudApi\Middleware\Router\SimpleRouter;
19
 use Tqdev\PhpCrudApi\Middleware\Router\SimpleRouter;
19
 use Tqdev\PhpCrudApi\Middleware\SanitationMiddleware;
20
 use Tqdev\PhpCrudApi\Middleware\SanitationMiddleware;
20
 use Tqdev\PhpCrudApi\Middleware\ValidationMiddleware;
21
 use Tqdev\PhpCrudApi\Middleware\ValidationMiddleware;
62
                 case 'sanitation':
63
                 case 'sanitation':
63
                     new SanitationMiddleware($router, $responder, $properties, $reflection);
64
                     new SanitationMiddleware($router, $responder, $properties, $reflection);
64
                     break;
65
                     break;
66
+                case 'multiTenancy':
67
+                    new MultiTenancyMiddleware($router, $responder, $properties, $reflection);
68
+                    break;
65
                 case 'authorization':
69
                 case 'authorization':
66
                     new AuthorizationMiddleware($router, $responder, $properties, $reflection);
70
                     new AuthorizationMiddleware($router, $responder, $properties, $reflection);
67
                     break;
71
                     break;

+ 0
- 4
src/Tqdev/PhpCrudApi/Column/ReflectionService.php View File

88
         return $this->database->removeTable($tableName);
88
         return $this->database->removeTable($tableName);
89
     }
89
     }
90
 
90
 
91
-    public function removeColumn(String $tableName, String $columnName): bool
92
-    {
93
-        return $this->getTable($tableName)->removeColumn($columnName);
94
-    }
95
 }
91
 }

+ 17
- 11
src/Tqdev/PhpCrudApi/Database/GenericDB.php View File

3
 
3
 
4
 use Tqdev\PhpCrudApi\Column\Reflection\ReflectedTable;
4
 use Tqdev\PhpCrudApi\Column\Reflection\ReflectedTable;
5
 use Tqdev\PhpCrudApi\Middleware\Communication\VariableStore;
5
 use Tqdev\PhpCrudApi\Middleware\Communication\VariableStore;
6
-use Tqdev\PhpCrudApi\Record\Condition\AndCondition;
7
 use Tqdev\PhpCrudApi\Record\Condition\ColumnCondition;
6
 use Tqdev\PhpCrudApi\Record\Condition\ColumnCondition;
8
 use Tqdev\PhpCrudApi\Record\Condition\Condition;
7
 use Tqdev\PhpCrudApi\Record\Condition\Condition;
9
 
8
 
98
         return $this->definition;
97
         return $this->definition;
99
     }
98
     }
100
 
99
 
101
-    private function addAuthorizationCondition(String $tableName, Condition $condition2): Condition
100
+    private function addMiddlewareConditions(String $tableName, Condition $condition): Condition
102
     {
101
     {
103
         $condition1 = VariableStore::get("authorization.conditions.$tableName");
102
         $condition1 = VariableStore::get("authorization.conditions.$tableName");
104
-        return $condition1 ? AndCondition::fromArray([$condition1, $condition2]) : $condition2;
103
+        if ($condition1) {
104
+            $condition = $condition->_and($condition1);
105
+        }
106
+        $condition2 = VariableStore::get("multiTenancy.conditions.$tableName");
107
+        if ($condition2) {
108
+            $condition = $condition->_and($condition2);
109
+        }
110
+        return $condition;
105
     }
111
     }
106
 
112
 
107
     public function createSingle(ReflectedTable $table, array $columnValues) /*: ?String*/
113
     public function createSingle(ReflectedTable $table, array $columnValues) /*: ?String*/
131
         $selectColumns = $this->columns->getSelect($table, $columnNames);
137
         $selectColumns = $this->columns->getSelect($table, $columnNames);
132
         $tableName = $table->getName();
138
         $tableName = $table->getName();
133
         $condition = new ColumnCondition($table->getPk(), 'eq', $id);
139
         $condition = new ColumnCondition($table->getPk(), 'eq', $id);
134
-        $condition = $this->addAuthorizationCondition($tableName, $condition);
140
+        $condition = $this->addMiddlewareConditions($tableName, $condition);
135
         $parameters = array();
141
         $parameters = array();
136
         $whereClause = $this->conditions->getWhereClause($condition, $parameters);
142
         $whereClause = $this->conditions->getWhereClause($condition, $parameters);
137
         $sql = 'SELECT ' . $selectColumns . ' FROM "' . $tableName . '" ' . $whereClause;
143
         $sql = 'SELECT ' . $selectColumns . ' FROM "' . $tableName . '" ' . $whereClause;
153
         $selectColumns = $this->columns->getSelect($table, $columnNames);
159
         $selectColumns = $this->columns->getSelect($table, $columnNames);
154
         $tableName = $table->getName();
160
         $tableName = $table->getName();
155
         $condition = new ColumnCondition($table->getPk(), 'in', implode(',', $ids));
161
         $condition = new ColumnCondition($table->getPk(), 'in', implode(',', $ids));
156
-        $condition = $this->addAuthorizationCondition($tableName, $condition);
162
+        $condition = $this->addMiddlewareConditions($tableName, $condition);
157
         $parameters = array();
163
         $parameters = array();
158
         $whereClause = $this->conditions->getWhereClause($condition, $parameters);
164
         $whereClause = $this->conditions->getWhereClause($condition, $parameters);
159
         $sql = 'SELECT ' . $selectColumns . ' FROM "' . $tableName . '" ' . $whereClause;
165
         $sql = 'SELECT ' . $selectColumns . ' FROM "' . $tableName . '" ' . $whereClause;
166
     public function selectCount(ReflectedTable $table, Condition $condition): int
172
     public function selectCount(ReflectedTable $table, Condition $condition): int
167
     {
173
     {
168
         $tableName = $table->getName();
174
         $tableName = $table->getName();
169
-        $condition = $this->addAuthorizationCondition($tableName, $condition);
175
+        $condition = $this->addMiddlewareConditions($tableName, $condition);
170
         $parameters = array();
176
         $parameters = array();
171
         $whereClause = $this->conditions->getWhereClause($condition, $parameters);
177
         $whereClause = $this->conditions->getWhereClause($condition, $parameters);
172
         $sql = 'SELECT COUNT(*) FROM "' . $tableName . '"' . $whereClause;
178
         $sql = 'SELECT COUNT(*) FROM "' . $tableName . '"' . $whereClause;
178
     {
184
     {
179
         $selectColumns = $this->columns->getSelect($table, $columnNames);
185
         $selectColumns = $this->columns->getSelect($table, $columnNames);
180
         $tableName = $table->getName();
186
         $tableName = $table->getName();
181
-        $condition = $this->addAuthorizationCondition($tableName, $condition);
187
+        $condition = $this->addMiddlewareConditions($tableName, $condition);
182
         $parameters = array();
188
         $parameters = array();
183
         $whereClause = $this->conditions->getWhereClause($condition, $parameters);
189
         $whereClause = $this->conditions->getWhereClause($condition, $parameters);
184
         $sql = 'SELECT ' . $selectColumns . ' FROM "' . $tableName . '"' . $whereClause;
190
         $sql = 'SELECT ' . $selectColumns . ' FROM "' . $tableName . '"' . $whereClause;
195
         }
201
         }
196
         $selectColumns = $this->columns->getSelect($table, $columnNames);
202
         $selectColumns = $this->columns->getSelect($table, $columnNames);
197
         $tableName = $table->getName();
203
         $tableName = $table->getName();
198
-        $condition = $this->addAuthorizationCondition($tableName, $condition);
204
+        $condition = $this->addMiddlewareConditions($tableName, $condition);
199
         $parameters = array();
205
         $parameters = array();
200
         $whereClause = $this->conditions->getWhereClause($condition, $parameters);
206
         $whereClause = $this->conditions->getWhereClause($condition, $parameters);
201
         $orderBy = $this->columns->getOrderBy($table, $columnOrdering);
207
         $orderBy = $this->columns->getOrderBy($table, $columnOrdering);
216
         $updateColumns = $this->columns->getUpdate($table, $columnValues);
222
         $updateColumns = $this->columns->getUpdate($table, $columnValues);
217
         $tableName = $table->getName();
223
         $tableName = $table->getName();
218
         $condition = new ColumnCondition($table->getPk(), 'eq', $id);
224
         $condition = new ColumnCondition($table->getPk(), 'eq', $id);
219
-        $condition = $this->addAuthorizationCondition($tableName, $condition);
225
+        $condition = $this->addMiddlewareConditions($tableName, $condition);
220
         $parameters = array_values($columnValues);
226
         $parameters = array_values($columnValues);
221
         $whereClause = $this->conditions->getWhereClause($condition, $parameters);
227
         $whereClause = $this->conditions->getWhereClause($condition, $parameters);
222
         $sql = 'UPDATE "' . $tableName . '" SET ' . $updateColumns . $whereClause;
228
         $sql = 'UPDATE "' . $tableName . '" SET ' . $updateColumns . $whereClause;
228
     {
234
     {
229
         $tableName = $table->getName();
235
         $tableName = $table->getName();
230
         $condition = new ColumnCondition($table->getPk(), 'eq', $id);
236
         $condition = new ColumnCondition($table->getPk(), 'eq', $id);
231
-        $condition = $this->addAuthorizationCondition($tableName, $condition);
237
+        $condition = $this->addMiddlewareConditions($tableName, $condition);
232
         $parameters = array();
238
         $parameters = array();
233
         $whereClause = $this->conditions->getWhereClause($condition, $parameters);
239
         $whereClause = $this->conditions->getWhereClause($condition, $parameters);
234
         $sql = 'DELETE FROM "' . $tableName . '" ' . $whereClause;
240
         $sql = 'DELETE FROM "' . $tableName . '" ' . $whereClause;
245
         $updateColumns = $this->columns->getIncrement($table, $columnValues);
251
         $updateColumns = $this->columns->getIncrement($table, $columnValues);
246
         $tableName = $table->getName();
252
         $tableName = $table->getName();
247
         $condition = new ColumnCondition($table->getPk(), 'eq', $id);
253
         $condition = new ColumnCondition($table->getPk(), 'eq', $id);
248
-        $condition = $this->addAuthorizationCondition($tableName, $condition);
254
+        $condition = $this->addMiddlewareConditions($tableName, $condition);
249
         $parameters = array_values($columnValues);
255
         $parameters = array_values($columnValues);
250
         $whereClause = $this->conditions->getWhereClause($condition, $parameters);
256
         $whereClause = $this->conditions->getWhereClause($condition, $parameters);
251
         $sql = 'UPDATE "' . $tableName . '" SET ' . $updateColumns . $whereClause;
257
         $sql = 'UPDATE "' . $tableName . '" SET ' . $updateColumns . $whereClause;

+ 1
- 1
src/Tqdev/PhpCrudApi/Middleware/AuthorizationMiddleware.php View File

30
             foreach ($table->columnNames() as $columnName) {
30
             foreach ($table->columnNames() as $columnName) {
31
                 $allowed = call_user_func($columnHandler, $operation, $tableName, $columnName);
31
                 $allowed = call_user_func($columnHandler, $operation, $tableName, $columnName);
32
                 if (!$allowed) {
32
                 if (!$allowed) {
33
-                    $this->reflection->removeColumn($tableName, $columnName);
33
+                    $table->removeColumn($columnName);
34
                 }
34
                 }
35
             }
35
             }
36
         }
36
         }

+ 4
- 1
tests/config/base.php View File

4
     'username' => 'php-crud-api',
4
     'username' => 'php-crud-api',
5
     'password' => 'php-crud-api',
5
     'password' => 'php-crud-api',
6
     'controllers' => 'records,columns,cache,openapi',
6
     'controllers' => 'records,columns,cache,openapi',
7
-    'middlewares' => 'cors,jwtAuth,basicAuth,authorization,validation,sanitation',
7
+    'middlewares' => 'cors,jwtAuth,basicAuth,authorization,validation,sanitation,multiTenancy',
8
     'jwtAuth.time' => '1538207605',
8
     'jwtAuth.time' => '1538207605',
9
     'jwtAuth.secret' => 'axpIrCGNGqxzx2R9dtXLIPUSqPo778uhb8CA0F4Hx',
9
     'jwtAuth.secret' => 'axpIrCGNGqxzx2R9dtXLIPUSqPo778uhb8CA0F4Hx',
10
     'basicAuth.passwordFile' => __DIR__ . DIRECTORY_SEPARATOR . '.htpasswd',
10
     'basicAuth.passwordFile' => __DIR__ . DIRECTORY_SEPARATOR . '.htpasswd',
23
     'validation.handler' => function ($operation, $tableName, $column, $value, $context) {
23
     'validation.handler' => function ($operation, $tableName, $column, $value, $context) {
24
         return ($column['name'] == 'post_id' && !is_numeric($value)) ? 'must be numeric' : true;
24
         return ($column['name'] == 'post_id' && !is_numeric($value)) ? 'must be numeric' : true;
25
     },
25
     },
26
+    'multiTenancy.handler' => function ($operation, $tableName) {
27
+        return ($tableName == 'kunsthåndværk') ? ['user_id' => 1] : [];
28
+    },
26
     'debug' => true,
29
     'debug' => true,
27
 ];
30
 ];

+ 6
- 3
tests/fixtures/blog_mysql.sql View File

152
 CREATE TABLE `kunsthåndværk` (
152
 CREATE TABLE `kunsthåndværk` (
153
   `id` varchar(36) NOT NULL,
153
   `id` varchar(36) NOT NULL,
154
   `Umlauts ä_ö_ü-COUNT` int(11) NOT NULL,
154
   `Umlauts ä_ö_ü-COUNT` int(11) NOT NULL,
155
+  `user_id` int(11) NOT NULL,
155
   `invisible` varchar(36),
156
   `invisible` varchar(36),
156
   PRIMARY KEY (`id`),
157
   PRIMARY KEY (`id`),
157
-  CONSTRAINT `kunsthåndværk_Umlauts ä_ö_ü-COUNT_fkey` UNIQUE (`Umlauts ä_ö_ü-COUNT`)
158
+  CONSTRAINT `kunsthåndværk_Umlauts ä_ö_ü-COUNT_fkey` UNIQUE (`Umlauts ä_ö_ü-COUNT`),
159
+  CONSTRAINT `kunsthåndværk_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)
158
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
160
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
159
 
161
 
160
-INSERT INTO `kunsthåndværk` (`id`, `Umlauts ä_ö_ü-COUNT`, `invisible`) VALUES
161
-('e42c77c6-06a4-4502-816c-d112c7142e6d', 1, NULL);
162
+INSERT INTO `kunsthåndværk` (`id`, `Umlauts ä_ö_ü-COUNT`, `user_id`, `invisible`) VALUES
163
+('e42c77c6-06a4-4502-816c-d112c7142e6d', 1, 1, NULL),
164
+('e31ecfe6-591f-4660-9fbd-1a232083037f', 2, 2, NULL);
162
 
165
 
163
 DROP TABLE IF EXISTS `invisibles`;
166
 DROP TABLE IF EXISTS `invisibles`;
164
 CREATE TABLE `invisibles` (
167
 CREATE TABLE `invisibles` (

+ 18
- 2
tests/fixtures/blog_pgsql.sql View File

159
 CREATE TABLE "kunsthåndværk" (
159
 CREATE TABLE "kunsthåndværk" (
160
   id character varying(36) NOT NULL,
160
   id character varying(36) NOT NULL,
161
   "Umlauts ä_ö_ü-COUNT" integer NOT NULL,
161
   "Umlauts ä_ö_ü-COUNT" integer NOT NULL,
162
+  user_id integer NOT NULL,
162
   invisible character varying(36)
163
   invisible character varying(36)
163
 );
164
 );
164
 
165
 
263
 -- Data for Name: kunsthåndværk; Type: TABLE DATA; Schema: public; Owner: postgres
264
 -- Data for Name: kunsthåndværk; Type: TABLE DATA; Schema: public; Owner: postgres
264
 --
265
 --
265
 
266
 
266
-INSERT INTO "kunsthåndværk" ("id", "Umlauts ä_ö_ü-COUNT", "invisible") VALUES
267
-('e42c77c6-06a4-4502-816c-d112c7142e6d', 1, NULL);
267
+INSERT INTO "kunsthåndværk" ("id", "Umlauts ä_ö_ü-COUNT", "user_id", "invisible") VALUES
268
+('e42c77c6-06a4-4502-816c-d112c7142e6d', 1, 1, NULL),
269
+('e31ecfe6-591f-4660-9fbd-1a232083037f', 2, 2, NULL);
268
 
270
 
269
 --
271
 --
270
 -- Data for Name: invisibles; Type: TABLE DATA; Schema: public; Owner: postgres
272
 -- Data for Name: invisibles; Type: TABLE DATA; Schema: public; Owner: postgres
429
 CREATE INDEX "kunsthåndværk_Umlauts ä_ö_ü-COUNT_idx" ON "kunsthåndværk" USING btree ("Umlauts ä_ö_ü-COUNT");
431
 CREATE INDEX "kunsthåndværk_Umlauts ä_ö_ü-COUNT_idx" ON "kunsthåndværk" USING btree ("Umlauts ä_ö_ü-COUNT");
430
 
432
 
431
 
433
 
434
+--
435
+-- Name: kunsthåndværk_user_id_idx; Type: INDEX; Schema: public; Owner: postgres; Tablespace:
436
+--
437
+
438
+CREATE INDEX "kunsthåndværk_user_id_idx" ON "kunsthåndværk" USING btree (user_id);
439
+
440
+
432
 --
441
 --
433
 -- Name: comments_post_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: postgres
442
 -- Name: comments_post_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: postgres
434
 --
443
 --
484
 ALTER TABLE ONLY "kunsthåndværk"
493
 ALTER TABLE ONLY "kunsthåndværk"
485
     ADD CONSTRAINT "kunsthåndværk_Umlauts ä_ö_ü-COUNT_uc" UNIQUE ("Umlauts ä_ö_ü-COUNT");
494
     ADD CONSTRAINT "kunsthåndværk_Umlauts ä_ö_ü-COUNT_uc" UNIQUE ("Umlauts ä_ö_ü-COUNT");
486
 
495
 
496
+--
497
+-- Name: kunsthåndværk_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: postgres
498
+--
499
+
500
+ALTER TABLE ONLY "kunsthåndværk"
501
+    ADD CONSTRAINT "kunsthåndværk_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(id);
502
+
487
 
503
 
488
 --
504
 --
489
 -- PostgreSQL database dump complete
505
 -- PostgreSQL database dump complete

+ 10
- 1
tests/fixtures/blog_sqlsrv.sql View File

224
 CREATE TABLE [kunsthåndværk](
224
 CREATE TABLE [kunsthåndværk](
225
 	[id] [nvarchar](36),
225
 	[id] [nvarchar](36),
226
 	[Umlauts ä_ö_ü-COUNT] [int] NOT NULL,
226
 	[Umlauts ä_ö_ü-COUNT] [int] NOT NULL,
227
+	[user_id] [int] NOT NULL,
227
 	[invisible] [nvarchar](36),
228
 	[invisible] [nvarchar](36),
228
 	CONSTRAINT [PK_kunsthåndværk]
229
 	CONSTRAINT [PK_kunsthåndværk]
229
 	PRIMARY KEY CLUSTERED([id] ASC)
230
 	PRIMARY KEY CLUSTERED([id] ASC)
294
 INSERT [barcodes] ([product_id], [hex], [bin]) VALUES (1, N'00ff01', 0x00ff01)
295
 INSERT [barcodes] ([product_id], [hex], [bin]) VALUES (1, N'00ff01', 0x00ff01)
295
 GO
296
 GO
296
 
297
 
297
-INSERT [kunsthåndværk] ([id], [Umlauts ä_ö_ü-COUNT], [invisible]) VALUES ('e42c77c6-06a4-4502-816c-d112c7142e6d', 1, NULL)
298
+INSERT [kunsthåndværk] ([id], [Umlauts ä_ö_ü-COUNT], [user_id], [invisible]) VALUES ('e42c77c6-06a4-4502-816c-d112c7142e6d', 1, 1, NULL)
299
+GO
300
+INSERT [kunsthåndværk] ([id], [Umlauts ä_ö_ü-COUNT], [user_id], [invisible]) VALUES ('e31ecfe6-591f-4660-9fbd-1a232083037f', 2, 2, NULL)
298
 GO
301
 GO
299
 
302
 
300
 INSERT [invisibles] ([id]) VALUES ('e42c77c6-06a4-4502-816c-d112c7142e6d')
303
 INSERT [invisibles] ([id]) VALUES ('e42c77c6-06a4-4502-816c-d112c7142e6d')
341
 
344
 
342
 ALTER TABLE [kunsthåndværk]  WITH CHECK ADD 	CONSTRAINT [UC_kunsthåndværk_Umlauts ä_ö_ü-COUNT] UNIQUE([Umlauts ä_ö_ü-COUNT])
345
 ALTER TABLE [kunsthåndværk]  WITH CHECK ADD 	CONSTRAINT [UC_kunsthåndværk_Umlauts ä_ö_ü-COUNT] UNIQUE([Umlauts ä_ö_ü-COUNT])
343
 GO
346
 GO
347
+
348
+ALTER TABLE [kunsthåndværk]  WITH CHECK ADD 	CONSTRAINT [FK_kunsthåndværk_users] FOREIGN KEY([user_id])
349
+REFERENCES [users] ([id])
350
+GO
351
+ALTER TABLE [kunsthåndværk] CHECK	CONSTRAINT [FK_kunsthåndværk_users]
352
+GO

+ 2
- 2
tests/functional/001_records/063_list_kunsthåndværk.log View File

2
 ===
2
 ===
3
 200
3
 200
4
 Content-Type: application/json
4
 Content-Type: application/json
5
-Content-Length: 86
5
+Content-Length: 98
6
 
6
 
7
-{"records":[{"id":"e42c77c6-06a4-4502-816c-d112c7142e6d","Umlauts ä_ö_ü-COUNT":1}]}
7
+{"records":[{"id":"e42c77c6-06a4-4502-816c-d112c7142e6d","Umlauts ä_ö_ü-COUNT":1,"user_id":1}]}

+ 1
- 1
tests/functional/001_records/064_add_kunsthåndværk.log View File

1
 POST /records/kunsthåndværk
1
 POST /records/kunsthåndværk
2
 
2
 
3
-{"id":"34451583-a747-4417-bdf0-bec7a5eacffa","Umlauts ä_ö_ü-COUNT":2}
3
+{"id":"34451583-a747-4417-bdf0-bec7a5eacffa","Umlauts ä_ö_ü-COUNT":3}
4
 ===
4
 ===
5
 200
5
 200
6
 Content-Type: application/json
6
 Content-Type: application/json

+ 2
- 2
tests/functional/003_columns/001_get_database.log View File

2
 ===
2
 ===
3
 200
3
 200
4
 Content-Type: application/json
4
 Content-Type: application/json
5
-Content-Length: 2224
5
+Content-Length: 2273
6
 
6
 
7
-{"name":"php-crud-api","tables":[{"name":"barcodes","columns":[{"name":"id","type":"integer","pk":true},{"name":"product_id","type":"integer","fk":"products"},{"name":"hex","type":"varchar","length":255},{"name":"bin","type":"blob"}]},{"name":"categories","columns":[{"name":"id","type":"integer","pk":true},{"name":"name","type":"varchar","length":255},{"name":"icon","type":"blob","nullable":true}]},{"name":"comments","columns":[{"name":"id","type":"integer","pk":true},{"name":"post_id","type":"integer","fk":"posts"},{"name":"message","type":"varchar","length":255}]},{"name":"countries","columns":[{"name":"id","type":"integer","pk":true},{"name":"name","type":"varchar","length":255},{"name":"shape","type":"geometry"}]},{"name":"events","columns":[{"name":"id","type":"integer","pk":true},{"name":"name","type":"varchar","length":255},{"name":"datetime","type":"timestamp"},{"name":"visitors","type":"integer"}]},{"name":"kunsthåndværk","columns":[{"name":"id","type":"varchar","length":36,"pk":true},{"name":"Umlauts ä_ö_ü-COUNT","type":"integer"}]},{"name":"nopk","columns":[{"name":"id","type":"varchar","length":36}]},{"name":"post_tags","columns":[{"name":"id","type":"integer","pk":true},{"name":"post_id","type":"integer","fk":"posts"},{"name":"tag_id","type":"integer","fk":"tags"}]},{"name":"posts","columns":[{"name":"id","type":"integer","pk":true},{"name":"user_id","type":"integer","fk":"users"},{"name":"category_id","type":"integer","fk":"categories"},{"name":"content","type":"varchar","length":255}]},{"name":"products","columns":[{"name":"id","type":"integer","pk":true},{"name":"name","type":"varchar","length":255},{"name":"price","type":"decimal","precision":10,"scale":2},{"name":"properties","type":"clob"},{"name":"created_at","type":"timestamp"},{"name":"deleted_at","type":"timestamp","nullable":true}]},{"name":"tags","columns":[{"name":"id","type":"integer","pk":true},{"name":"name","type":"varchar","length":255},{"name":"is_important","type":"boolean"}]},{"name":"users","columns":[{"name":"id","type":"integer","pk":true},{"name":"username","type":"varchar","length":255},{"name":"password","type":"varchar","length":255},{"name":"location","type":"geometry","nullable":true}]}]}
7
+{"name":"php-crud-api","tables":[{"name":"barcodes","columns":[{"name":"id","type":"integer","pk":true},{"name":"product_id","type":"integer","fk":"products"},{"name":"hex","type":"varchar","length":255},{"name":"bin","type":"blob"}]},{"name":"categories","columns":[{"name":"id","type":"integer","pk":true},{"name":"name","type":"varchar","length":255},{"name":"icon","type":"blob","nullable":true}]},{"name":"comments","columns":[{"name":"id","type":"integer","pk":true},{"name":"post_id","type":"integer","fk":"posts"},{"name":"message","type":"varchar","length":255}]},{"name":"countries","columns":[{"name":"id","type":"integer","pk":true},{"name":"name","type":"varchar","length":255},{"name":"shape","type":"geometry"}]},{"name":"events","columns":[{"name":"id","type":"integer","pk":true},{"name":"name","type":"varchar","length":255},{"name":"datetime","type":"timestamp"},{"name":"visitors","type":"integer"}]},{"name":"kunsthåndværk","columns":[{"name":"id","type":"varchar","length":36,"pk":true},{"name":"Umlauts ä_ö_ü-COUNT","type":"integer"},{"name":"user_id","type":"integer","fk":"users"}]},{"name":"nopk","columns":[{"name":"id","type":"varchar","length":36}]},{"name":"post_tags","columns":[{"name":"id","type":"integer","pk":true},{"name":"post_id","type":"integer","fk":"posts"},{"name":"tag_id","type":"integer","fk":"tags"}]},{"name":"posts","columns":[{"name":"id","type":"integer","pk":true},{"name":"user_id","type":"integer","fk":"users"},{"name":"category_id","type":"integer","fk":"categories"},{"name":"content","type":"varchar","length":255}]},{"name":"products","columns":[{"name":"id","type":"integer","pk":true},{"name":"name","type":"varchar","length":255},{"name":"price","type":"decimal","precision":10,"scale":2},{"name":"properties","type":"clob"},{"name":"created_at","type":"timestamp"},{"name":"deleted_at","type":"timestamp","nullable":true}]},{"name":"tags","columns":[{"name":"id","type":"integer","pk":true},{"name":"name","type":"varchar","length":255},{"name":"is_important","type":"boolean"}]},{"name":"users","columns":[{"name":"id","type":"integer","pk":true},{"name":"username","type":"varchar","length":255},{"name":"password","type":"varchar","length":255},{"name":"location","type":"geometry","nullable":true}]}]}

Loading…
Cancel
Save