-
-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
89b781a
commit ef8ca95
Showing
28 changed files
with
1,271 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
/tests export-ignore | ||
.gitattributes export-ignore | ||
.gitignore export-ignore | ||
.scrutinizer.yml export-ignore | ||
.travis.yml export-ignore | ||
phpunit.xml.dist export-ignore |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/.idea | ||
/.vagrant | ||
/vendor | ||
.phpunit.result.cache | ||
after.sh | ||
aliases | ||
composer.lock | ||
Homestead.yaml | ||
Vagrantfile |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
tools: | ||
external_code_coverage: | ||
runs: 3 | ||
timeout: 600 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
language: php | ||
|
||
dist: xenial | ||
|
||
services: | ||
- mysql | ||
- postgresql | ||
|
||
env: | ||
global: | ||
- COVERAGE=no | ||
- DB=mysql | ||
- RELEASE=stable | ||
|
||
matrix: | ||
include: | ||
- php: 7.0 | ||
- php: 7.0 | ||
env: RELEASE=lowest | ||
- php: 7.1 | ||
- php: 7.2 | ||
- php: 7.3 | ||
env: COVERAGE=yes | ||
- php: 7.3 | ||
env: COVERAGE=yes DB=pgsql | ||
- php: 7.3 | ||
env: COVERAGE=yes DB=sqlite | ||
|
||
cache: | ||
directories: | ||
- $HOME/.composer/cache | ||
|
||
before_install: | ||
- COMPOSER_FLAGS=$([ $RELEASE == "lowest" ] && echo "--prefer-lowest" || echo "") | ||
- PHPUNIT_FLAGS=$([ $COVERAGE == "yes" ] && echo "--coverage-clover=coverage.xml" || echo "") | ||
|
||
install: | ||
- travis_retry composer update --no-interaction --no-suggest --prefer-dist --prefer-stable $COMPOSER_FLAGS | ||
|
||
before_script: | ||
- cp tests/config/database.travis.php tests/config/database.php | ||
- mysql -e 'create database `test`;' | ||
- psql -c 'create database "test";' -U postgres | ||
|
||
script: | ||
- vendor/bin/phpunit $PHPUNIT_FLAGS | ||
|
||
after_script: | ||
- | | ||
if [ $COVERAGE == "yes" ]; then | ||
travis_retry wget https://scrutinizer-ci.com/ocular.phar | ||
travis_retry php ocular.phar code-coverage:upload --format=php-clover coverage.xml | ||
fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
[![Build Status](https://travis-ci.org/staudenmeir/laravel-upsert.svg?branch=master)](https://travis-ci.org/staudenmeir/laravel-upsert) | ||
[![Code Coverage](https://scrutinizer-ci.com/g/staudenmeir/laravel-upsert/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/staudenmeir/laravel-upsert/?branch=master) | ||
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/staudenmeir/laravel-upsert/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/staudenmeir/laravel-upsert/?branch=master) | ||
[![Latest Stable Version](https://poser.pugx.org/staudenmeir/laravel-upsert/v/stable)](https://packagist.org/packages/staudenmeir/laravel-upsert) | ||
[![Total Downloads](https://poser.pugx.org/staudenmeir/laravel-upsert/downloads)](https://packagist.org/packages/staudenmeir/laravel-upsert) | ||
[![License](https://poser.pugx.org/staudenmeir/laravel-upsert/license)](https://packagist.org/packages/staudenmeir/laravel-upsert) | ||
|
||
## Introduction | ||
This Laravel extension adds support for INSERT & UPDATE (UPSERT) and INSERT IGNORE to the query builder and Eloquent. | ||
|
||
Supports Laravel 5.5+. | ||
|
||
## Compatibility | ||
|
||
- MySQL 5.1+: [INSERT ON DUPLICATE KEY UPDATE](https://dev.mysql.com/doc/refman/en/insert-on-duplicate.html) | ||
- MariaDB 5.1+: [INSERT ON DUPLICATE KEY UPDATE](https://mariadb.com/kb/en/library/insert-on-duplicate-key-update/) | ||
- PostgreSQL 9.5+: [INSERT ON CONFLICT](https://www.postgresql.org/docs/current/sql-insert.html#SQL-ON-CONFLICT) | ||
- SQLite 3.24.0+: [INSERT ON CONFLICT](https://www.sqlite.org/lang_UPSERT.html) | ||
- SQL Server 2008+: [MERGE](https://docs.microsoft.com/sql/t-sql/statements/merge-transact-sql) | ||
|
||
## Installation | ||
|
||
composer require staudenmeir/laravel-upsert:"^1.0" | ||
|
||
## Usage | ||
|
||
- [INSERT & UPDATE (UPSERT)](#insert--update-upsert) | ||
- [INSERT IGNORE](#insert-ignore) | ||
- [Eloquent](#eloquent) | ||
- [Lumen](#lumen) | ||
|
||
### INSERT & UPDATE (UPSERT) | ||
|
||
Consider this `users` table with a unique `username` column: | ||
|
||
```php | ||
Schema::create('users', function (Blueprint $table) { | ||
$table->increments('id'); | ||
$table->string('username')->unique(); | ||
$table->boolean('active'); | ||
$table->timestamps(); | ||
}); | ||
``` | ||
|
||
Use `upsert()` to insert a new user or update the existing one. In this example, an inactive user will be reactivated and the `updated_at` timestamp will be updated: | ||
|
||
```php | ||
DB::table('users')->upsert( | ||
['username' => 'foo', 'active' => true, 'created_at' => now(), 'updated_at' => now()], | ||
'username', | ||
['active', 'updated_at'] | ||
); | ||
``` | ||
|
||
Provide the values to be inserted as the first argument. This can be a single record or multiple records. | ||
|
||
The second argument is the column(s) that uniquely identify records. All databases except SQL Server require these columns to have a `PRIMARY` or `UNIQUE` index. | ||
|
||
Provide the columns to be the updated as the third argument (optional). By default, all columns will be updated. | ||
You can provide column names and key-value pairs with literals or raw expressions (see below). | ||
|
||
As an example with a composite key and a raw expression, consider this table that counts visitors per post and day: | ||
|
||
```php | ||
Schema::create('stats', function (Blueprint $table) { | ||
$table->unsignedInteger('post_id'); | ||
$table->date('date'); | ||
$table->unsignedInteger('views'); | ||
$table->unique(['post_id', 'date']); | ||
}); | ||
``` | ||
|
||
Use `upsert()` to log visits. The query will create a new record per post and day or increment the existing view counter: | ||
|
||
```php | ||
DB::table('stats')->upsert( | ||
[ | ||
['post_id' => 1, 'date' => now()->toDateString(), 'views' => 1], | ||
['post_id' => 2, 'date' => now()->toDateString(), 'views' => 1], | ||
], | ||
['post_id', 'date'], | ||
['views' => DB::raw('stats.views + 1')] | ||
); | ||
``` | ||
|
||
### INSERT IGNORE | ||
|
||
You can also insert records while ignoring duplicate-key errors: | ||
|
||
```php | ||
Schema::create('users', function (Blueprint $table) { | ||
$table->increments('id'); | ||
$table->string('username')->unique(); | ||
$table->timestamps(); | ||
}); | ||
|
||
DB::table('users')->insertIgnore([ | ||
['username' => 'foo', 'created_at' => now(), 'updated_at' => now()], | ||
['username' => 'bar', 'created_at' => now(), 'updated_at' => now()], | ||
]); | ||
``` | ||
|
||
SQL Server requires a second argument with the column(s) that uniquely identify records: | ||
|
||
```php | ||
DB::table('users')->insertIgnore( | ||
['username' => 'foo', 'created_at' => now(), 'updated_at' => now()], | ||
'username' | ||
); | ||
``` | ||
|
||
### Eloquent | ||
|
||
You can use UPSERT and INSERT IGNORE queries in Eloquent with the `HasUpsertQueries` trait: | ||
|
||
```php | ||
class User extends Model | ||
{ | ||
use \Staudenmeir\LaravelUpsert\Eloquent\HasUpsertQueries; | ||
} | ||
|
||
User::upsert(['username' => 'foo', 'active' => true], 'username', ['active']); | ||
|
||
User::insertIgnore(['username' => 'foo']); | ||
``` | ||
|
||
If the model uses timestamps, `upsert()` and `insertIgnore()` will automatically add timestamps to the inserted values. `upsert()` will also add `updated_at` to the updated columns. | ||
|
||
### Lumen | ||
|
||
If you are using Lumen, you have to instantiate the query builder manually: | ||
|
||
```php | ||
$builder = new \Staudenmeir\LaravelUpsert\Query\Builder(app('db')->connection()); | ||
|
||
$builder->from(...)->upsert(...); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
{ | ||
"name": "staudenmeir/laravel-upsert", | ||
"description": "Laravel UPSERT and INSERT IGNORE queries", | ||
"license": "MIT", | ||
"authors": [ | ||
{ | ||
"name": "Jonas Staudenmeir", | ||
"email": "[email protected]" | ||
} | ||
], | ||
"require": { | ||
"php": ">=7.0", | ||
"illuminate/database": "5.5.*|5.6.*|5.7.*" | ||
}, | ||
"require-dev": { | ||
"laravel/homestead": "^7.0", | ||
"orchestra/testbench": "^3.5" | ||
}, | ||
"autoload": { | ||
"psr-4": { | ||
"Staudenmeir\\LaravelUpsert\\": "src/" | ||
} | ||
}, | ||
"autoload-dev": { | ||
"psr-4": { | ||
"Tests\\": "tests/" | ||
} | ||
}, | ||
"extra": { | ||
"laravel": { | ||
"providers": [ | ||
"Staudenmeir\\LaravelUpsert\\DatabaseServiceProvider" | ||
] | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<phpunit backupGlobals="false" | ||
backupStaticAttributes="false" | ||
colors="true" | ||
convertErrorsToExceptions="true" | ||
convertNoticesToExceptions="true" | ||
convertWarningsToExceptions="true" | ||
processIsolation="false" | ||
stopOnError="false" | ||
stopOnFailure="false" | ||
verbose="true" | ||
> | ||
<testsuites> | ||
<testsuite name="LaravelUpsert Test Suite"> | ||
<directory suffix="Test.php">./tests</directory> | ||
</testsuite> | ||
</testsuites> | ||
<filter> | ||
<whitelist processUncoveredFilesFromWhitelist="true"> | ||
<directory suffix=".php">./src</directory> | ||
</whitelist> | ||
</filter> | ||
</phpunit> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<?php | ||
|
||
namespace Staudenmeir\LaravelUpsert\Connections; | ||
|
||
use Staudenmeir\LaravelUpsert\Query\Builder; | ||
|
||
trait CreatesQueryBuilder | ||
{ | ||
/** | ||
* Get a new query builder instance. | ||
* | ||
* @return \Illuminate\Database\Query\Builder | ||
*/ | ||
public function query() | ||
{ | ||
return new Builder($this); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<?php | ||
|
||
namespace Staudenmeir\LaravelUpsert\Connections; | ||
|
||
use Illuminate\Database\MySqlConnection as Base; | ||
|
||
class MySqlConnection extends Base | ||
{ | ||
use CreatesQueryBuilder; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<?php | ||
|
||
namespace Staudenmeir\LaravelUpsert\Connections; | ||
|
||
use Illuminate\Database\PostgresConnection as Base; | ||
|
||
class PostgresConnection extends Base | ||
{ | ||
use CreatesQueryBuilder; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<?php | ||
|
||
namespace Staudenmeir\LaravelUpsert\Connections; | ||
|
||
use Illuminate\Database\SQLiteConnection as Base; | ||
|
||
class SQLiteConnection extends Base | ||
{ | ||
use CreatesQueryBuilder; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<?php | ||
|
||
namespace Staudenmeir\LaravelUpsert\Connections; | ||
|
||
use Illuminate\Database\SqlServerConnection as Base; | ||
|
||
class SqlServerConnection extends Base | ||
{ | ||
use CreatesQueryBuilder; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
<?php | ||
|
||
namespace Staudenmeir\LaravelUpsert\Connectors; | ||
|
||
use Illuminate\Database\Connection; | ||
use Illuminate\Database\Connectors\ConnectionFactory as Base; | ||
use InvalidArgumentException; | ||
use Staudenmeir\LaravelUpsert\Connections\MySqlConnection; | ||
use Staudenmeir\LaravelUpsert\Connections\PostgresConnection; | ||
use Staudenmeir\LaravelUpsert\Connections\SQLiteConnection; | ||
use Staudenmeir\LaravelUpsert\Connections\SqlServerConnection; | ||
|
||
class ConnectionFactory extends Base | ||
{ | ||
/** | ||
* Create a new connection instance. | ||
* | ||
* @param string $driver | ||
* @param \PDO|\Closure $connection | ||
* @param string $database | ||
* @param string $prefix | ||
* @param array $config | ||
* @return \Illuminate\Database\Connection | ||
* | ||
* @throws \InvalidArgumentException | ||
*/ | ||
protected function createConnection($driver, $connection, $database, $prefix = '', array $config = []) | ||
{ | ||
if ($resolver = Connection::getResolver($driver)) { | ||
return $resolver($connection, $database, $prefix, $config); // @codeCoverageIgnore | ||
} | ||
|
||
switch ($driver) { | ||
case 'mysql': | ||
return new MySqlConnection($connection, $database, $prefix, $config); | ||
case 'pgsql': | ||
return new PostgresConnection($connection, $database, $prefix, $config); | ||
case 'sqlite': | ||
return new SQLiteConnection($connection, $database, $prefix, $config); | ||
case 'sqlsrv': | ||
return new SqlServerConnection($connection, $database, $prefix, $config); | ||
} | ||
|
||
throw new InvalidArgumentException("Unsupported driver [{$driver}]"); // @codeCoverageIgnore | ||
} | ||
} |
Oops, something went wrong.