Skip to content

Commit dcd32c3

Browse files
committed
Initial Release
1 parent f172e30 commit dcd32c3

Some content is hidden

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

59 files changed

+4081
-0
lines changed

README.md

+138
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,140 @@
11
# codeigniter4-schemas
22
Database schema management, for CodeIgniter 4
3+
4+
## Quick Start
5+
6+
1. Install with Composer: `> composer require codenom/schemas`
7+
2. Generate a new schema: `> php spark schemas`
8+
9+
## Features
10+
11+
* View your entire database mapped out in a cascading structure
12+
* Read or detect table relationships for easy object-relation mapping (see e.g. [Tatter\Relations](https://github.com/tattersoftware/codeigniter4-relations))
13+
* Get helpful advice on optimizations to your database structure with schema analysis<sup>1</sup>
14+
* Backup, restore, or deploy an entire database structure between servers or environments<sup>1</sup>
15+
* Generate CodeIgniter 4 migration files from an existing database<sup>1</sup>
16+
* Transfer projects to CodeIgniter 4 by reading schema files from other supported formats<sup>1</sup>
17+
18+
<sup>1</sup> Some features are still in development. See **Handlers > Development** for
19+
planned future expansion.
20+
21+
## Installation
22+
23+
Install easily via Composer to take advantage of CodeIgniter 4's autoloading capabilities
24+
and always be up-to-date:
25+
* `> composer require codenom/schemas`
26+
27+
Or, install manually by downloading the source files and adding the directory to
28+
`app/Config/Autoload.php`.
29+
30+
## Configuration (optional)
31+
32+
The library's default behavior can be altered by extending its config file. Copy
33+
**bin/Schemas.php** to **app/Config/** and follow the instructions
34+
in the comments. If no config file is found in **app/Config** the library will use its own.
35+
36+
## Usage
37+
38+
**Schemas** has four main functions, each with a variety of handlers available:
39+
* *Draft*: Generates a new schema from a variety of sources
40+
* *Archive*: Stores a copy of a schema for later use
41+
* *Read*: Loads a schema for live access
42+
* *Publish*: (not yet available) Modifies environments to match schema specs
43+
44+
The **Schemas** service is also available to simplify a workflow with convenient wrapper functions.
45+
At its most basic (with automation enabled), the service will draft, archive, and return
46+
a schema with one simple command:
47+
48+
$schema = service('schemas')->get();
49+
50+
You may want to control when portions of the workflow take place to optimize performance.
51+
Here is an example of one common process, mapping the default database group and storing
52+
the resulting schema to the cache:
53+
54+
```
55+
// Map the database and store the schema in cache
56+
$schemas = service('schemas');
57+
$schemas->draft('database')->archive('cache');
58+
59+
// Load the schema from cache, add Model data, and get the updated schema
60+
$schema = $schemas->read('cache')->draft('model')->get();
61+
```
62+
63+
If you need to deviate from default handler configurations you can inject the handlers yourself:
64+
```
65+
$db = db_connect('alternate_database');
66+
$databaseHandler = new \Codenom\Schemas\Drafter\Handlers\DatabaseHandler(null, $db);
67+
$schema = $schemas->draft($databaseHandler)->get();
68+
```
69+
70+
## Command
71+
72+
**Schemas** comes with a `spark` command for convenient schema generation and display:
73+
74+
`schemas [-draft handler1,handler2,...] [-archive handler1,... | -print]`
75+
76+
Use the command to test and troubleshoot, or add it to your cron for periodic schema caching:
77+
78+
php spark schemas -draft database,model -archive cache
79+
80+
## Automation
81+
82+
By default automation is turned on, but this can be configured via the `$automate` toggles
83+
in your config file. Automation will allow the service to fall back on a Reader, or even on
84+
a Drafter should it fail to have a schema already loaded. While automation makes using the
85+
library very easy, it can come at a performance cost if your application is not configured
86+
correctly, since it may draft a schema on every page load. Use automation to help but don't
87+
let it become a crutch.
88+
89+
## Structure
90+
91+
**Schemas** uses foreign keys, indexes, and naming convention to detect relationships
92+
automatically. Make sure your database is setup using the appropriate keys and
93+
foreign keys to assist with the detection. Naming conventions follow the format of
94+
`{table}_id` for foreign keys and `{table1}_{table2}` for pivot tables. For more examples
95+
on relationship naming conventions consult the Rails Guide
96+
[Active Record Associations](https://guides.rubyonrails.org/association_basics.html#the-types-of-associations)
97+
(and please excuse the Ruby reference).
98+
99+
### Intervention
100+
101+
Should autodetection fail or should you need to deviate from conventions there are a few
102+
tools you can use to overwrite or augment the generated schema.
103+
104+
* **Config/Schemas**: the Config file includes a variable for `$ignoredTables` that will let you skip tables entirely. By default this includes the framework's `migrations` table.
105+
* **app/Schemas/{file}.php**: The `DirectoryHandler` will load any schemas detected in your **Schemas** directory - this gives you a chance to specify anything you want. See [tests/_support/Schemas/Good/Products.php](tests/_support/Schemas/Good/Products.php) for an example.
106+
107+
## Drafting
108+
109+
Currently supported handlers:
110+
111+
* Database
112+
* Model
113+
* PHP
114+
* Directory (PHP import only)
115+
116+
## Archiving/reading
117+
118+
* Cache
119+
120+
## Database Support
121+
122+
All CodeIgniter 4 database drivers work but due to some differences in index handling they
123+
may not all report the same results. Example: see skipped tests for SQLite3.
124+
125+
## Development
126+
127+
The eventual goal is to support mapping from and deploying to any source. Planned handler
128+
implementations include:
129+
130+
* `Publisher\DatabaseHandler`: Recreate a live database from its schema
131+
* `MigrationsHandler`: Create a schema from migration files, or vice versa
132+
* `FileHandler`: A wrapper for importing and exporting from popular schema file formats
133+
* Lots more...
134+
135+
And the file-specific handlers:
136+
* `PhpHandler->archive()`: Create a PHP file with a Schema object in `$schema`
137+
* `XmlHandler`: Support for Doctrine-style XML files
138+
* More to come...
139+
140+
Want to help out? All code and issues are managed on GitHub at [Codenom\Schemas](https://github.com/codenomdev/codeigniter4-schemas)

bin/Schemas.php

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
3+
namespace Config;
4+
5+
/***
6+
*
7+
* This file contains example values to alter default library behavior.
8+
* Recommended usage:
9+
* 1. Copy the file to app/Config/
10+
* 2. Change any values
11+
* 3. Remove any lines to fallback to defaults
12+
*
13+
***/
14+
15+
class Schemas extends \Codenom\Schemas\Config\Schemas
16+
{
17+
// Whether to continue instead of throwing exceptions
18+
public $silent = true;
19+
20+
// Which tasks to automate when a schema is not available from the service
21+
public $automate = [
22+
'draft' => true,
23+
'archive' => true,
24+
'read' => true,
25+
];
26+
27+
//--------------------------------------------------------------------
28+
// Drafting
29+
//--------------------------------------------------------------------
30+
31+
// Default handlers used to create a schema (order sensitive)
32+
// (Probably shouldn't change this unless you really know what you're doing)
33+
public $draftHandlers = [
34+
'Codenom\Schemas\Drafter\Handlers\DatabaseHandler',
35+
'Codenom\Schemas\Drafter\Handlers\ModelHandler',
36+
'Codenom\Schemas\Drafter\Handlers\DirectoryHandler',
37+
];
38+
39+
// Tables to ignore when creating the schema
40+
public $ignoredTables = ['migrations'];
41+
42+
// Namespaces to ignore (mostly for ModelHandler)
43+
public $ignoredNamespaces = [
44+
'Tests\Support',
45+
];
46+
47+
// Path the directoryHandler should scan for schema files
48+
public $schemasDirectory = APPPATH . 'Schemas';
49+
50+
//--------------------------------------------------------------------
51+
// Archiving
52+
//--------------------------------------------------------------------
53+
54+
// Default handlers to archive copies of the schema
55+
public $archiveHandlers = [
56+
'Codenom\Schemas\Archiver\Handlers\CacheHandler',
57+
];
58+
59+
// Default time-to-live for a stored schema (e.g. Cache) in seconds
60+
public $ttl = 14400; // 4 hours
61+
62+
//--------------------------------------------------------------------
63+
// Reading
64+
//--------------------------------------------------------------------
65+
66+
// Default handler used to return and read a schema
67+
public $readHandler = 'Codenom\Schemas\Reader\Handlers\CacheHandler';
68+
69+
//--------------------------------------------------------------------
70+
// Publishing
71+
//--------------------------------------------------------------------
72+
73+
// Precaution to prevent accidental wiping of databases or files
74+
public $safeMode = true;
75+
}
76+
77+
/** End of bin/Schemas.php */

composer.json

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
{
2+
"name": "codenom/schemas",
3+
"description": "Database schema management, for CodeIgniter 4",
4+
"keywords": [
5+
"codeigniter",
6+
"codeigniter4",
7+
"schemas",
8+
"database",
9+
"mapping",
10+
"structure"
11+
],
12+
"homepage": "https://github.com/codenom/codeigniter4-schemas",
13+
"license": "MIT",
14+
"authors": [
15+
{
16+
"name": "Database Schemas for CodeIgniter 4",
17+
"email": "[email protected]",
18+
"homepage": "https://codenom.com",
19+
"role": "Developer"
20+
}
21+
],
22+
"repositories": [
23+
{
24+
"type": "vcs",
25+
"url": "https://github.com/codeigniter4/CodeIgniter4"
26+
}
27+
],
28+
"minimum-stability": "dev",
29+
"prefer-stable": true,
30+
"require": {
31+
"php": ">=7.2"
32+
},
33+
"require-dev": {
34+
"phpunit/phpunit": "8.5.*",
35+
"mockery/mockery": "^1.0",
36+
"codeigniter4/codeigniter4": "dev-develop"
37+
},
38+
"autoload": {
39+
"psr-4": {
40+
"Codenom\\Schemas\\": "src"
41+
}
42+
},
43+
"autoload-dev": {
44+
"psr-4": {
45+
"Tests\\Support\\": "tests/_support"
46+
}
47+
},
48+
"scripts": {
49+
"test": "phpunit",
50+
"post-update-cmd": [
51+
"composer dump-autoload"
52+
]
53+
}
54+
}

phpunit.xml.dist

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit bootstrap="vendor/codeigniter4/codeigniter4/system/Test/bootstrap.php"
3+
backupGlobals="false"
4+
colors="true"
5+
convertErrorsToExceptions="true"
6+
convertNoticesToExceptions="true"
7+
convertWarningsToExceptions="true"
8+
stopOnError="false"
9+
stopOnFailure="false"
10+
stopOnIncomplete="false"
11+
stopOnSkipped="false">
12+
<testsuites>
13+
<testsuite name="app">
14+
<directory>./tests</directory>
15+
</testsuite>
16+
</testsuites>
17+
18+
<filter>
19+
<whitelist addUncoveredFilesFromWhitelist="true" processUncoveredFilesFromWhitelist="true">
20+
<directory suffix=".php">./src</directory>
21+
<exclude>
22+
<directory suffix=".php">./src/Agents</directory>
23+
<directory suffix=".php">./src/Structures</directory>
24+
<directory suffix=".php">./src/Views</directory>
25+
<file>./src/Config/Routes.php</file>
26+
</exclude>
27+
</whitelist>
28+
</filter>
29+
30+
<logging>
31+
<log type="coverage-html" target="build/logs/html"/>
32+
<log type="coverage-clover" target="build/logs/clover.xml"/>
33+
<log type="coverage-php" target="build/logs/coverage.serialized"/>
34+
<log type="coverage-text" target="php://stdout" showUncoveredFiles="false"/>
35+
<log type="testdox-html" target="build/logs/testdox.html"/>
36+
<log type="testdox-text" target="build/logs/testdox.txt"/>
37+
<log type="junit" target="build/logs/logfile.xml"/>
38+
</logging>
39+
40+
<php>
41+
<server name="app.baseURL" value="http://example.com"/>
42+
43+
<!-- Directory containing phpunit.xml -->
44+
<const name="HOMEPATH" value="./"/>
45+
46+
<!-- Directory containing the Paths config file -->
47+
<const name="CONFIGPATH" value="./vendor/codeigniter4/codeigniter4/app/Config/"/>
48+
49+
<!-- Directory containing the front controller (index.php) -->
50+
<const name="PUBLICPATH" value="./vendor/codeigniter4/codeigniter4/public/"/>
51+
52+
<!-- https://getcomposer.org/xdebug -->
53+
<env name="COMPOSER_DISABLE_XDEBUG_WARN" value="1"/>
54+
55+
<!-- Database configuration -->
56+
<!-- <env name="database.tests.hostname" value="localhost"/> -->
57+
<!-- <env name="database.tests.database" value="tests"/> -->
58+
<!-- <env name="database.tests.username" value="tests_user"/> -->
59+
<!-- <env name="database.tests.password" value=""/> -->
60+
<!-- <env name="database.tests.DBDriver" value="MySQLi"/> -->
61+
<!-- <env name="database.tests.DBPrefix" value="tests_"/> -->
62+
<env name="database.tests.database" value=":memory:"/>
63+
<env name="database.tests.DBDriver" value="SQLite3"/>
64+
</php>
65+
</phpunit>

src/Agents/SchemaAgent.php

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
namespace Codenom\Schemas\Agents;
4+
5+
/* Codenom\Agents
6+
* Service analysis and assessment for CodeIgniter 4
7+
* https://github.com/Codenom/codeigniter4-agents
8+
*
9+
* Install:
10+
* `composer require Codenom\agents`
11+
* `php spark handlers:register`
12+
*
13+
* Collect:
14+
* `php spark agents:check`
15+
*
16+
* Monitor:
17+
* https://github.com/Codenom/headquarters
18+
*/
19+
20+
use CodeIgniter\Config\Services;
21+
use Codenom\Agents\BaseAgent;
22+
use Codenom\Agents\Interfaces\AgentInterface;
23+
24+
class SchemaAgent extends BaseAgent implements AgentInterface
25+
{
26+
// Attributes for Codenom\Handlers
27+
public $attributes = [
28+
'name' => 'Schema',
29+
'uid' => 'schema',
30+
'icon' => 'fas fa-project-diagram',
31+
'summary' => 'Map the database structure from the default connection',
32+
];
33+
34+
public function check($path = null)
35+
{
36+
$schemas = Services::schemas();
37+
if (empty($schemas)) {
38+
return false;
39+
}
40+
$config = config('Schemas');
41+
42+
// Generate the schema
43+
$schema = $schemas->import(...$config->defaultHandlers)->get();
44+
45+
46+
$this->record('defaultSchema', 'object', $schema);
47+
}
48+
}
49+
50+
/** End of src/Agents/SchemaAgent.php */

0 commit comments

Comments
 (0)