Code Monkey home page Code Monkey logo

codeigniter4-schemas's Introduction

Tatter\Schemas

Database schema management, for CodeIgniter 4

Coverage Status

Quick Start

  1. Install with Composer: > composer require tatter/schemas
  2. Generate a new schema: > php spark schemas

Features

  • View your entire database mapped out in a cascading structure
  • Read or detect table relationships for easy object-relation mapping (see e.g. Tatter\Relations)
  • Get helpful advice on optimizations to your database structure with schema analysis1
  • Backup, restore, or deploy an entire database structure between servers or environments1
  • Generate CodeIgniter 4 migration files from an existing database1
  • Transfer projects to CodeIgniter 4 by reading schema files from other supported formats1

1 Some features are still in development. See Handlers > Development for planned future expansion.

Installation

Install easily via Composer to take advantage of CodeIgniter 4's autoloading capabilities and always be up-to-date:

  • > composer require tatter/schemas

Or, install manually by downloading the source files and adding the directory to app/Config/Autoload.php.

Configuration (optional)

The library's default behavior can be altered by extending its config file. Copy examples/Schemas.php to app/Config/ and follow the instructions in the comments. If no config file is found in app/Config the library will use its own.

Usage

Schemas has four main functions, each with a variety of handlers available:

  • Draft: Generates a new schema from a variety of sources
  • Archive: Stores a copy of a schema for later use
  • Read: Loads a schema for live access
  • Publish: (not yet available) Modifies environments to match schema specs

The Schemas service is also available to simplify a workflow with convenient wrapper functions. At its most basic (with automation enabled), the service will draft, archive, and return a schema with one simple command:

$schema = service('schemas')->get();

You may want to control when portions of the workflow take place to optimize performance. Here is an example of one common process, mapping the default database group and storing the resulting schema to the cache:

// Map the database and store the schema in cache
$schemas = service('schemas');
$schemas->draft('database')->archive('cache');

// Load the schema from cache, add Model data, and get the updated schema
$schema = $schemas->read('cache')->draft('model')->get();

If you need to deviate from default handler configurations you can inject the handlers yourself:

$db = db_connect('alternate_database');
$databaseHandler = new \Tatter\Schemas\Drafter\Handlers\DatabaseHandler(null, $db);
$schema = $schemas->draft($databaseHandler)->get();

Command

Schemas comes with a spark command for convenient schema generation and display:

`schemas [-draft handler1,handler2,...] [-archive handler1,... | -print]`

Use the command to test and troubleshoot, or add it to your cron for periodic schema caching:

php spark schemas -draft database,model -archive cache

Automation

By default automation is turned on, but this can be configured via the $automate toggles in your config file. Automation will allow the service to fall back on a Reader, or even on a Drafter should it fail to have a schema already loaded. While automation makes using the library very easy, it can come at a performance cost if your application is not configured correctly, since it may draft a schema on every page load. Use automation to help but don't let it become a crutch.

Structure

Schemas uses foreign keys, indexes, and naming convention to detect relationships automatically. Make sure your database is setup using the appropriate keys and foreign keys to assist with the detection. Naming conventions follow the format of {table}_id for foreign keys and {table1}_{table2} for pivot tables. For more examples on relationship naming conventions consult the Rails Guide Active Record Associations (and please excuse the Ruby reference).

Intervention

Should autodetection fail or should you need to deviate from conventions there are a few tools you can use to overwrite or augment the generated schema.

  • 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.
  • 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 for an example.

Drafting

Currently supported handlers:

  • Database
  • Model
  • PHP
  • Directory (PHP import only)

Archiving/reading

  • Cache

Database Support

All CodeIgniter 4 database drivers work but due to some differences in index handling they may not all report the same results. Example: see skipped tests for SQLite3.

Development

The eventual goal is to support mapping from and deploying to any source. Planned handler implementations include:

  • Publisher\DatabaseHandler: Recreate a live database from its schema
  • MigrationsHandler: Create a schema from migration files, or vice versa
  • FileHandler: A wrapper for importing and exporting from popular schema file formats
  • Lots more...

And the file-specific handlers:

  • PhpHandler->archive(): Create a PHP file with a Schema object in $schema
  • XmlHandler: Support for Doctrine-style XML files
  • More to come...

Want to help out? All code and issues are managed on GitHub at Tatter\Schemas

codeigniter4-schemas's People

Contributors

dependabot[bot] avatar mgatner avatar sfadschm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

codeigniter4-schemas's Issues

unable connect postgre database

Goodnight.

I am following the github instructions and when I perform the actions on a mysql database everything works perfectly.

However, when I configure a database in postgre, launching php spark schemas always tells me the same error. I have tried to locate the error but cannot.

"PS C: \ wamp64 \ www \ tatter-core> php spark schemas

CodeIgniter v4.1.1 Command Line Tool - Server Time: 2021-03-02 15:21:20 UTC-06: 00

[CodeIgniter \ Database \ Exceptions \ DatabaseException]

Unable to connect to the database.

at SYSTEMPATH \ Database \ BaseConnection.php: 395 "

However if it connects correctly in normal functionality, that is, I have access to data, I can make queries, etc.

I have all the drivers installed and it is functional both locally and on an AWS server.

Could you tell me what I am missing?

my .env

database.default.DSN = pgsql: host = host-amazon.amazonaws.com; port = 5432; dbname = name-base; user = my-user; password = my-password
database.default.hostname = host-amazon.amazonaws.com
database.default.database = name-base
database.default.username = my-user
database.default.password = my-password
database.default.DBDriver = Postgre
database.default.port = 5432
database.default.DBdebug = true

Thanks a lot.

After upgrading to CI4 v4.3.0, the generated schema is broken and can't be used with relations.

It appears to be a foreign key issue.

For example schema generated with Shield installed before anad after 4.3.0 upgrade.

CleanShot 2023-01-10 at 14 57 02

My troubleshooting:

in vendor/tatter/schemas/src/Structures/ForeignKey.php

I added dd to the end of __contstruct method and in before 4.3.0 it returns

Tatter\Schemas\Structures\ForeignKey (5) (
    public 'constraint_name' -> string (33) "auth_groups_users_user_id_foreign"
    public 'table_name' -> string (17) "auth_groups_users"
    public 'column_name' -> string (7) "user_id"
    public 'foreign_table_name' -> string (5) "users"
    public 'foreign_column_name' -> string (2) "id"
)

and after

Tatter\Schemas\Structures\ForeignKey#170 (8) (
    public 'constraint_name' -> string (33) "auth_groups_users_user_id_foreign"
    public 'table_name' -> string (17) "auth_groups_users"
    public 'column_name' -> array (1) [
        0 => string (7) "user_id"
    ]
    public 'foreign_table_name' -> string (5) "users"
    public 'foreign_column_name' -> array (1) [
        0 => string (2) "id"
    ]
    public 'on_delete' -> string (7) "CASCADE"
    public 'on_update' -> string (8) "RESTRICT"
    public 'match' -> string (4) "NONE"
)

This issue is there because of

Foreign Key Data

PHP 8.1 Fatal error

Using this on PHP 8.1 I get the following error:

During inheritance of IteratorAggregate: Uncaught ErrorException: Return type of Tatter\Schemas\Reader\Handlers\CacheHandler::getIterator() should either be compatible with IteratorAggregate::getIterator(): Traversable, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /path-to-project/vendor/tatter/schemas/src/Reader/Handlers/CacheHandler.php:155

Error: undefined function: plural()

When running "php spark schemas", I get the following error:

Type: Error Message: Call to undefined function Tatter\Schemas\Drafter\Handlers\plural() Filename: C:\xampp\htdocs\euro2021\vendor\tatter\schemas\src\Drafter\Handlers\DatabaseHandler.php Line Number: 269

What am I missing?

Feature: Multiple Models

The Table structure and Model Drafter should both support multiple models per table. Models should be priority ordered (e.g. App, modules). Tatter\Relations will need to take advantage of this as well.

Handler Naming Convention

Consider dropping "handler" in favor of the actual type (e.g. CacheHandler => CacheArchiver and CacheReader)

Feature: Toolbar collector

Add a toolbar collector to make an easy UI for viewing the current schema. Could likely be just the HTML output from Kint's d().

codeigniter4-schemas/src/Handlers/DatabaseHandler.php

// Create a relation
$relation = new Relation();
$relation->type = 'belongsTo';
$relation->singleton = true;
$relation->table = $this->stripPrefix($foreignKey->foreign_table_name);

Why type is always belongsTo ?

When i try to connect a many to one it triggers a relation exception that the table[0] is not related to table[1]

but in table[1] has a foreign_key with table[0]

I think code is missing for this case. It should know from relation schema that a foreign relation exists.

Tables :
connectors
id_connector
id_menu

menu
id_menu
title

$menu = new menuModel()
$menu->with('connectors')->findAll();

im getting this ERROR Table {0} is not known to be related to {1}

How to use this package?

I read README, but I don't get how to use this package.

I ran php spark schemas, but all I got is the messagesuccess.

https://github.com/tattersoftware/codeigniter4-schemas#features

View your entire database mapped out in a cascading structure
Get helpful advice on optimizations to your database structure with schema analysis
Backup, restore, or deploy an entire database structure between servers or environments
Generate CodeIgniter 4 migration files from an existing database

How?

Can one object belongsTo more than one user ?

I have a table orders.

There is two columns disponent_id & salesman_id.

Both have foreign key to the users table id. If I don't overwrite a scheme, then it's used last one so only user paired to the salesman_id.

So I tried to overwrite schema like in #41. Now my relation to the users table looks like:

                [users] => Tatter\Schemas\Structures\Relation Object
                (
                    [table] => users
                    [type] => belongsTo
                    [singleton] => 
                    [pivots] => Array
                        (
                            [0] => Array
                                (
                                    [0] => orders
                                    [1] => salesman_id
                                    [2] => users
                                    [3] => id
                                )

                            [1] => Array
                                (
                                    [0] => orders
                                    [1] => disponent_id
                                    [2] => users
                                    [3] => id
                                )

                        )

                )

I think this is a bad design, but I need to pair two users from different groups because of internal settlement.

Thanks.

Cache crashes

Cache permissions can cause the whole app to come down. Schemas should remove itself from this by ignoring the cache if it fails:

chmod(): Operation not permitted

at SYSTEMPATH/Cache/Handlers/FileHandler.php:127

Backtrace:
  1    [internal function]
       CodeIgniter\Debug\Exceptions()->errorHandler()

  2    SYSTEMPATH/Cache/Handlers/FileHandler.php:127
       chmod()

  3    VENDORPATH/tatter/schemas/src/Archiver/Handlers/CacheHandler.php:46
       CodeIgniter\Cache\Handlers\FileHandler()->save()

  4    VENDORPATH/tatter/schemas/src/Schemas.php:215
       Tatter\Schemas\Archiver\Handlers\CacheHandler()->archive()

  5    VENDORPATH/tatter/schemas/src/Schemas.php:120
       Tatter\Schemas\Schemas()->archive()

  6    VENDORPATH/tatter/schemas/src/Collectors/Schema.php:55
       Tatter\Schemas\Schemas()->get()

  7    SYSTEMPATH/Debug/Toolbar.php:69
       Tatter\Schemas\Collectors\Schema()->__construct()

  8    SYSTEMPATH/Config/Services.php:800
       CodeIgniter\Debug\Toolbar()->__construct()

  9    SYSTEMPATH/Config/BaseService.php:174
       CodeIgniter\Config\Services::toolbar()

 10    SYSTEMPATH/Config/Services.php:795
       CodeIgniter\Config\BaseService::getSharedInstance()

 11    SYSTEMPATH/Config/BaseService.php:245
       CodeIgniter\Config\Services::toolbar()

 12    APPPATH/Config/Events.php:52
       CodeIgniter\Config\BaseService::__callStatic()

 13    [internal function]
       CodeIgniter\Events\Events::Config\{closure}()

 14    SYSTEMPATH/Events/Events.php:166
       call_user_func()

 15    SYSTEMPATH/CodeIgniter.php:314
       CodeIgniter\Events\Events::trigger()

 16    SYSTEMPATH/CLI/Console.php:61
       CodeIgniter\CodeIgniter()->run()

 17    ROOTPATH/spark:66
       CodeIgniter\CLI\Console()->run()

Load models outside of 'Models' folders.

This is related to #17 and might also be connected to #7 when it gets implemented.

Not sure if the current behaviour is desired, but the ModelHandler currently only explicitly loads classes contained in 'Models' folders in the namespaces.

foreach ($locator->listNamespaceFiles($namespace, '/Models/') as $file)

This might ignore some model classes that are stored in other subfolders (e.g., Myth\Auth\Authorization).

As explained in #17, the ModelHandler uses get_declared_classes to collect class names. Therefore some of those not explicitly loaded models will still be collected, if they have been loaded from the system before the draft() (e.g. 'Myth\Auth\Authorization\GroupModel' is group filters are used for the current route).

A workaround might be, to not only load files in Models subdirectories but also file ending with Model.php or something like this. As all file are required_once, this should not be a problem but ensure, that all (or at least, more) models are considered.

Error When Running `php spark schemas` with CodeIgniter Shield: Cannot Instantiate Abstract Class

Hello,

I've encountered an issue when using the Tatter\Schemas package in combination with the official CodeIgniter Shield package. When attempting to run the php spark schemas command to generate schema files, I receive the following error message:

CodeIgniter v4.4.4 Command Line Tool - Server Time: 2024-02-05 22:02:35 UTC+00:00

[Error]
Cannot instantiate abstract class CodeIgniter\Shield\Models\BaseModel
at VENDORPATH/tatter/schemas/src/Drafter/Handlers/ModelHandler.php:173

Backtrace:
  1    VENDORPATH/tatter/schemas/src/Drafter/Handlers/ModelHandler.php:84
       Tatter\Schemas\Drafter\Handlers\ModelHandler()->getModels()

  2    VENDORPATH/tatter/schemas/src/Schemas.php:165
       Tatter\Schemas\Drafter\Handlers\ModelHandler()->draft()

  3    VENDORPATH/tatter/schemas/src/Commands/Schemas.php:57
       Tatter\Schemas\Schemas()->draft()

  4    SYSTEMPATH/CLI/Commands.php:65
       Tatter\Schemas\Commands\Schemas()->run()

  5    SYSTEMPATH/CLI/Console.php:46
       CodeIgniter\CLI\Commands()->run()

  6    ROOTPATH/spark:102
       CodeIgniter\CLI\Console()->run()

I believe this issue could be related to how the ModelHandler in the Tatter\Schemas package handles model instantiation, particularly with abstract classes like BaseModel in the Shield package.

Any guidance on resolving this error would be greatly appreciated.

Thank you.

Issue with optimization

If i have a big database with 100 tables, this schema and algorithm uses more and more when tables keep growing.

Do you guys want this to be optimized ?
You need some how to export the cache into separate files.

Like a schema for one table with all relations and export them like that.

This is usefull for debug only some parts and for optimization sake.

From 0.001 s with a normal Model im getting 0.1 seconds with Tatter Model.

I know this is because of the schema cache with all tables and when it reads it needs to search in all schema instead of the schema foreach table.

Is this a issue that you can solve ? or this isn`t a problem ?

Access to an undefined property Tatter\Schemas\Structures\Mergeable::$orders.

I created custom schema

<?php

declare(strict_types=1);

namespace Modules\Schemas\Custom;

use Tatter\Schemas\Structures\Relation;
use Tatter\Schemas\Structures\Schema;
use Tatter\Schemas\Structures\Table;

// SCHEMA
$schema = new Schema();

// TABLES
$schema->tables->orders = new Table('orders');
$schema->tables->users  = new Table('users');

// RELATIONS
// Orders->Users
$relation         = new Relation();
$relation->type   = 'belongsTo';
$relation->table  = 'users';
$relation->pivots = [
    ['orders', 'disponent_id', 'users', 'id'],
];
$schema->tables->orders->relations->users = $relation;

// Users->Orders
$relation         = new Relation();
$relation->type   = 'hasMany';
$relation->table  = 'orders';
$relation->pivots = [
    ['users', 'id', 'orders', 'disponent_id'],
];
$schema->tables->users->relations->orders = $relation;

// CLEANUP
unset($relation);

it's working as expected, but thre is an Phpstan issue.

 Line   modules/Schemas/Custom/Orders.php                                              
 ------ ------------------------------------------------------------------------------- 
  15     Access to an undefined property Tatter\Schemas\Structures\Mergeable::$orders.  
  16     Access to an undefined property Tatter\Schemas\Structures\Mergeable::$users.   
  26     Access to an undefined property Tatter\Schemas\Structures\Mergeable::$users.   
  35     Access to an undefined property Tatter\Schemas\Structures\Mergeable::$orders.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.