Skip to content

Commit a0b3156

Browse files
committed
Merge branches 'master' and '45-setting-dbtype-to-enum-is-not-totally-correct' of github.com:php-openapi/yii2-openapi into 45-setting-dbtype-to-enum-is-not-totally-correct
2 parents c4b4cf6 + e993ed3 commit a0b3156

File tree

343 files changed

+9659
-681
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

343 files changed

+9659
-681
lines changed

.github/workflows/test.yml

+15-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ jobs:
2222
matrix:
2323
php-versions: ['7.4', '8.0', '8.1', '8.2', '8.3']
2424

25-
# TODO use cache
2625
steps:
2726
- uses: actions/checkout@v3
2827

@@ -42,6 +41,21 @@ jobs:
4241
- name: docker-compose up
4342
run: make up
4443

44+
# https://github.com/shivammathur/setup-php?tab=readme-ov-file#cache-composer-dependencies
45+
- name: Get composer cache directory
46+
id: composer-cache
47+
run: echo "dir=./tests/tmp/.composer/cache/files" >> $GITHUB_OUTPUT
48+
49+
- name: Make tests dir writable for restoring cache in next step
50+
run: make tests_dir_write_permission
51+
52+
- name: Cache dependencies
53+
uses: actions/cache@v4
54+
with:
55+
path: ${{ steps.composer-cache.outputs.dir }}
56+
key: ${{ runner.os }}-composer-${{ hashFiles('composer.json') }}
57+
restore-keys: ${{ runner.os }}-composer-
58+
4559
- name: Install Docker and composer dependencies
4660
run: docker-compose exec php php -v && make installdocker
4761

CONTRIBUTING.md

+9-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ cd yii2-openapi
1010
make clean_all
1111
make up
1212
make installdocker
13-
sudo chmod -R 777 tests/tmp/ # https://github.com/cebe/yii2-openapi/issues/156
13+
sudo chmod -R 777 tests/tmp/ # TODO avoid 777 https://github.com/cebe/yii2-openapi/issues/156
1414
make migrate
1515

1616
# to check everything is setup up correctly ensure all tests passes
@@ -95,6 +95,14 @@ with Zend OPcache v7.4.27, Copyright (c), by Zend Technologies
9595
with Xdebug v2.9.6, Copyright (c) 2002-2020, by Derick Rethans
9696
```
9797

98+
If a PHP version is changed as mentioned above, then following operations must be performed:
99+
100+
```
101+
rm -rf vendor
102+
rm -rf composer.lock
103+
composer install
104+
```
105+
98106
Issues and solutions
99107
--------------------
100108

Makefile

+8-3
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,15 @@ up:
3939
echo "Waiting for mariadb to start up..."
4040
docker-compose exec -T mysql timeout 60s sh -c "while ! (mysql -udbuser -pdbpass -h maria --execute 'SELECT 1;' > /dev/null 2>&1); do echo -n '.'; sleep 0.1 ; done; echo 'ok'" || (docker-compose ps; docker-compose logs; exit 1)
4141

42-
# Solution to problem https://stackoverflow.com/questions/50026939/php-mysqli-connect-authentication-method-unknown-to-the-client-caching-sha2-pa
43-
# if updated to PHP 7.4 or more, this command is not needed (TODO)
44-
docker-compose exec -T mysql timeout 60s sh -c "while ! (mysql --execute \"ALTER USER 'dbuser'@'%' IDENTIFIED WITH mysql_native_password BY 'dbpass';\" > /dev/null 2>&1); do echo -n '.'; sleep 0.1 ; done; echo 'ok'" || (docker-compose ps; docker-compose logs; exit 1)
42+
echo "Waiting for Mysql to start up..."
43+
docker-compose exec -T mysql timeout 60s sh -c "while ! (mysql -udbuser -pdbpass -h mysql --execute 'SELECT 1;' > /dev/null 2>&1); do echo -n '.'; sleep 0.1 ; done; echo 'ok'" || (docker-compose ps; docker-compose logs; exit 1)
4544

4645
cli:
4746
docker-compose exec --user=$(UID) php bash
4847

48+
cli_root:
49+
docker-compose exec --user="root" php bash
50+
4951
cli_mysql:
5052
docker-compose exec --user=$(UID) mysql bash
5153

@@ -57,6 +59,9 @@ migrate:
5759
installdocker:
5860
docker-compose run --user=$(UID) --rm php composer install && chmod +x tests/yii
5961

62+
tests_dir_write_permission:
63+
docker-compose run --user="root" --rm php chmod -R 777 tests/tmp/ # TODO avoid 777 https://github.com/cebe/yii2-openapi/issues/156
64+
6065
testdocker:
6166
docker-compose run --user=$(UID) --rm php sh -c 'vendor/bin/phpunit --repeat 3'
6267

README.md

+163-6
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@ return $config;
7676

7777
To use the web generator, open `index.php?r=gii` and select the `REST API Generator`.
7878

79-
On console you can run the generator with `./yii gii/api --openApiPath=@app/openapi.yaml`. Where `@app/openapi.yaml` should be the absolute path to your OpenAPI spec file. This can be JSON as well as YAML (see also [php-openapi/php-openapi](https://github.com/php-openapi/php-openapi/) for supported formats).
79+
On console, you can run the generator with `./yii gii/api --openApiPath=@app/openapi.yaml`. Where `@app/openapi.yaml`
80+
should be the absolute path to your OpenAPI spec file. This can be JSON as well as YAML (see
81+
also [php-openapi/php-openapi](https://github.com/php-openapi/php-openapi/) for supported formats).
8082

8183
Run `./yii gii/api --help` for all options. Example: Disable generation of migrations files `./yii gii/api --generateMigrations=0`
8284

@@ -212,6 +214,14 @@ Specify table indexes
212214
default: '{}'
213215
```
214216

217+
If raw DB expression is needed in index, then it must be for only one column. Example:
218+
219+
```yaml
220+
x-indexes:
221+
- "gin(to_tsvector('english', search::text)):search" # valid
222+
- "gin(to_tsvector('english', search::text)):search,column2" # invalid
223+
```
224+
215225
### `x-db-default-expression`
216226

217227
Ability to provide default value by database expression
@@ -309,15 +319,161 @@ Provide custom database table column name in case of relationship column. This w
309319
- x-fk-column-name: redelivery_of # this will create `redelivery_of` column instead of `redelivery_of_id`
310320
```
311321
322+
323+
### `x-deleted-schemas`
324+
325+
This is root level key used to generate "drop table" migration for the deleted component schema. If a component schema (DB model) is removed from OpenAPI spec then its following entities should be also deleted from the code:
326+
327+
- DB table (migrations)
328+
- model
329+
- faker
330+
331+
So to generate appropriate migration for the removed schema, explicitly setting schema name or schema name + custom table name is required in this key. Only then the migrations will be generated. It should be set as:
332+
333+
```yaml
334+
x-deleted-schemas:
335+
- Fruit # Example: table name is evaluated to `itt_fruits`, if `itt_` is prefix set in DB config
336+
- Mango: the_mango_table_name # custom table name; see `x-table` in README.md
337+
```
338+
339+
### `x-no-relation`
340+
341+
To differentiate a component schema property from one-to-many or many-to-many relation in favour of array(json) of
342+
related objects, `x-no-relation` (type: boolean, default: false) is used.
343+
344+
```yaml
345+
comments:
346+
type: array
347+
items:
348+
$ref: "#/components/schemas/Comment"
349+
```
350+
351+
This will not generate 'comments' column in database migrations. But it will generate `getComments()` relation in Yii model file.
352+
353+
In order to make it real database column, extension `x-no-relation` can be used.
354+
355+
```yaml
356+
comments:
357+
type: array
358+
x-no-relation: true
359+
items:
360+
$ref: "#/components/schemas/Comment"
361+
```
362+
363+
Database column type can be `array`, `json` etc. to store such data.
364+
365+
Now if the Comment schema from the above example is
366+
367+
```yaml
368+
Comment:
369+
properties:
370+
id:
371+
type: integer
372+
content:
373+
type: string
374+
```
375+
376+
then the value for `comments` can be
377+
378+
```json
379+
[
380+
{
381+
"id": 1,
382+
"content": "Hi there"
383+
},
384+
{
385+
"id": 2,
386+
"content": "Hi there 2"
387+
}
388+
]
389+
```
390+
391+
`x-no-relation` can be only used with OpenAPI schema data type `array`.
392+
393+
### `x-route`
394+
395+
To customize route (controller ID/action ID) for a path, use custom key `x-route` with value `<controller ID>/<action ID>`. It can be used for non-crud paths. It must be used under HTTP method key but not
396+
directly under the `paths` key of OpenAPI spec. Example:
397+
398+
```yaml
399+
paths:
400+
/payments/invoice/{invoice}:
401+
parameters:
402+
- name: invoice
403+
in: path
404+
description: lorem ipsum
405+
required: true
406+
schema:
407+
type: integer
408+
post:
409+
x-route: 'payments/invoice'
410+
summary: Pay Invoice
411+
description: Pay for Invoice with given invoice number
412+
requestBody:
413+
description: Record new payment for an invoice
414+
content:
415+
application/json:
416+
schema:
417+
$ref: '#/components/schemas/Payments'
418+
required: true
419+
responses:
420+
'200':
421+
description: Successfully paid the invoice
422+
content:
423+
application/json:
424+
schema:
425+
$ref: '#/components/schemas/Success'
426+
```
427+
428+
It won't generate `actionCreateInvoice` in `PaymentsController.php` file, but will generate `actionInvoice` instead in
429+
same file.
430+
431+
Generated URL rules config for above is (in `urls.rest.php` or pertinent file):
432+
```php
433+
'POST payments/invoice/<invoice:\d+>' => 'payments/invoice',
434+
'payments/invoice/<invoice:\d+>' => 'payments/options',
435+
```
436+
437+
Also, if same action is needed for HTTP GET and POST then use same value for `x-route`. Example:
438+
439+
```yaml
440+
paths:
441+
/a1/b1:
442+
get:
443+
x-route: 'abc/xyz'
444+
operationId: opnid1
445+
summary: List
446+
description: Lists
447+
responses:
448+
'200':
449+
description: The Response
450+
post:
451+
x-route: 'abc/xyz'
452+
operationId: opnid2
453+
summary: create
454+
description: create
455+
responses:
456+
'200':
457+
description: The Response
458+
```
459+
460+
Generated URL rules config for above is (in `urls.rest.php` or pertinent file):
461+
```php
462+
'GET a1/b1' => 'abc/xyz',
463+
'POST a1/b1' => 'abc/xyz',
464+
'a1/b1' => 'abc/options',
465+
```
466+
`x-route` does not support [Yii Modules](https://www.yiiframework.com/doc/guide/2.0/en/structure-modules).
467+
312468
## Many-to-Many relation definition
313469

314470
There are two ways for define many-to-many relations:
315471

316472
### Simple many-to-many without junction model
317473

318474
- property name for many-to-many relation should be equal lower-cased, pluralized related schema name
319-
320-
- referenced schema should contains mirrored reference to current schema
475+
476+
- referenced schema should contain mirrored reference to current schema
321477

322478
- migration for junction table can be generated automatically - table name should be [pluralized, lower-cased
323479
schema_name1]2[pluralized, lower-cased schema name2], in alphabetical order;
@@ -390,7 +546,7 @@ User:
390546
`NOT NULL` in DB migrations is determined by `nullable` and `required` properties of the OpenAPI schema.
391547
e.g. attribute = 'my_property'.
392548
393-
- If you define attribute neither "required" nor via "nullable", then it is by default `NULL`:
549+
- If you define attribute neither "required" nor via "nullable", then it is by default `NULL` ([opposite of OpenAPI spec](https://swagger.io/specification/v3/?sbsearch=nullable)):
394550
395551
```yaml
396552
ExampleSchema:
@@ -508,12 +664,13 @@ created_at:
508664
## Assumptions
509665

510666
When generating code from an OpenAPI description there are many possible ways to achive a fitting result.
511-
Thus there are some assumptions and limitations that are currently applied to make this work.
667+
Thus, there are some assumptions and limitations that are currently applied to make this work.
512668
Here is a (possibly incomplete) list:
513669

514670
- The current implementation works best with OpenAPI description that follows the [JSON:API](https://jsonapi.org/) guidelines.
515671
- The request and response format/schema is currently not extracted from OpenAPI schema and may need to be adjusted manually if it does not follow JSON:API
516-
- column/field/property with name `id` is considered as Primary Key by this library and it is automatically handled by DB/Yii; so remove it from validation `rules()`
672+
- column/field/property with name `id` is considered as Primary Key by this library, and it is automatically handled by
673+
DB/Yii; so remove it from validation `rules()`
517674
- other fields can currently be used as primary keys using the `x-pk` OpenAPI extension (see below) but it may not be work correctly in all cases, please report bugs if you find them.
518675

519676
Other things to keep in mind:

composer.json

+5-4
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,20 @@
1919
},
2020
"require": {
2121
"php": "^7.4 || ^8.0",
22-
"cebe/php-openapi": "^1.5.0",
22+
"cebe/php-openapi": "^1.7.0",
2323
"yiisoft/yii2": "~2.0.48",
2424
"yiisoft/yii2-gii": "~2.0.0 | ~2.1.0 | ~2.2.0| ~2.3.0",
2525
"laminas/laminas-code": ">=3.4 <=4.13",
26-
"php-openapi/yii2-fractal": "^1.0.0",
26+
"php-openapi/yii2-fractal": "^1.4",
2727
"fakerphp/faker": "^1.9",
28-
"sam-it/yii2-mariadb": "^2.0"
28+
"sam-it/yii2-mariadb": "^2.0",
29+
"symfony/var-exporter": "^5.4",
30+
"symfony/polyfill-php80": "^1.31"
2931
},
3032
"require-dev": {
3133
"cebe/indent": "*",
3234
"friendsofphp/php-cs-fixer": "~2.16",
3335
"phpunit/phpunit": "^8.0",
34-
"symfony/polyfill-php80": "^1.16",
3536
"yiisoft/yii2-gii": ">=2.1.0"
3637
},
3738
"autoload": {

docker-compose.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ services:
4545
ports:
4646
- '23306:3306'
4747
volumes:
48-
- ./tests/tmp/maria:/var/lib/mysql:rw
48+
- ./tests/tmp/mariadb:/var/lib/mariadb:rw
4949
environment:
5050
# TZ: UTC
5151
# MARIADB_ALLOW_EMPTY_PASSWORD: 1

src/db/ColumnSchema.php

+20
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,24 @@ class ColumnSchema extends \yii\db\ColumnSchema
2525
* ```
2626
*/
2727
public $xDbType;
28+
29+
/**
30+
* Used only for MySQL/MariaDB
31+
* @var array|null
32+
* [
33+
* index => int # position: starts from 1
34+
* after => ?string # after column
35+
* before => ?string # before column
36+
* ]
37+
* If `before` is null then column is last
38+
* If `after` is null then column is first
39+
* If both are null then table has only 1 column
40+
*/
41+
public ?array $fromPosition = null;
42+
public ?array $toPosition = null;
43+
44+
/**
45+
* From `$this->fromPosition` and `$this->toPosition` we can check if the position is changed or not. This is done in `BaseMigrationBuilder::setColumnsPositions()`
46+
*/
47+
public bool $isPositionChanged = false;
2848
}

0 commit comments

Comments
 (0)