Support for many missing PostgreSQL specific features

Overview

License PHP PHP Latest Version on Packagist GitHub PHPUnit Action Status GitHub Psalm Action Status GitHub PhpCsFixer Action Status

Laravel supports many different databases and therefore has to limit itself to the lowest common denominator of all databases. PostgreSQL, however, offers a ton more functionality which is being added to Laravel by this extension.

Installation

You can install the package via composer:

composer require tpetry/laravel-postgresql-enhanced

Features

Migration

Extensions

Create Extensions

The Schema facade supports the creation of extensions with the createExtension and createExtensionIfNotExists methods:

use Tpetry\PostgresqlEnhanced\Support\Facades\Schema;

Schema::createExtension('tablefunc');
Schema::createExtensionIfNotExists('tablefunc');

Dropping Extensions

To remove extensions, you may use the dropExtension and dropExtensionIfExists methods provided by the Schema facade:

use Tpetry\PostgresqlEnhanced\Support\Facades\Schema;

Schema::dropExtension('tablefunc');
Schema::dropExtensionIfExists('tablefunc');

You may drop many extensions at once by passing multiple extension names:

use Tpetry\PostgresqlEnhanced\Support\Facades\Schema;

Schema::dropExtension('tablefunc', 'fuzzystrmatch');
Schema::dropExtensionIfExists('tablefunc', 'fuzzystrmatch');

Views

Create Views

The Schema facade supports the creation of views with the createView and createViewOrReplace methods. The definition of your view can be a sql query string or a query builder instance:

use Illuminate\Support\Facades\DB;
use Tpetry\PostgresqlEnhanced\Support\Facades\Schema;

Schema::createView('users_with_2fa', 'SELECT * FROM users WHERE two_factor_secret IS NOT NULL');
Schema::createViewOrReplace('users_without_2fa', DB::table('users')->whereNull('two_factor_secret'));

If you need to create recursive views the createRecursiveView and createRecursiveViewOrReplace methods can be used like in the former examples but you need to provide the available columns as last parameter:

use Illuminate\Support\Facades\DB;
use Tpetry\PostgresqlEnhanced\Support\Facades\Schema;

// TODO simple example explaining the concept
Schema::createView('viewname', 'SELECT id, col1, col2 FROM ....', ['id', 'col1', 'col2']);
Schema::createViewOrReplace('viewname', 'SELECT id, col1, col2 FROM ....', ['id', 'col1', 'col2']);

Dropping Views

To remove views, you may use the dropView and dropViewIfExists methods provided by the Schema facade. You don't have to distinguish normala and recursive views:

use Tpetry\PostgresqlEnhanced\Support\Facades\Schema;

Schema::dropView('myview');
Schema::dropViewIfExists('myview');

You may drop many views at once by passing multiple view names:

use Tpetry\PostgresqlEnhanced\Support\Facades\Schema;

Schema::dropExtension('myview1', 'myview2');
Schema::dropExtensionIfExists('myview1', 'myview2');

Indexes

Drop If Exists

In addition to the Laravel methods to drop indexes, methods to drop indexes if they exist have been added. The methods dropIndexIfExists, dropPrimaryIfExists, dropSpatialIndexIfExists and dropSpatialIndexIfExists match the semantics of their laravel originals.

Create Partial Indexes

A partial index is an index built over a subset of a table; the subset is defined by a condition. The index contains entries only for those table rows that satisfy the condition. Partial indexes are a specialized feature, but there are several situations in which they are useful. Take for example you want to make the email address column of your users table unique and you are using soft-deletes. This is not possible because by deleting a user and creating it again the email address is used twice. With partial indexes this can be done by limiting the index to only untrashed rows:

use Illuminate\Database\Query\Builder;
use Tpetry\PostgresqlEnhanced\Schema\Blueprint;
use Tpetry\PostgresqlEnhanced\Support\Facades\Schema;

Schema::table('users', function(Blueprint $table) {
    $table->partialUnique(['email'], fn (Builder $condition) => $condition->whereNull('deleted_at'));
});

Partial Indexes are created with the partialIndex, partialSpatialIndex, partialUnique methods. The name of the index is created automatically like for normal laravel indexes, if you want to change the name pass it's value as third parameter.

Special attention is needed for dropping partial unique indexes, you need to use the special partial drop methods: dropPartialUnique and dropPartialUniqueIfExists.

Column Types

Bit Strings

The bit string data types store strings of 0s and 1s. They can be used to e.g. store bitmaps.

// @see https://www.postgresql.org/docs/current/datatype-bit.html
$table->bit(string $column, int $length = 1);
$table->varbit(string $column, ?int $length = null);

Case Insensitive Text

The case insensitive text type is used to store a text that will be compared case insensitive. It can be used to e.g. store and compare e-mail addresses.

// @see https://www.postgresql.org/docs/current/citext.html
$table->caseInsensitiveText(string $column);

IP Networks

The ip network datatype stores an ip network in cidr notation.

// @see https://www.postgresql.org/docs/current/datatype-net-types.html
$table->ipNetwork(string $column);

Hstore

The hstore data type is used store key/value pairs within a single PostgreSQL value. The new json data type is better in all aspects, so hstore should only be used for compatibility with old applications.

// @see https://www.postgresql.org/docs/current/hstore.html
$table->hstore(string $column);

International Product Numbers

The international product number data types are used to store common product numbers types and validate them before saving.

// @see https://www.postgresql.org/docs/current/isn.html
$table->europeanArticleNumber13(string $column);
$table->internationalStandardBookNumber(string $column);
$table->internationalStandardBookNumber13(string $column);
$table->internationalStandardMusicNumber(string $column);
$table->internationalStandardMusicNumber13(string $column);
$table->internationalStandardSerialNumber(string $column);
$table->internationalStandardSerialNumber13(string $column);
$table->universalProductNumber(string $column);

Label Tree

The ltree data type stores a label as its position in a tree. This provides an easy way to manage a tree without performance and complexity disadvantages compared to alternative solutions.

// @see https://www.postgresql.org/docs/current/ltree.html
$table->labelTree(string $column);

Ranges

The range data types store a range of values with optional start and end values. They can be used e.g. to describe the duration a meeting room is booked.

// @see https://www.postgresql.org/docs/current/rangetypes.html
$table->bigIntegerRange(string $column);
$table->dateRange(string $column);
$table->decimalRange(string $column);
$table->integerRange(string $column);
$table->timestampRange(string $column);
$table->timestampTzRange(string $column);

XML

The xml data type can be used to store an xml document.

// @see https://www.postgresql.org/docs/current/datatype-xml.html
$table->xml(string $column);

Changelog

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

Security Vulnerabilities

If you discover any security related issues, please email [email protected] instead of using the issue tracker.

License

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

Comments
  • Add returning methods to Eloquent Builder

    Add returning methods to Eloquent Builder

    This PR add the ability to call *Returning methods on Eloquent Builder and retrieve the results as models.

    The tests are pretty minimal but should be a good starting point.

    The implementation is based on Builder::get (https://github.com/laravel/framework/blob/9.x/src/Illuminate/Database/Eloquent/Builder.php#L669-L700)

    I don't know if adding eager loading ability should be done but it could be added here or on another PR if needed.

    opened by bastien-phi 18
  • [DRAFT] feat: support functions

    [DRAFT] feat: support functions

    This PR adds support to create functions. We can of course change the signature but this is just a first proposal because I think it would be a great addition.

    opened by jaulz 17
  • Add feature to work with With and with recursive.

    Add feature to work with With and with recursive.

    Excellent package, I've been using it for a long time.

    Recently I needed to use with and with recursive and I wanted to use it in the model and not DB.

    Would it be possible to add?

    I even made it locally for myself, but the code I made I don't think it's feasible to put on the air, but I've extended the service provider and made changes so that Grammer has this method:

      /**
         * Compile the select query into SQL.
         *
         * @param \Illuminate\Database\Query\Builder $query
         * @return string
         */
        public function compileSelect(Builder $query)
        {
            $sql = parent::compileSelect($query);
    
            $withQuery = $query->withQuery;
    
            if ($withQuery) {
                $withQuery .= ' ';
            }
    
            return "{$withQuery}{$sql}";
        }
    

    Query\Builder I added:

       public $withQuery = '';
        public function withQuery($query = null)
        {
            $this->withQuery = $query;
    
            return $this;
        }
    

    It works for me, but it could be better by adding the bindings and making the code better.

    enhancement 
    opened by emtudo 10
  • Why running function created in with table data returned raised error ?

    Why running function created in with table data returned raised error ?

    In laravel9.6.0 app using tpetry/laravel-postgresql-enhanced 0.20.0 I create function with table data returned :

    return new class extends Migration
    {
        public function up()
        {
            Schema::createFunctionOrReplace('ts_categories_get', ['sort_field' => 'character varying'],
                'TABLE(id smallint, name character varying, active boolean, slug character varying, description text,
                 created_at timestamp, updated_at timestamp)', 'plpgsql', '
    
      BEGIN
        SELECT ts_categories.id, ts_categories.name, ts_categories.active, ts_categories.slug, ts_categories.description,
        ts_categories.created_at, ts_categories.updated_at
            from ts_categories;
      END;
    
    ');
        }
    
    

    But running the function : SELECT ts_categories_get('name') I got error : ERROR: query has no destination for result data HINT: If you want to discard the results of a SELECT, use PERFORM instead. CONTEXT: PL/pgSQL function ts_categories_get(character varying) line 4 at SQL statement In statement: SELECT ts_categories_get('name') I see in phppgadmin this function defined as : https://prnt.sc/TuNTxr6-TcxM

    What is wrong ?

    Thanks!

    enhancement 
    opened by sergeynilov 9
  • lazy() via cursor fetching

    lazy() via cursor fetching

    Eloquents lazy() has the problem of making new queries for each chunk via OFFSET+LIMIT, which doesn't give a stable result if something changed in parallel. Meanwhile lazyById prevents applying own ordering, plus aren't completely safe from changes in parallel requests either. And chunk() ends up with all the results queried out into memory at PDO level, which is unsuitable for dealing with a lot of rows.

    So I had to come up with a version that overcomes all that by making use of PostgreSQL cursors to handle the chunking. Here's a quick (and perhaps a bit dirty in regards to toSql() usage) macro that does this:

        public function boot()
        {
            Builder::macro('lazyFetch', function(int $chunkSize = 1000) {
                if ($chunkSize < 1) {
                    throw new InvalidArgumentException('The chunk size should be at least 1');
                }
                if (DB::transactionLevel() <= 0) {
                    throw new RuntimeException('lazyFetch can only be used within a DB transaction');
                }
    
                return LazyCollection::make(function () use ($chunkSize) {
                    $cursorName = 'lazy_fetch_' . spl_object_id($this);
                    DB::statement("DECLARE {$cursorName} NO SCROLL CURSOR FOR " . $this->toSql(), $this->getBindings());
    
                    while (true) {
                        $results = DB::select("FETCH FORWARD {$chunkSize} FROM {$cursorName}");
    
                        foreach ($results as $result) {
                            yield $result;
                        }
    
                        if (count($results) < $chunkSize) {
                            DB::statement("CLOSE {$cursorName}");
                            return;
                        }
                    }
                });
            });
        }
    

    and then it can be used by just using lazyFetch() instead of lazy() to get a stable LazyCollection. It might even be a good idea to use that for lazy() automatically if within a transaction?

    Anyhow, I think it might be a good fit into laravel-postgresql-enhanced in some form. If so, how would it be integrated into a package like laravel-postgresql-enhanced is for easy usage by programs? Might take a stab at making a PR for this if I knew which way to integrate it into the package.

    enhancement 
    opened by leio 9
  • Making sure a CTE is only added once

    Making sure a CTE is only added once

    I have a model Location with relationships to organization and region models. Each of those is part of a hierarchical structure, stored in the database as an adjacency list.

    For example:

    • Location 1 has region_id = 2 and organization_id = 3
    • Region 2 has parent_id = 20
    • Organization 3 has parent_id = 33

    When users load a list of locations, there are two sets of where clauses that need to be applied:

    1. Filter based on the user's permissions (at the organization, region, or location level; via an assignments table with a morphTo relationship)
    2. Filter based on the user's request (also at the organization, region, or location level)

    My Location model has this scope for the first filter:

    public function scopeUserCanAccess($rootQuery, User $user)
    {
        $rootQuery->where(function ($query) use ($user, $rootQuery) {
            $addedOrgCTE = false;
            $addedRegionCTE = false;
    
            foreach ($user->assignments as $assignment) {
                switch ($assignment->assignable_type) {
                    case 'organization':
                        if (!$addedOrgCTE) {
                            $orgQuery = Organization::query()
                                ->select('id', 'parent_id')
                                ->where('id', $assignment->assignable_id)
                                ->unionAll(
                                    Organization::query()
                                        ->select('organizations.id', 'organizations.parent_id')
                                        ->join('org_tree', 'org_tree.id', 'organizations.parent_id')
                                );
                            $rootQuery->withExpression('org_tree', $orgQuery, ['recursive' => true]);
                            $addedOrgCTE = true;
                        }
                        $query->orWhereIn('organization_id', function ($query) {
                            $query->select('id')->from('org_tree');
                        });
                        break;
                    case 'region':
                        if (!$addedRegionCTE) {
                            $regionQuery = Region::query()
                                ->select('id', 'parent_id')
                                ->where('id', $assignment->assignable_id)
                                ->unionAll(
                                    Region::query()
                                        ->select('regions.id', 'regions.parent_id')
                                        ->join('region_tree', 'region_tree.id', 'regions.parent_id')
                                );
                            $rootQuery->withExpression('region_tree', $regionQuery, ['recursive' => true]);
                            $addedRegionCTE = true;
                        }
                        $query->orWhereIn('region_id', function ($query) {
                            $query->select('id')->from('region_tree');
                        });
                        break;
                    case 'location':
                        $query->orWhere('id', $assignment->assignable_id);
                        break;
                }
            }
        });
    }
    

    For the second filter, I have this function that modifies the query based on the request:

    public function filterQuery($request, $rootQuery)
    {
        $rootQuery->where(function ($query) use ($rootQuery) {
            $addedOrgCTE = true;
            $addedRegionCTE = false;
    
            if ($request->has('organization')) {
                $rawArg = $request->organization;
                $arg = str_contains($rawArg, ',') ? explode(',', $rawArg) : [$rawArg];
                if (!$addedOrgCTE) {
                    $orgQuery = Organization::query()
                        ->select('id', 'parent_id')
                        ->whereIn('id', $arg)
                        ->unionAll(
                            Organization::query()
                                ->select('organizations.id', 'organizations.parent_id')
                                ->join('org_tree', 'org_tree.id', 'organizations.parent_id')
                        );
                    $rootQuery->withExpression('org_tree', $orgQuery, ['recursive' => true]);
                    $addedOrgCTE = true;
                }
                $query->orWhereIn('organization_id', function ($query) {
                    $query->select('id')->from('org_tree');
                });
            }
    
            if ($request->has('region')) {
                $rawArg = $request->region;
                $arg = str_contains($rawArg, ',') ? explode(',', $rawArg) : [$rawArg];
                if (!$addedRegionCTE) {
                    $regionQuery = Region::query()
                        ->select('id', 'parent_id')
                        ->whereIn('id', $arg)
                        ->unionAll(
                            Region::query()
                                ->select('regions.id', 'regions.parent_id')
                                ->join('region_tree', 'region_tree.id', 'regions.parent_id')
                        );
                    $rootQuery->withExpression('region_tree', $regionQuery, ['recursive' => true]);
                    $addedRegionCTE = true;
                }
                $query->orWhereIn('region_id', function ($query) {
                    $query->select('id')->from('region_tree');
                });
            }
    
            if ($request->has('location')) {
                $rawArg = $request->location;
                $arg = str_contains($rawArg, ',') ? explode(',', $rawArg) : [$rawArg];
                $query->orWhereIn('id', $arg);
            }
        });
    }
    

    The problem I have is that this generates an invalid query because it adds the same CTE (org_tree or region_tree) twice.

    Is there any way I can check if a CTE is already added before I add it again, or we can change the withExpression method to not add an expression with the same name as one that is already present?

    bug enhancement 
    opened by kohenkatz 7
  • Larastan undefined property when accessing model properties

    Larastan undefined property when accessing model properties

    Hello, First off I want to say thank you for all the hard work you've put into this amazing package.

    I ran into an issue where Larastan is giving me errors when I access model properties that were defined in migrations using the package's Blueprint class. For example, given the following user migration:

    <?php
    
    use Illuminate\Database\Migrations\Migration;
    use Tpetry\PostgresqlEnhanced\Schema\Blueprint;
    use Tpetry\PostgresqlEnhanced\Support\Facades\Schema;
    
    class CreateUsersTable extends Migration
    {
        public function up()
        {
            Schema::create('users', function (Blueprint $table) {
                $table->uuid('id')->primary();
                $table->string('name');
                $table->caseInsensitiveText('email')->unique()->index();
            });
        }
    }
    

    Calling properties on the model with $user->name or $user->email will give the following error:

    ------ ---------------------------------------------------------- 
      Line   Data/AuthData.php                                         
     ------ ---------------------------------------------------------- 
      49     Access to an undefined property App\Models\User::$name.   
      51     Access to an undefined property App\Models\User::$email.  
     ------ ---------------------------------------------------------- 
    

    It's easy enough to work around by annotating the model.

    /**
     * @property string $name
     * @property string $email
     */
    class User extends Authenticatable
    

    But since I'm using the package's phpstan extension I figured I'd ask if this is expected functionality or if I'm missing something obvious.

    Thanks again!


    Environment Details

    composer.json

    "php": "^8.1",
    "laravel/framework": "^9.43",
    "nunomaduro/larastan": "^2.2.9",
    "tpetry/laravel-postgresql-enhanced": "^0.23.0"
    

    phpstan.neon

    includes:
        - ./vendor/nunomaduro/larastan/extension.neon
        - ./vendor/tpetry/laravel-postgresql-enhanced/phpstan-extension.neon
    
    parameters:
        level: 8
    
    bug 
    opened by benbjurstrom 7
  • `LIKE` query does not work with `citext`

    `LIKE` query does not work with `citext`

    It seems that the LIKE query is not working with citext columns. I assume that it's related to this piece of code: https://github.com/laravel/framework/blob/aad4521c6a5c91a8fc0b9acbc2362c281013daea/src/Illuminate/Database/Query/Grammars/PostgresGrammar.php#L42-L47

    The column will be casted into text and thus any case insensitive search isn't working anymore. Is there any smart way to solve it?

    opened by jaulz 6
  • Laravel 9 TypeError

    Laravel 9 TypeError

    Hi, I'm getting a TypeError trying to use this on Laravel 9. What am I doing wrong?

    TypeError 
    
    Illuminate\Database\Migrations\Migration@anonymous(): Argument #1 ($table) must be of type Tpetry\PostgresqlEnhanced\Schema\Blueprint, Illuminate\Database\Schema\Blueprint given, called in
    /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Schema/Builder.php on line 256 
    

    Migration:

    <?php
    
    use Illuminate\Database\Migrations\Migration;
    use Tpetry\PostgresqlEnhanced\Schema\Blueprint;
    use Tpetry\PostgresqlEnhanced\Schema\Concerns\ZeroDowntimeMigration;
    use Tpetry\PostgresqlEnhanced\Support\Facades\Schema;
    
    return new class extends Migration
    {
        use ZeroDowntimeMigration;
    
        /**
         * Run the migrations.
         *
         * @return void
         */
        public function up()
        {
            Schema::create('somethings', function (Blueprint $table) {
            // ...
    
    question 
    opened by LiamKarlMitchell 6
  • fix: implement base contract

    fix: implement base contract

    Occasionally I see this error when I type my arguments:

    Argument #1 ($builder) must be of type Illuminate\Contracts\Database\Eloquent\Builder, Tpetry\PostgresqlEnhanced\Query\Builder given
    

    I think this change should not have any side effects.

    opened by jaulz 5
  • feat: support `ON TRUE`

    feat: support `ON TRUE`

    This PR just provides the general idea of supporting an ON TRUE condition. If you want to return a NULL-extended row in the case where the lateral join returns no rows, then you would use LEFT JOIN LATERAL (...) ON TRUE. You can already achieve it with the current implementation by providing the values manually but extending this library would even make it easier. What do you think?

    opened by jaulz 5
  • Compatibility with other Postgres libraries

    Compatibility with other Postgres libraries

    Hello! I use Postgres heavily and am very excited to see that you started this project.

    Right now I have umbrellio/laravel-pg-extensions implemented and have used its "Custom Extensions" method for adding other new functionality I needed. On top of that library I have umbrellio/laravel-ltree, belamov/postgres-range, staudenmeir/laravel-adjacency-list, and with it staudenmeir/laravel-cte.

    Most of the custom functionality I've added is already handled by your library, so I would just be able to remove that on my end. LTree I can just use the Eloquent helpers and your library can do the schema stuff. You also support ranges so that's easy. I do use Laravel Adjacency List heavily so I'm wondering how it would work with both libraries implementing CTE (maybe no issue if there's no naming conflict?), and then compatibility with other Postgres libraries in general.

    I think the main issue I run into when I'm trying to get these libraries to work together is when there's conflicts with the PostgresConnection. And then some way for multiple libraries to extend Blueprint and Schema Grammar which is what the Custom Extension method allows for.

    So far I've used the umbrellio/laravel-pg-extensions implementation of PostgresConnection and extended that. Then when there's conflicts, which I ran into with belamov/postgres-range and staudenmeir/laravel-cte, I just implement them manually using the Custom Extension method so that they do not load their versions of the PostgresConnection, and prevent them from being automatically discovered by Laravel using composer.json:

    "extra": {
        "laravel": {
            "dont-discover": [
              "belamov/postgres-range",
              "staudenmeir/laravel-cte"
            ]
        }
    }
    

    Switching to your library I won't have that Custom Extension method anymore, which means I don't have a clear way to deal with conflicts, so I know that will be the main challenge in transitioning here.

    Of course this is out of scope of this repository but I thought I'd ask just in case you have some insight here. Either way, I do plan to try this transition in just the next few days, so if you're not sure I'll go ahead and just update this issue with anything that I find, maybe help others in the future.

    I am so excited about this library, thank you so much for starting this!

    wontfix 
    opened by kdevan 4
  • Extended PostgreSQL types are not supported with the Laravel IDE Helper Generator

    Extended PostgreSQL types are not supported with the Laravel IDE Helper Generator

    When running composer update which regenerates ide-helper stubs, I go this as it was analyzing the models.

    Exception: Unknown database type citext requested, Doctrine\DBAL\Platforms\PostgreSQL100Platform may not support it.
    Could not analyze class App\Models\Tag.
    

    The fix was easy enough, in AppServiceProvider I put:

    <?php
    // ...
    use Tpetry\PostgresqlEnhanced\Types\CitextType;
    class AppServiceProvider extends ServiceProvider
    {
    ...
        public function boot(){
            \app('db')->registerDoctrineType(CitextType::class, 'citext', 'string');
            // ...
        }
    

    As I was looking at the code in the vendor folder, I noticed the $typeInstance->getName() is deprecated in doctrine, not sure if that is related,and I'm not sure that's the best way to register the doctrine type, but it made the error go away..

    bug 
    opened by patrickcurl 3
  • Support `whereIsDistinctFrom` and `whereNotIsDistinctFrom`

    Support `whereIsDistinctFrom` and `whereNotIsDistinctFrom`

    The IS DISTINCT FROM and IS NOT DISTINCT FROM terms simplify a query a lot for nullable columns:

    col IS DISTINCT FROM 'value' simplifies a query with nullable columns as it is a replacement for (col IS NULL OR col != 'value')

    enhancement 
    opened by tpetry 0
  • Nulls first/last

    Nulls first/last

    I think it would be a great addition if we could order by nulls first/last, i.e. see https://www.postgresql.org/docs/current/sql-select.html#SQL-ORDERBY. Maybe as a new Builder trait? What do you think?

    If possible, we should also try to support CursorPaginator since it does not work with raw values at the moment.

    enhancement 
    opened by jaulz 4
Releases(0.5.0)
Owner
Tobias Petry
Tobias Petry
PHP Object Model Manager for Postgresql

POMM: The PHP Object Model Manager for Postgresql Note This is the 1,x version of Pomm. This package is not maintained anymore, the stable Pomm 2.0 is

Grégoire HUBERT 161 Oct 17, 2022
🔌 A Doctrine DBAL Driver implementation on top of Swoole Coroutine PostgreSQL extension

Swoole Coroutine PostgreSQL Doctrine DBAL Driver A Doctrine\DBAL\Driver implementation on top of Swoole\Coroutine\PostgreSQL. Getting started Install

Leo Cavalcante 19 Nov 25, 2022
phpMyFAQ - Open Source FAQ web application for PHP and MySQL, PostgreSQL and other databases

phpMyFAQ 3.1 What is phpMyFAQ? phpMyFAQ is a multilingual, completely database-driven FAQ-system. It supports various databases to store all data, PHP

Thorsten Rinne 547 Dec 27, 2022
Laravel Thermite is an extended PostgreSQL Laravel database driver to connect to a CockroachDB cluster.

Laravel Thermite Laravel Thermite is an extended PostgreSQL Laravel database driver to connect to a CockroachDB cluster. ?? Supporting If you are usin

Renoki Co. 9 Nov 15, 2022
A simple library to access and manipulate database records. Built on top of Dibi and hardwired for PostgreSQL.

grifart/tables A simple library to access and manipulate database records. Built on top of Dibi and hardwired for PostgreSQL. This library is develope

GRIFART 5 Nov 11, 2022
PostgreSQL enhancements for Doctrine

PostgreSQL enhancements for Doctrine. Provides support for advanced data types (json, jssnb, arrays), text search, array operators and jsonb specific functions.

Martin Georgiev 258 Dec 31, 2022
Orm is a simple database abstraction layer that supports postgresql.

Orm What is it Orm is a simple database abstraction layer that supports postgresql. Welcome to join us or star us for encouragement. Requires php 8.1

null 2 Sep 28, 2022
A Laravel package to output a specific sql to your favourite debugging tool. The supported log output is Laravel Telescope, Laravel Log, Ray, Clockwork, Laravel Debugbar and your browser.

Laravel showsql A Laravel package to output a specific sql to your favourite debugging tool, your browser or your log file. Use case You often want to

Dieter Coopman 196 Dec 28, 2022
Phpstan-dba - database handling related class reflection extension for PHPStan & framework-specific rules

database handling class reflection extension for PHPStan This extension provides following features: PDO->query knows the array shape of the returned

Markus Staab 175 Dec 29, 2022
A drop-in library for certain database functionality in Laravel, that allows for extra features that may never make it into the main project.

Eloquence Eloquence is a package to extend Laravel's base Eloquent models and functionality. It provides a number of utilities and classes to work wit

Kirk Bushell 470 Dec 8, 2022
:gem: Simple MySQLi Abstraction Layer + Doctrine/DBAL support

?? Simple MySQLi Class This is a simple MySQL Abstraction Layer compatible with PHP 7+ that provides a simple and secure interaction with your databas

Lars Moelleken 40 Sep 5, 2022
MySQL Load Data Infile Support For Laravel

Laravel Load File ?? A package to help with loading files into MySQL tables. This uses MySQL's LOAD DATA statement to load text files quickly into you

Ellis Green 64 Dec 30, 2022
MongoDB ORM that includes support for references,embed and multilevel inheritance.

Introduction Features Requirements Installation Setup Database Basic Usage - CRUD Relationship - Reference Relationship - Embed Collection Inheritance

Michael Gan 202 Nov 17, 2022
Extend Jenssegers/laravel-mongodb to support transaction function

Laravel Mongodb (Transactional support) Introduction Jensseger's laravel-mongodb extension package is very popular among Laravel developers, but it la

Iman RJ 10 Nov 1, 2022
This plugin allows you to create many-to-many relationships between pages in Kirby and synchronizes them on both sides.

Kirby 3 Many To Many Field This plugin allows you to create many-to-many relationships between pages in Kirby.

Jonas Holfeld 41 Nov 19, 2022
This is a lightweight package that allows you assign roles and permissions to any Laravel model, or on a pivot table (many to many relationship).

Simple Laravel roles and permissions Introduction This package allows you to assign roles and permissions to any laravel model, or on a pivot table (m

null 52 Nov 10, 2022
Pico disk, Not need any database, support html5, support mp3, mp4, support streaming media, support AriaNg

Nano netdisk, Now changed to pico disk. Pico disk,does not need any database, support html5, support mp3, mp4, support streaming media, support AriaNg.

null 53 Dec 26, 2022
A PocketMine-MP plugin which let's you whitelist specific commands on specific worlds.

LevelLimiter A PocketMine-MP plugin which let's you whitelist specific commands on specific worlds. Config.yml Set up the commands and the whitelisted

MCA7 7 Aug 6, 2022
LaraAdmin is a Open source Laravel Admin Panel / CMS which can be used as Admin Backend, Data Management Tool or CRM boilerplate for Laravel with features like Advanced CRUD Generation, Module Manager, Backups and many more.

LaraAdmin 1.0 LaraAdmin is a Open source CRM for quick-start Admin based applications with features like Advanced CRUD Generation, Schema Manager and

Dwij IT Solutions 1.5k Dec 29, 2022