added static php-crud-api
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# PHP-CRUD-API
|
||||
|
||||
Single file PHP 7 script that adds a REST API to a MySQL/MariaDB, PostgreSQL, SQL Server or SQLite database.
|
||||
Single file PHP 7 script that adds a REST API to a MySQL 5.6 InnoDB database. PostgreSQL 9.1 and MS SQL Server 2012 are fully supported.
|
||||
|
||||
NB: This is the [TreeQL](https://treeql.org) reference implementation in PHP.
|
||||
|
||||
@@ -27,11 +27,10 @@ There are also proof-of-concept ports of this script that only support basic RES
|
||||
|
||||
## Requirements
|
||||
|
||||
- PHP 7.0 or higher with PDO drivers enabled for one of these database systems:
|
||||
- MySQL 5.6 / MariaDB 10.0 or higher for spatial features in MySQL
|
||||
- PostgreSQL 9.1 or higher with PostGIS 2.0 or higher for spatial features
|
||||
- SQL Server 2012 or higher (2017 for Linux support)
|
||||
- SQLite 3.16 or higher (spatial features NOT supported)
|
||||
- PHP 7.0 or higher with PDO drivers for MySQL, PgSQL or SqlSrv enabled
|
||||
- MySQL 5.6 / MariaDB 10.0 or higher for spatial features in MySQL
|
||||
- PostGIS 2.0 or higher for spatial features in PostgreSQL 9.1 or higher
|
||||
- SQL Server 2012 or higher (2017 for Linux support)
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -53,11 +52,6 @@ Alternatively you can integrate this project into the web framework of your choi
|
||||
- [Automatic REST API for Symfony 4](https://tqdev.com/2019-automatic-rest-api-symfony)
|
||||
- [Automatic REST API for SlimPHP 4](https://tqdev.com/2019-automatic-api-slimphp-4)
|
||||
|
||||
In these integrations [Composer](https://getcomposer.org/) is used to load this project as a dependency.
|
||||
|
||||
For people that don't use composer, the file "`api.include.php`" is provided. This file contains everything
|
||||
from "`api.php`" except the configuration from "`src/index.php`" and can be used by PHP's "include".
|
||||
|
||||
## Configuration
|
||||
|
||||
Edit the following lines in the bottom of the file "`api.php`":
|
||||
@@ -70,8 +64,8 @@ Edit the following lines in the bottom of the file "`api.php`":
|
||||
|
||||
These are all the configuration options and their default value between brackets:
|
||||
|
||||
- "driver": `mysql`, `pgsql`, `sqlsrv` or `sqlite` (`mysql`)
|
||||
- "address": Hostname (or filename) of the database server (`localhost`)
|
||||
- "driver": `mysql`, `pgsql` or `sqlsrv` (`mysql`)
|
||||
- "address": Hostname of the database server (`localhost`)
|
||||
- "port": TCP port of the database server (defaults to driver default)
|
||||
- "username": Username of the user connecting to the database (no default)
|
||||
- "password": Password of the user connecting to the database (no default)
|
||||
@@ -83,33 +77,19 @@ These are all the configuration options and their default value between brackets
|
||||
- "cacheType": `TempFile`, `Redis`, `Memcache`, `Memcached` or `NoCache` (`TempFile`)
|
||||
- "cachePath": Path/address of the cache (defaults to system's temp directory)
|
||||
- "cacheTime": Number of seconds the cache is valid (`10`)
|
||||
- "debug": Show errors in the "X-Exception" headers (`false`)
|
||||
- "debug": Show errors in the "X-Debug-Info" header (`false`)
|
||||
- "basePath": URI base path of the API (determined using PATH_INFO by default)
|
||||
|
||||
All configuration options are also available as environment variables. Write the config option with capitals, a "PHP_CRUD_API_" prefix and underscores for word breakes, so for instance:
|
||||
|
||||
- PHP_CRUD_API_DRIVER=mysql
|
||||
- PHP_CRUD_API_ADDRESS=localhost
|
||||
- PHP_CRUD_API_PORT=3306
|
||||
- PHP_CRUD_API_DATABASE=php-crud-api
|
||||
- PHP_CRUD_API_USERNAME=php-crud-api
|
||||
- PHP_CRUD_API_PASSWORD=php-crud-api
|
||||
- PHP_CRUD_API_DEBUG=1
|
||||
|
||||
The environment variables take precedence over the PHP configuration.
|
||||
|
||||
## Limitations
|
||||
|
||||
These limitation and constrains apply:
|
||||
|
||||
- Primary keys should either be auto-increment (from 1 to 2^53) or UUID
|
||||
- Composite primary and composite foreign keys are not supported
|
||||
- Composite primary or foreign keys are not supported
|
||||
- Complex writes (transactions) are not supported
|
||||
- Complex queries calling functions (like "concat" or "sum") are not supported
|
||||
- Database must support and define foreign key constraints
|
||||
- SQLite cannot have bigint typed auto incrementing primary keys
|
||||
- SQLite does not support altering table columns (structure)
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
The following features are supported:
|
||||
@@ -119,7 +99,7 @@ The following features are supported:
|
||||
- Supports POST variables as input (x-www-form-urlencoded)
|
||||
- Supports a JSON object as input
|
||||
- Supports a JSON array as input (batch insert)
|
||||
- Sanitize and validate input using type rules and callbacks
|
||||
- Sanitize and validate input using callbacks
|
||||
- Permission system for databases, tables, columns and records
|
||||
- Multi-tenant single and multi database layouts are supported
|
||||
- Multi-domain CORS support for cross-domain requests
|
||||
@@ -292,9 +272,8 @@ Examples of filter usage are:
|
||||
GET /records/categories?filter=name,eq,Internet
|
||||
GET /records/categories?filter=name,sw,Inter
|
||||
GET /records/categories?filter=id,le,1
|
||||
GET /records/categories?filter=id,ngt,1
|
||||
GET /records/categories?filter=id,bt,0,1
|
||||
GET /records/categories?filter=id,in,0,1
|
||||
GET /records/categories?filter=id,ngt,2
|
||||
GET /records/categories?filter=id,bt,1,1
|
||||
|
||||
Output:
|
||||
|
||||
@@ -323,7 +302,7 @@ As you see we added a number to the "filter" parameter to indicate that "OR" ins
|
||||
Note that you can also repeat "filter1" and create an "AND" within an "OR". Since you can also go one level deeper
|
||||
by adding a letter (a-f) you can create almost any reasonably complex condition tree.
|
||||
|
||||
NB: You can only filter on the requested table (not on it's included tables) and filters are only applied on list calls.
|
||||
NB: You can only filter on the requested table (not on it's included) and filters are only applied on list calls.
|
||||
|
||||
### Column selection
|
||||
|
||||
@@ -605,7 +584,6 @@ The GeoJSON functionality is enabled by default, but can be disabled using the "
|
||||
You can enable the following middleware using the "middlewares" config parameter:
|
||||
|
||||
- "firewall": Limit access to specific IP addresses
|
||||
- "sslRedirect": Force connection over HTTPS instead of HTTP
|
||||
- "cors": Support for CORS requests (enabled by default)
|
||||
- "xsrf": Block XSRF attacks using the 'Double Submit Cookie' method
|
||||
- "ajaxOnly": Restrict non-AJAX requests to prevent XSRF attacks
|
||||
@@ -614,14 +592,13 @@ You can enable the following middleware using the "middlewares" config parameter
|
||||
- "basicAuth": Support for "Basic Authentication"
|
||||
- "reconnect": Reconnect to the database with different parameters
|
||||
- "authorization": Restrict access to certain tables or columns
|
||||
- "validation": Return input validation errors for custom rules and default type rules
|
||||
- "validation": Return input validation errors for custom rules
|
||||
- "ipAddress": Fill a protected field with the IP address on create
|
||||
- "sanitation": Apply input sanitation on create and update
|
||||
- "multiTenancy": Restricts tenants access in a multi-tenant scenario
|
||||
- "pageLimits": Restricts list operations to prevent database scraping
|
||||
- "joinLimits": Restricts join parameters to prevent database scraping
|
||||
- "customization": Provides handlers for request and response customization
|
||||
- "xml": Translates all input and output from JSON to XML
|
||||
|
||||
The "middlewares" config parameter is a comma separated list of enabled middlewares.
|
||||
You can tune the middleware behavior using middleware specific configuration parameters:
|
||||
@@ -629,7 +606,7 @@ You can tune the middleware behavior using middleware specific configuration par
|
||||
- "firewall.reverseProxy": Set to "true" when a reverse proxy is used ("")
|
||||
- "firewall.allowedIpAddresses": List of IP addresses that are allowed to connect ("")
|
||||
- "cors.allowedOrigins": The origins allowed in the CORS headers ("*")
|
||||
- "cors.allowHeaders": The headers allowed in the CORS request ("Content-Type, X-XSRF-TOKEN, X-Authorization")
|
||||
- "cors.allowHeaders": The headers allowed in the CORS request ("Content-Type, X-XSRF-TOKEN")
|
||||
- "cors.allowMethods": The methods allowed in the CORS request ("OPTIONS, GET, PUT, POST, DELETE, PATCH")
|
||||
- "cors.allowCredentials": To allow credentials in the CORS request ("true")
|
||||
- "cors.exposeHeaders": Whitelist headers that browsers are allowed to access ("")
|
||||
@@ -645,8 +622,6 @@ You can tune the middleware behavior using middleware specific configuration par
|
||||
- "dbAuth.usernameColumn": The users table column that holds usernames ("username")
|
||||
- "dbAuth.passwordColumn": The users table column that holds passwords ("password")
|
||||
- "dbAuth.returnedColumns": The columns returned on successful login, empty means 'all' ("")
|
||||
- "dbAuth.registerUser": JSON user data (or "1") in case you want the /register endpoint enabled ("")
|
||||
- "dbAuth.passwordLength": Minimum length that the password must have ("12")
|
||||
- "dbAuth.sessionName": The name of the PHP session that is started ("")
|
||||
- "jwtAuth.mode": Set to "optional" if you want to allow anonymous access ("required")
|
||||
- "jwtAuth.header": Name of the header containing the JWT token ("X-Authorization")
|
||||
@@ -670,16 +645,11 @@ You can tune the middleware behavior using middleware specific configuration par
|
||||
- "reconnect.passwordHandler": Handler to implement retrieval of the database password ("")
|
||||
- "authorization.tableHandler": Handler to implement table authorization rules ("")
|
||||
- "authorization.columnHandler": Handler to implement column authorization rules ("")
|
||||
- "authorization.pathHandler": Handler to implement path authorization rules ("")
|
||||
- "authorization.recordHandler": Handler to implement record authorization filter rules ("")
|
||||
- "validation.handler": Handler to implement validation rules for input values ("")
|
||||
- "validation.types": Types to enable type validation for, empty means 'none' ("all")
|
||||
- "validation.tables": Tables to enable type validation for, empty means 'none' ("all")
|
||||
- "ipAddress.tables": Tables to search for columns to override with IP address ("")
|
||||
- "ipAddress.columns": Columns to protect and override with the IP address on create ("")
|
||||
- "sanitation.handler": Handler to implement sanitation rules for input values ("")
|
||||
- "sanitation.types": Types to enable type sanitation for, empty means 'none' ("all")
|
||||
- "sanitation.tables": Tables to enable type sanitation for, empty means 'none' ("all")
|
||||
- "multiTenancy.handler": Handler to implement simple multi-tenancy rules ("")
|
||||
- "pageLimits.pages": The maximum page number that a list operation allows ("100")
|
||||
- "pageLimits.records": The maximum number of records returned by a list operation ("1000")
|
||||
@@ -688,7 +658,6 @@ You can tune the middleware behavior using middleware specific configuration par
|
||||
- "joinLimits.records": The maximum number of records returned for a joined entity ("1000")
|
||||
- "customization.beforeHandler": Handler to implement request customization ("")
|
||||
- "customization.afterHandler": Handler to implement response customization ("")
|
||||
- "xml.types": JSON types that should be added to the XML type attribute ("null,array")
|
||||
|
||||
If you don't specify these parameters in the configuration, then the default values (between brackets) are used.
|
||||
|
||||
@@ -710,22 +679,20 @@ Below you find more information on each of the authentication types.
|
||||
|
||||
#### Database authentication
|
||||
|
||||
The database authentication middleware defines three new routes:
|
||||
The database authentication middleware defines two new routes:
|
||||
|
||||
method path - parameters - description
|
||||
---------------------------------------------------------------------------------------------------
|
||||
GET /me - - returns the user that is currently logged in
|
||||
POST /register - username, password - adds a user with given username and password
|
||||
POST /login - username, password - logs a user in by username and password
|
||||
POST /password - username, password, newPassword - updates the password of the logged in user
|
||||
POST /logout - - logs out the currently logged in user
|
||||
method path - parameters - description
|
||||
----------------------------------------------------------------------------------------
|
||||
POST /login - username + password - logs a user in by username and password
|
||||
POST /logout - - logs out the currently logged in user
|
||||
|
||||
A user can be logged in by sending it's username and password to the login endpoint (in JSON format).
|
||||
The authenticated user (with all it's properties) will be stored in the `$_SESSION['user']` variable.
|
||||
The user can be logged out by sending a POST request with an empty body to the logout endpoint.
|
||||
The passwords are stored as hashes in the password column in the users table. You can register a new user
|
||||
using the register endpoint, but this functionality must be turned on using the "dbAuth.regsiterUser"
|
||||
configuration parameter.
|
||||
The passwords are stored as hashes in the password column in the users table. To generate the hash value
|
||||
for the password 'pass2' you can run on the command line:
|
||||
|
||||
php -r 'echo password_hash("pass2", PASSWORD_DEFAULT)."\n";'
|
||||
|
||||
It is IMPORTANT to restrict access to the users table using the 'authorization' middleware, otherwise all
|
||||
users can freely add, modify or delete any account! The minimal configuration is shown below:
|
||||
@@ -860,7 +827,7 @@ Add the "columns" controller in the configuration to enable this functionality.
|
||||
|
||||
### Authorizing tables, columns and records
|
||||
|
||||
By default all tables, columns and paths are accessible. If you want to restrict access to some tables you may add the 'authorization' middleware
|
||||
By default all tables and columns are accessible. If you want to restrict access to some tables you may add the 'authorization' middleware
|
||||
and define a 'authorization.tableHandler' function that returns 'false' for these tables.
|
||||
|
||||
'authorization.tableHandler' => function ($operation, $tableName) {
|
||||
@@ -882,12 +849,6 @@ The above example will restrict access to the 'password' field of the 'users' ta
|
||||
The above example will disallow access to user records where the username is 'admin'.
|
||||
This construct adds a filter to every executed query.
|
||||
|
||||
'authorization.pathHandler' => function ($path) {
|
||||
return $path === 'openapi' ? false : true;
|
||||
},
|
||||
|
||||
The above example will disabled the `/openapi` route.
|
||||
|
||||
NB: You need to handle the creation of invalid records with a validation (or sanitation) handler.
|
||||
|
||||
### SQL GRANT authorization
|
||||
@@ -904,7 +865,7 @@ should not use the "authorization" middleware, but you do need to use the "recon
|
||||
},
|
||||
|
||||
This will make the API connect to the database specifying "mevdschee" as the username and "secret123" as the password.
|
||||
The OpenAPI specification is less specific on allowed and disallowed operations when you are using database permissions,
|
||||
The OpenAPI specification is less specific on allowed and disallowed operations, when you are using database permissions,
|
||||
as the permissions are not read in the reflection step.
|
||||
|
||||
NB: You may want to retrieve the username and password from the session (the "$_SESSION" variable).
|
||||
@@ -920,28 +881,10 @@ the 'sanitation' middleware and define a 'sanitation.handler' function that retu
|
||||
|
||||
The above example will strip all HTML tags from strings in the input.
|
||||
|
||||
### Type sanitation
|
||||
|
||||
If you enable the 'sanitation' middleware, then you (automatically) also enable type sanitation. When this is enabled you may:
|
||||
|
||||
- send leading and trailing whitespace in a non-character field (it will be ignored).
|
||||
- send a float to an integer or bigint field (it will be rounded).
|
||||
- send a base64url encoded string (it will be converted to regular base64 encoding).
|
||||
- send a time/date/timestamp in any [strtotime accepted format](https://www.php.net/manual/en/datetime.formats.php) (it will be converted).
|
||||
|
||||
You may use the config settings "`sanitation.types`" and "`sanitation.tables`"' to define for which types and
|
||||
in which tables you want to apply type sanitation (defaults to 'all'). Example:
|
||||
|
||||
'sanitation.types' => 'date,timestamp',
|
||||
'sanitation.tables' => 'posts,comments',
|
||||
|
||||
Here we enable the type sanitation for date and timestamp fields in the posts and comments tables.
|
||||
|
||||
### Validating input
|
||||
|
||||
By default all input is accepted and sent to the database. If you want to validate the input in a custom way,
|
||||
you may add the 'validation' middleware and define a 'validation.handler' function that returns a boolean
|
||||
indicating whether or not the value is valid.
|
||||
By default all input is accepted. If you want to validate the input, you may add the 'validation' middleware and define a
|
||||
'validation.handler' function that returns a boolean indicating whether or not the value is valid.
|
||||
|
||||
'validation.handler' => function ($operation, $tableName, $column, $value, $context) {
|
||||
return ($column['name'] == 'post_id' && !is_numeric($value)) ? 'must be numeric' : true;
|
||||
@@ -967,37 +910,6 @@ Then the server will return a '422' HTTP status code and nice error message:
|
||||
|
||||
You can parse this output to make form fields show up with a red border and their appropriate error message.
|
||||
|
||||
### Type validations
|
||||
|
||||
If you enable the 'validation' middleware, then you (automatically) also enable type validation.
|
||||
This includes the following error messages:
|
||||
|
||||
| error message | reason | applies to types |
|
||||
| ------------------- | --------------------------- | ------------------------------------------- |
|
||||
| cannot be null | unexpected null value | (any non-nullable column) |
|
||||
| illegal whitespace | leading/trailing whitespace | integer bigint decimal float double boolean |
|
||||
| invalid integer | illegal characters | integer bigint |
|
||||
| string too long | too many characters | varchar varbinary |
|
||||
| invalid decimal | illegal characters | decimal |
|
||||
| decimal too large | too many digits before dot | decimal |
|
||||
| decimal too precise | too many digits after dot | decimal |
|
||||
| invalid float | illegal characters | float double |
|
||||
| invalid boolean | use 1, 0, true or false | boolean |
|
||||
| invalid date | use yyyy-mm-dd | date |
|
||||
| invalid time | use hh:mm:ss | time |
|
||||
| invalid timestamp | use yyyy-mm-dd hh:mm:ss | timestamp |
|
||||
| invalid base64 | illegal characters | varbinary, blob |
|
||||
|
||||
You may use the config settings "`validation.types`" and "`validation.tables`"' to define for which types and
|
||||
in which tables you want to apply type validation (defaults to 'all'). Example:
|
||||
|
||||
'validation.types' => 'date,timestamp',
|
||||
'validation.tables' => 'posts,comments',
|
||||
|
||||
Here we enable the type validation for date and timestamp fields in the posts and comments tables.
|
||||
|
||||
NB: Types that are enabled will be checked for null values when the column is non-nullable.
|
||||
|
||||
### Multi-tenancy support
|
||||
|
||||
Two forms of multi-tenancy are supported:
|
||||
@@ -1066,36 +978,6 @@ You may use the "customization" middleware to modify request and response and im
|
||||
|
||||
The above example will add a header "X-Time-Taken" with the number of seconds the API call has taken.
|
||||
|
||||
### XML middleware
|
||||
|
||||
You may use the "xml" middleware to translate input and output from JSON to XML. This request:
|
||||
|
||||
GET /records/posts/1
|
||||
|
||||
Outputs (when "pretty printed"):
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"user_id": 1,
|
||||
"category_id": 1,
|
||||
"content": "blog started"
|
||||
}
|
||||
|
||||
While (note the "format" query parameter):
|
||||
|
||||
GET /records/posts/1?format=xml
|
||||
|
||||
Outputs:
|
||||
|
||||
<root>
|
||||
<id>1</id>
|
||||
<user_id>1</user_id>
|
||||
<category_id>1</category_id>
|
||||
<content>blog started</content>
|
||||
</root>
|
||||
|
||||
This functionality is disabled by default and must be enabled using the "middlewares" configuration setting.
|
||||
|
||||
### File uploads
|
||||
|
||||
File uploads are supported through the [FileReader API](https://caniuse.com/#feat=filereader), check out the [example](https://github.com/mevdschee/php-crud-api/blob/master/examples/clients/upload/vanilla.html).
|
||||
@@ -1131,39 +1013,42 @@ in case that you use a non-default "cacheType" the hostname (optionally with por
|
||||
|
||||
## Types
|
||||
|
||||
These are the supported types with their length, category, JSON type and format:
|
||||
These are the supported types with their default length/precision/scale:
|
||||
|
||||
| type | length | category | JSON type | format |
|
||||
| ---------- | ------ | --------- | --------- | ------------------- |
|
||||
| varchar | 255 | character | string | |
|
||||
| clob | | character | string | |
|
||||
| boolean | | boolean | boolean | |
|
||||
| integer | | integer | number | |
|
||||
| bigint | | integer | number | |
|
||||
| float | | float | number | |
|
||||
| double | | float | number | |
|
||||
| decimal | 19,4 | decimal | string | |
|
||||
| date | | date/time | string | yyyy-mm-dd |
|
||||
| time | | date/time | string | hh:mm:ss |
|
||||
| timestamp | | date/time | string | yyyy-mm-dd hh:mm:ss |
|
||||
| varbinary | 255 | binary | string | base64 encoded |
|
||||
| blob | | binary | string | base64 encoded |
|
||||
| geometry | | other | string | well-known text |
|
||||
character types
|
||||
- varchar(255)
|
||||
- clob
|
||||
|
||||
Note that geometry is a non-jdbc type and thus has limited support.
|
||||
boolean types:
|
||||
- boolean
|
||||
|
||||
## Data types in JavaScript
|
||||
integer types:
|
||||
- integer
|
||||
- bigint
|
||||
|
||||
Javascript and Javascript object notation (JSON) are not very well suited for reading database records. Decimal, date/time, binary and geometry types must be represented as strings in JSON (binary is base64 encoded, geometries are in WKT format). Below are two more serious issues described.
|
||||
floating point types:
|
||||
- float
|
||||
- double
|
||||
|
||||
### 64 bit integers
|
||||
decimal types:
|
||||
- decimal(19,4)
|
||||
|
||||
date/time types:
|
||||
- date
|
||||
- time
|
||||
- timestamp
|
||||
|
||||
binary types:
|
||||
- varbinary(255)
|
||||
- blob
|
||||
|
||||
other types:
|
||||
- geometry /* non-jdbc type, extension with limited support */
|
||||
|
||||
## 64 bit integers in JavaScript
|
||||
|
||||
JavaScript does not support 64 bit integers. All numbers are stored as 64 bit floating point values. The mantissa of a 64 bit floating point number is only 53 bit and that is why all integer numbers bigger than 53 bit may cause problems in JavaScript.
|
||||
|
||||
### Inf and NaN floats
|
||||
|
||||
The valid floating point values 'Infinite' (calculated with '1/0') and 'Not a Number' (calculated with '0/0') cannot be expressed in JSON, as they are not supported by the [JSON specification](https://www.json.org). When these values are stored in a database then you cannot read them as this script outputs database records as JSON.
|
||||
|
||||
## Errors
|
||||
|
||||
The following errors may be reported:
|
||||
@@ -1205,12 +1090,10 @@ NB: Any non-error response will have status: 200 OK
|
||||
|
||||
I am testing mainly on Ubuntu and I have the following test setups:
|
||||
|
||||
- (Docker) Debian 10 with PHP 7.3, MariaDB 10.3, PostgreSQL 11.4 (PostGIS 2.5)
|
||||
- (Docker) Debian 9 with PHP 7.0, MariaDB 10.1, PostgreSQL 9.6 (PostGIS 2.3)
|
||||
- (Docker) Ubuntu 16.04 with PHP 7.0, MariaDB 10.0, PostgreSQL 9.5 (PostGIS 2.2) and SQL Server 2017
|
||||
- (Docker) Debian 9 with PHP 7.0, MariaDB 10.1, PostgreSQL 9.6 (PostGIS 2.3) and SQLite 3.16
|
||||
- (Docker) Ubuntu 18.04 with PHP 7.2, MySQL 5.7, PostgreSQL 10.4 (PostGIS 2.4) and SQLite 3.22
|
||||
- (Docker) Debian 10 with PHP 7.3, MariaDB 10.3, PostgreSQL 11.4 (PostGIS 2.5) and SQLite 3.27
|
||||
- (Docker) Ubuntu 20.04 with PHP 7.4, MySQL 8.0, PostgreSQL 12.2 (PostGIS 3.0) and SQLite 3.31
|
||||
- (Docker) CentOS 8 with PHP 7.4, MariaDB 10.5, PostgreSQL 12.5 (PostGIS 3.0) and SQLite 3.26
|
||||
- (Docker) Ubuntu 18.04 with PHP 7.2, MySQL 5.7, PostgreSQL 10.4 (PostGIS 2.4)
|
||||
|
||||
This covers not all environments (yet), so please notify me of failing tests and report your environment.
|
||||
I will try to cover most relevant setups in the "docker" folder of the project.
|
||||
@@ -1254,7 +1137,7 @@ server {
|
||||
}
|
||||
```
|
||||
|
||||
### Docker tests
|
||||
### Docker
|
||||
|
||||
Install docker using the following commands and then logout and login for the changes to take effect:
|
||||
|
||||
@@ -1263,18 +1146,6 @@ Install docker using the following commands and then logout and login for the ch
|
||||
|
||||
To run the docker tests run "build_all.sh" and "run_all.sh" from the docker directory. The output should be:
|
||||
|
||||
================================================
|
||||
CentOS 8 (PHP 7.4)
|
||||
================================================
|
||||
[1/4] Starting MariaDB 10.5 ..... done
|
||||
[2/4] Starting PostgreSQL 12.5 .. done
|
||||
[3/4] Starting SQLServer 2017 ... skipped
|
||||
[4/4] Cloning PHP-CRUD-API v2 ... skipped
|
||||
------------------------------------------------
|
||||
mysql: 110 tests ran in 1911 ms, 1 skipped, 0 failed
|
||||
pgsql: 110 tests ran in 1112 ms, 1 skipped, 0 failed
|
||||
sqlsrv: skipped, driver not loaded
|
||||
sqlite: 110 tests ran in 1178 ms, 12 skipped, 0 failed
|
||||
================================================
|
||||
Debian 10 (PHP 7.3)
|
||||
================================================
|
||||
@@ -1283,10 +1154,9 @@ To run the docker tests run "build_all.sh" and "run_all.sh" from the docker dire
|
||||
[3/4] Starting SQLServer 2017 ... skipped
|
||||
[4/4] Cloning PHP-CRUD-API v2 ... skipped
|
||||
------------------------------------------------
|
||||
mysql: 110 tests ran in 3459 ms, 1 skipped, 0 failed
|
||||
pgsql: 110 tests ran in 1134 ms, 1 skipped, 0 failed
|
||||
mysql: 100 tests ran in 3623 ms, 0 failed
|
||||
pgsql: 100 tests ran in 1310 ms, 0 failed
|
||||
sqlsrv: skipped, driver not loaded
|
||||
sqlite: 110 tests ran in 1275 ms, 12 skipped, 0 failed
|
||||
================================================
|
||||
Debian 9 (PHP 7.0)
|
||||
================================================
|
||||
@@ -1295,10 +1165,9 @@ To run the docker tests run "build_all.sh" and "run_all.sh" from the docker dire
|
||||
[3/4] Starting SQLServer 2017 ... skipped
|
||||
[4/4] Cloning PHP-CRUD-API v2 ... skipped
|
||||
------------------------------------------------
|
||||
mysql: 110 tests ran in 3181 ms, 1 skipped, 0 failed
|
||||
pgsql: 110 tests ran in 1201 ms, 1 skipped, 0 failed
|
||||
mysql: 100 tests ran in 4844 ms, 0 failed
|
||||
pgsql: 100 tests ran in 1394 ms, 0 failed
|
||||
sqlsrv: skipped, driver not loaded
|
||||
sqlite: 110 tests ran in 1414 ms, 12 skipped, 0 failed
|
||||
================================================
|
||||
Ubuntu 16.04 (PHP 7.0)
|
||||
================================================
|
||||
@@ -1307,10 +1176,9 @@ To run the docker tests run "build_all.sh" and "run_all.sh" from the docker dire
|
||||
[3/4] Starting SQLServer 2017 ... done
|
||||
[4/4] Cloning PHP-CRUD-API v2 ... skipped
|
||||
------------------------------------------------
|
||||
mysql: 110 tests ran in 3168 ms, 1 skipped, 0 failed
|
||||
pgsql: 110 tests ran in 1197 ms, 1 skipped, 0 failed
|
||||
sqlsrv: 110 tests ran in 10151 ms, 1 skipped, 0 failed
|
||||
sqlite: skipped, driver not loaded
|
||||
mysql: 100 tests ran in 4932 ms, 0 failed
|
||||
pgsql: 100 tests ran in 1394 ms, 0 failed
|
||||
sqlsrv: 100 tests ran in 50977 ms, 0 failed
|
||||
================================================
|
||||
Ubuntu 18.04 (PHP 7.2)
|
||||
================================================
|
||||
@@ -1319,33 +1187,18 @@ To run the docker tests run "build_all.sh" and "run_all.sh" from the docker dire
|
||||
[3/4] Starting SQLServer 2017 ... skipped
|
||||
[4/4] Cloning PHP-CRUD-API v2 ... skipped
|
||||
------------------------------------------------
|
||||
mysql: 110 tests ran in 3709 ms, 1 skipped, 0 failed
|
||||
pgsql: 110 tests ran in 1334 ms, 1 skipped, 0 failed
|
||||
mysql: 100 tests ran in 4327 ms, 0 failed
|
||||
pgsql: 100 tests ran in 1396 ms, 0 failed
|
||||
sqlsrv: skipped, driver not loaded
|
||||
sqlite: 110 tests ran in 1477 ms, 12 skipped, 0 failed
|
||||
================================================
|
||||
Ubuntu 20.04 (PHP 7.4)
|
||||
================================================
|
||||
[1/4] Starting MySQL 8.0 ........ done
|
||||
[2/4] Starting PostgreSQL 12.2 .. done
|
||||
[3/4] Starting SQLServer 2017 ... skipped
|
||||
[4/4] Cloning PHP-CRUD-API v2 ... skipped
|
||||
------------------------------------------------
|
||||
mysql: 110 tests ran in 5102 ms, 1 skipped, 0 failed
|
||||
pgsql: 110 tests ran in 1170 ms, 1 skipped, 0 failed
|
||||
sqlsrv: skipped, driver not loaded
|
||||
sqlite: 110 tests ran in 1380 ms, 12 skipped, 0 failed
|
||||
|
||||
The above test run (including starting up the databases) takes less than 5 minutes on my slow laptop.
|
||||
|
||||
$ ./run.sh
|
||||
1) centos8
|
||||
2) debian10
|
||||
3) debian9
|
||||
4) ubuntu16
|
||||
5) ubuntu18
|
||||
6) ubuntu20
|
||||
> 5
|
||||
$ ./run.sh
|
||||
1) debian10
|
||||
2) debian9
|
||||
3) ubuntu16
|
||||
4) ubuntu18
|
||||
> 4
|
||||
================================================
|
||||
Ubuntu 18.04 (PHP 7.2)
|
||||
================================================
|
||||
@@ -1354,36 +1207,11 @@ The above test run (including starting up the databases) takes less than 5 minut
|
||||
[3/4] Starting SQLServer 2017 ... skipped
|
||||
[4/4] Cloning PHP-CRUD-API v2 ... skipped
|
||||
------------------------------------------------
|
||||
mysql: 105 tests ran in 3390 ms, 1 skipped, 0 failed
|
||||
pgsql: 105 tests ran in 936 ms, 1 skipped, 0 failed
|
||||
mysql: 100 tests ran in 4327 ms, 0 failed
|
||||
pgsql: 100 tests ran in 1396 ms, 0 failed
|
||||
sqlsrv: skipped, driver not loaded
|
||||
sqlite: 105 tests ran in 1063 ms, 12 skipped, 0 failed
|
||||
root@b7ab9472e08f:/php-crud-api#
|
||||
|
||||
As you can see the "run.sh" script gives you access to a prompt in a chosen the docker environment.
|
||||
In this environment the local files are mounted. This allows for easy debugging on different environments.
|
||||
You may type "exit" when you are done.
|
||||
|
||||
### Docker image
|
||||
|
||||
There is a `Dockerfile` in the repository that is used to build an image at:
|
||||
|
||||
[https://hub.docker.com/r/mevdschee/php-crud-api](https://hub.docker.com/r/mevdschee/php-crud-api)
|
||||
|
||||
It will be automatically build on every release. The "latest" tag points to the last release.
|
||||
|
||||
### Docker compose
|
||||
|
||||
This repository also contains a `docker-compose.yml` file that you can install/build/run using:
|
||||
|
||||
sudo apt install docker-compose
|
||||
docker-compose build
|
||||
docker-compose up
|
||||
|
||||
This will setup a database (MySQL) and a webserver (Apache) and runs the application using the blog example data used in the tests.
|
||||
|
||||
Test the script (running in the container) by opening the following URL:
|
||||
|
||||
http://localhost:8080/records/posts/1
|
||||
|
||||
Enjoy!
|
||||
|
||||
Reference in New Issue
Block a user