envor/laravel-datastore

v3.0.0 2024-12-16 19:47 UTC

README

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

A simple strategy for handling dynamic databases of varying types

Upgrade Guide

Upgrading from 1.x to 2.x.

2x does not push middleware by default, or configure context by default. To continue using as before add the following to your project's .env file:

DATASTORE_PUSH_CONTEXT_MIDDLEWARE=true
AUTOCONFIGURE_DEFAULT_CONTEXT=true

2x does not require envor/platform by default, Next you will need to manually require envor/platform

composer require envor/platform

Installation

You can install the package via composer:

composer require envor/laravel-datastore

You can publish and run the migrations with:

php artisan vendor:publish --tag="datastore-migrations"
php artisan migrate

You can publish the config file with:

php artisan vendor:publish --tag="datastore-config"

This is the contents of the published config file:

return [
    'model' => \Envor\Datastore\Models\Datastore::class,
    'create_databases' => env('DATASTORE_CREATE_DATABASES', true),
    'push_middleware' => env('DATASTORE_PUSH_CONTEXT_MIDDLEWARE', false),
    'autoconfigure_default_context' => env('AUTOCONFIGURE_DEFAULT_CONTEXT', false),
];

Usage

You actually don't need to use the model or even run migrations. You can use the factory directly like so:

use Envor\Datastore\DatabaseFactory;

$sqlite = DatabaseFactory::newDatabase('mydb', 'sqlite');

// Envor\Datastore\Databases\SQLite {#2841 ...

$sqlite->create();

// true

$sqlite->name;

// ...storage/app/datastore/mydb.sqlite

$sqlite->connection;

// mydb

$sqlite->migrate();

  //  INFO  Preparing database.  

  // Creating migration table ................ 9.55ms DONE

$sqlite->configure();


config('database.default');

// "mydb"

config('database.connections.mydb');

// [
//     "driver" => "sqlite",
//     "url" => null,
//     "database" => "...storage/app/datastore/mydb.sqlite",
//     "prefix" => "",
//     "foreign_key_constraints" => true,
//     "name" => "mydb",
// ]
    /**
     * Create a newly registered user.
     *
     * @param  array<string, string>  $input
     */
    public function create(array $input): User
    {
        $create = function () use ($input) {
            Validator::make($input, [
                'name' => ['required', 'string', 'max:255'],
                'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
                'password' => $this->passwordRules(),
                'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature() ? ['accepted', 'required'] : '',
            ])->validate();

            return DB::transaction(function () use ($input) {
                return tap(User::create([
                    'name' => $input['name'],
                    'email' => $input['email'],
                    'password' => Hash::make($input['password']),
                ]), function (User $user) {
                    $this->createTeam($user);
                });
            });
        };

        SQLite::make(database_path('my_backup.sqlite'))
            ->create()
            ->migratePath('database/migrations/platform')
            ->migrate()
            ->run($create)
            ->disconnect();
            
        MariaDB::make('backup')
            ->create()
            ->migratePath('database/migrations/platform')
            ->migrate()
            ->run($create)
            ->disconnect();

        return MariaDB::make('datastore')
            ->create()
            ->migratePath('database/migrations/platform')
            ->migrate()
            ->run($create)
            ->return();
    }

Middleware

You can use the 'datastore.context' middleware to get the app to behave in the context of the current datastore;

Route::get('/contexed', fn() => 'OK')->middleware('datastore.context');

// or
Route::get('/contexed', fn() => 'OK')->middleware(\Envor\Datastore\DatastoreContextMiddleware::class);

// will use the authenticated user to configure a database

Your user must implement the HasDatastoreContext interface in order for this to work.

...
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable implements \Envor\Datastore\Contracts\HasDatastoreContex
{
    use \Envor\Datastore\Concerns\BelongsToDatastore

    public function datastoreContext(): \Envor\Datastore\Contracts\ConfiguresDatastore;
    {
        return $this->datastore;
    }
}

Here are the relevant interfaces:

interface HasDatastoreContext
{
    public function datastoreContext(): ?\Envor\Datastore\Contracts\ConfiguresDatastore;
}


interface ConfiguresDatastore
{
    public function configure();

    public function use();

    public function database(): ?\Envor\Datastore\Datastore;
}

Testing

composer test

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

Credits

License

The MIT License (MIT). Please see License File for more information.