Code Monkey home page Code Monkey logo

replaceable-model's Introduction

ReplaceableModel

Latest Version on Packagist Software License Total Downloads Travis CI

The default Eloquent model is great for most cases, but if you have a database table that has additional constraints you may run into race conditions where the standard update() call will fail. Imagine, for example, the following table structure:

id auto increment
user_id
widget_id
date

where you have a constraint with each user can only have one widget per day, so you have a unique constraint across user_id and date. Now in your interface you have a form that uses ajax calls to update the entries in this table, which may include removing items based on which items are selected. Because the form submits, say, an entire month's worth of widgets, you don't want to loop through and do individual inserts - you want to perform a single insert query. So you have something like the following in your php code:

Model::where('user_id',$user_id)->delete();
Model::insert($inserts);

This essentially performs the following under the hood:

delete from table where user_id = A;
insert into table (user_id, widget_id, date) values (A, B, C) ...

If you get stuck in a race condition, you might end up with the following:

delete from table where user_id = A; -- process #1
delete from table where user_id = A; -- process #2
insert into table (user_id, widget_id, date) values (A, B, C) ... -- process #1
insert into table (user_id, widget_id, date) values (A, B, C) ... -- process #2 - Exception!

The second insert will result in an exception. If the second query had an additional row than the first one, that insert is lost forever.

Before Laravel, I would normally have handled this type of situation with REPLACE or INSERT IGNORE commands. REPLACE will do a delete and insert based on any constraints in the query, and INSERT IGNORE will perform the insert but if there are any rows that cause constraint collisions those rows will not be updated. You would use REPLACE if you want the last query to overwrite any existing rows, and you would use INSERT IGNORE to only insert new rows.

Because this is a specific feature of MySQL, Laravel does not support it in Eloquent. The standard solution is to perform a raw query. This is ok, but it is kind of cumbersome to build this query every time with the bindings, etc, and I decided it would be helpful to create a trait for Eloquent that handles all of this for me and can be accessed in the same way that I would use insert().

Note that I'm NOT using the Builder class here. I'm directly extending the Model class and as such you won't be able to chain these functions like you might the regular insert() command. This is really just a macro to fix a problem that I had. I welcome any pull requests that solve additional problems you may have with this package.

The 'saving' and 'saved' events are fired for both of these commands.

Install

Via Composer

$ composer require jdavidbakr/replaceable-model

Usage

Apply the trait to your models to activate the ability to use replace and insertIgnore

class model extends Model {
	...	
	use \jdavidbakr\ReplaceableModel\ReplaceableModel
	...
}

Then build your insert array like you would for the insert() call and call one of the two functions:

$inserts = [...];
\App\Model::replace($inserts);
\App\Model::insertIgnore($inserts);

Contributing

Please see CONTRIBUTING and CONDUCT for details.

Security

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

Credits

License

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

replaceable-model's People

Contributors

jdavidbakr avatar kirill001 avatar michaeldyrynda avatar mseymour avatar

Watchers

 avatar

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.