Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
SOHELAHMED7 committed Nov 13, 2024
2 parents 1c86e8e + a16ac6c commit 592b309
Show file tree
Hide file tree
Showing 262 changed files with 7,398 additions and 499 deletions.
2 changes: 1 addition & 1 deletion .env.dist
Original file line number Diff line number Diff line change
@@ -1 +1 @@
PHP_VERSION=7.4
PHP_VERSION=8.3
16 changes: 15 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ jobs:
matrix:
php-versions: ['7.4', '8.0', '8.1', '8.2', '8.3']

# TODO use cache
steps:
- uses: actions/checkout@v3

Expand All @@ -42,6 +41,21 @@ jobs:
- name: docker-compose up
run: make up

# https://github.com/shivammathur/setup-php?tab=readme-ov-file#cache-composer-dependencies
- name: Get composer cache directory
id: composer-cache
run: echo "dir=./tests/tmp/.composer/cache/files" >> $GITHUB_OUTPUT

- name: Make tests dir writable for restoring cache in next step
run: make tests_dir_write_permission

- name: Cache dependencies
uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('composer.json') }}
restore-keys: ${{ runner.os }}-composer-

- name: Install Docker and composer dependencies
run: docker-compose exec php php -v && make installdocker

Expand Down
10 changes: 9 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ cd yii2-openapi
make clean_all
make up
make installdocker
sudo chmod -R 777 tests/tmp/ # https://github.com/cebe/yii2-openapi/issues/156
sudo chmod -R 777 tests/tmp/ # TODO avoid 777 https://github.com/cebe/yii2-openapi/issues/156
make migrate

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

If a PHP version is changed as mentioned above, then following operations must be performed:

```
rm -rf vendor
rm -rf composer.lock
composer install
```

Issues and solutions
--------------------

Expand Down
11 changes: 8 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,15 @@ up:
echo "Waiting for mariadb to start up..."
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)

# Solution to problem https://stackoverflow.com/questions/50026939/php-mysqli-connect-authentication-method-unknown-to-the-client-caching-sha2-pa
# if updated to PHP 7.4 or more, this command is not needed (TODO)
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)
echo "Waiting for Mysql to start up..."
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)

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

cli_root:
docker-compose exec --user="root" php bash

cli_mysql:
docker-compose exec --user=$(UID) mysql bash

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

tests_dir_write_permission:
docker-compose run --user="root" --rm php chmod -R 777 tests/tmp/ # TODO avoid 777 https://github.com/cebe/yii2-openapi/issues/156

testdocker:
docker-compose run --user=$(UID) --rm php sh -c 'vendor/bin/phpunit --repeat 3'

Expand Down
165 changes: 152 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ REST API application generator for Yii2, openapi 3.0 YAML -> Yii2.

Base on [Gii, the Yii Framework Code Generator](https://www.yiiframework.com/extension/yiisoft/yii2-gii).

[![Latest Stable Version](https://poser.pugx.org/cebe/yii2-openapi/v/stable)](https://packagist.org/packages/cebe/yii2-openapi)
[![Latest Alpha Version](https://poser.pugx.org/cebe/yii2-openapi/v/unstable)](https://packagist.org/packages/cebe/yii2-openapi)
[![Total Downloads](https://poser.pugx.org/cebe/yii2-openapi/downloads)](https://packagist.org/packages/cebe/yii2-openapi)
[![License](https://poser.pugx.org/cebe/yii2-openapi/license)](https://packagist.org/packages/cebe/yii2-openapi)
![yii2-openapi](https://github.com/cebe/yii2-openapi/workflows/yii2-openapi/badge.svg?branch=wip)
[![Latest Stable Version](https://poser.pugx.org/php-openapi/yii2-openapi/v/stable)](https://packagist.org/packages/php-openapi/yii2-openapi)
[![Latest Alpha Version](https://poser.pugx.org/php-openapi/yii2-openapi/v/unstable)](https://packagist.org/packages/php-openapi/yii2-openapi)
[![Total Downloads](https://poser.pugx.org/php-openapi/yii2-openapi/downloads)](https://packagist.org/packages/php-openapi/yii2-openapi)
[![License](https://poser.pugx.org/php-openapi/yii2-openapi/license)](https://packagist.org/packages/php-openapi/yii2-openapi)
![yii2-openapi](https://github.com/php-openapi/yii2-openapi/workflows/yii2-openapi/badge.svg?branch=wip)

## TLDR; what is this?

A code generator for OpenAPI and Yii Framework based PHP API application.

Input: [OpenAPI 3.0 YAML or JSON](https://github.com/OAI/OpenAPI-Specification#the-openapi-specification) (via [cebe/php-openapi](https://github.com/cebe/php-openapi))
Input: [OpenAPI 3.0 YAML or JSON](https://github.com/OAI/OpenAPI-Specification#the-openapi-specification) (via [cebe/php-openapi](https://github.com/php-openapi/php-openapi))

Output: Yii Framework Application with Controllers, Models, database schema

Expand All @@ -41,7 +41,7 @@ Currently available features:
## Usage

You can use this package in your existing application or start a new project using the
[yii2-app-api](https://github.com/cebe/yii2-app-api) application template.
[yii2-app-api](https://github.com/php-openapi/yii2-app-api) application template.
For usage of the template, see instructions in the template repo readme.

In your existing Yii application config (works for console as well as web):
Expand Down Expand Up @@ -76,7 +76,9 @@ return $config;

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

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 [cebe/php-openapi](https://github.com/cebe/php-openapi/) for supported formats).
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).

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

Expand Down Expand Up @@ -212,6 +214,14 @@ Specify table indexes
default: '{}'
```

If raw DB expression is needed in index, then it must be for only one column. Example:

```yaml
x-indexes:
- "gin(to_tsvector('english', search::text)):search" # valid
- "gin(to_tsvector('english', search::text)):search,column2" # invalid
```

### `x-db-default-expression`

Ability to provide default value by database expression
Expand Down Expand Up @@ -326,6 +336,134 @@ x-deleted-schemas:
- Mango: the_mango_table_name # custom table name; see `x-table` in README.md
```
### `x-no-relation`

To differentiate a component schema property from one-to-many or many-to-many relation in favour of array(json) of
related objects, `x-no-relation` (type: boolean, default: false) is used.

```yaml
comments:
type: array
items:
$ref: "#/components/schemas/Comment"
```

This will not generate 'comments' column in database migrations. But it will generate `getComments()` relation in Yii model file.

In order to make it real database column, extension `x-no-relation` can be used.

```yaml
comments:
type: array
x-no-relation: true
items:
$ref: "#/components/schemas/Comment"
```

Database column type can be `array`, `json` etc. to store such data.

Now if the Comment schema from the above example is

```yaml
Comment:
properties:
id:
type: integer
content:
type: string
```

then the value for `comments` can be

```json
[
{
"id": 1,
"content": "Hi there"
},
{
"id": 2,
"content": "Hi there 2"
}
]
```

`x-no-relation` can be only used with OpenAPI schema data type `array`.

### `x-route`

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
directly under the `paths` key of OpenAPI spec. Example:

```yaml
paths:
/payments/invoice/{invoice}:
parameters:
- name: invoice
in: path
description: lorem ipsum
required: true
schema:
type: integer
post:
x-route: 'payments/invoice'
summary: Pay Invoice
description: Pay for Invoice with given invoice number
requestBody:
description: Record new payment for an invoice
content:
application/json:
schema:
$ref: '#/components/schemas/Payments'
required: true
responses:
'200':
description: Successfully paid the invoice
content:
application/json:
schema:
$ref: '#/components/schemas/Success'
```

It won't generate `actionCreateInvoice` in `PaymentsController.php` file, but will generate `actionInvoice` instead in
same file.

Generated URL rules config for above is (in `urls.rest.php` or pertinent file):
```php
'POST payments/invoice/<invoice:\d+>' => 'payments/invoice',
'payments/invoice/<invoice:\d+>' => 'payments/options',
```

Also, if same action is needed for HTTP GET and POST then use same value for `x-route`. Example:

```yaml
paths:
/a1/b1:
get:
x-route: 'abc/xyz'
operationId: opnid1
summary: List
description: Lists
responses:
'200':
description: The Response
post:
x-route: 'abc/xyz'
operationId: opnid2
summary: create
description: create
responses:
'200':
description: The Response
```

Generated URL rules config for above is (in `urls.rest.php` or pertinent file):
```php
'GET a1/b1' => 'abc/xyz',
'POST a1/b1' => 'abc/xyz',
'a1/b1' => 'abc/options',
```
`x-route` does not support [Yii Modules](https://www.yiiframework.com/doc/guide/2.0/en/structure-modules).

## Many-to-Many relation definition

Expand All @@ -334,8 +472,8 @@ There are two ways for define many-to-many relations:
### Simple many-to-many without junction model

- property name for many-to-many relation should be equal lower-cased, pluralized related schema name
- referenced schema should contains mirrored reference to current schema

- referenced schema should contain mirrored reference to current schema

- migration for junction table can be generated automatically - table name should be [pluralized, lower-cased
schema_name1]2[pluralized, lower-cased schema name2], in alphabetical order;
Expand Down Expand Up @@ -408,7 +546,7 @@ User:
`NOT NULL` in DB migrations is determined by `nullable` and `required` properties of the OpenAPI schema.
e.g. attribute = 'my_property'.
- If you define attribute neither "required" nor via "nullable", then it is by default `NULL`:
- 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)):
```yaml
ExampleSchema:
Expand Down Expand Up @@ -526,12 +664,13 @@ created_at:
## Assumptions

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

- The current implementation works best with OpenAPI description that follows the [JSON:API](https://jsonapi.org/) guidelines.
- 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
- 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()`
- 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()`
- 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.

Other things to keep in mind:
Expand Down
11 changes: 6 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "cebe/yii2-openapi",
"name": "php-openapi/yii2-openapi",
"description": "Generate full REST API application from OpenAPI 3 specification.",
"keywords": ["yii2", "rest", "openapi"],
"homepage": "https://github.com/cebe/yii2-openapi#readme",
Expand All @@ -19,19 +19,20 @@
},
"require": {
"php": "^7.4 || ^8.0",
"cebe/php-openapi": "^1.5.0",
"cebe/php-openapi": "^1.7.0",
"yiisoft/yii2": "~2.0.48",
"yiisoft/yii2-gii": "~2.0.0 | ~2.1.0 | ~2.2.0| ~2.3.0",
"laminas/laminas-code": ">=3.4 <=4.13",
"insolita/yii2-fractal": "^1.0.0",
"php-openapi/yii2-fractal": "^1.0.0",
"fakerphp/faker": "^1.9",
"sam-it/yii2-mariadb": "^2.0"
"sam-it/yii2-mariadb": "^2.0",
"symfony/var-exporter": "^5.4",
"symfony/polyfill-php80": "^1.30"
},
"require-dev": {
"cebe/indent": "*",
"friendsofphp/php-cs-fixer": "~2.16",
"phpunit/phpunit": "^8.0",
"symfony/polyfill-php80": "^1.16",
"yiisoft/yii2-gii": ">=2.1.0"
},
"autoload": {
Expand Down
6 changes: 3 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
version: "3.5"
services:
php:
image: yii2-openapi-php:${PHP_VERSION:-7.4}
image: yii2-openapi-php:${PHP_VERSION:-8.3}
build:
dockerfile: tests/docker/Dockerfile
context: .
args:
- BUILD_PHP_VERSION=${PHP_VERSION:-7.4}
- BUILD_PHP_VERSION=${PHP_VERSION:-8.3}
extra_hosts: # https://stackoverflow.com/a/67158212/1106908
- "host.docker.internal:host-gateway"
volumes:
Expand Down Expand Up @@ -45,7 +45,7 @@ services:
ports:
- '23306:3306'
volumes:
- ./tests/tmp/maria:/var/lib/mysql:rw
- ./tests/tmp/mariadb:/var/lib/mariadb:rw
environment:
# TZ: UTC
# MARIADB_ALLOW_EMPTY_PASSWORD: 1
Expand Down
20 changes: 20 additions & 0 deletions src/db/ColumnSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,24 @@ class ColumnSchema extends \yii\db\ColumnSchema
* ```
*/
public $xDbType;

/**
* Used only for MySQL/MariaDB
* @var array|null
* [
* index => int # position: starts from 1
* after => ?string # after column
* before => ?string # before column
* ]
* If `before` is null then column is last
* If `after` is null then column is first
* If both are null then table has only 1 column
*/
public ?array $fromPosition = null;
public ?array $toPosition = null;

/**
* From `$this->fromPosition` and `$this->toPosition` we can check if the position is changed or not. This is done in `BaseMigrationBuilder::setColumnsPositions()`
*/
public bool $isPositionChanged = false;
}
Loading

0 comments on commit 592b309

Please sign in to comment.