Add transparent versioning to Laravel 5's Eloquent ORM

Overview

Eloquent Versioned

Adds transparent versioning support to Laravel 5.2's Eloquent ORM.

WARNING: This repository is currently super-duper experimental. I will gladly accept pull requests and issues, but you probably shouldn't use this in production, and the interfaces may change without notice (although major changes will bump the version).

It was also recently updated to bring global scopes in line with Laravel 5.2 so if you are not yet on 5.2, stick with release 0.0.7.

When using this trait (and with a table that includes the required fields), saving your model will actually create a new row instead, and increment the version number.

Using global scopes, old versions are ignored in the standard ORM operations (selects, updates, deletes) and relations (hasOne, hasMany, belongsTo, etc).

The package also provides some special methods to include old versions in queries (or only query old versions) which can be useful for showing a model's history, or the like.

Installation

To add via Composer:

composer require sbarre/eloquent-versioned --no-dev

Use the --no-dev flag to avoid pulling down all the testing dependencies (like the entire Laravel framework).

Migrations

Versioned models require that your database table contain 3 fields to handle the versioning.

If you are creating a new table, or if you are changing an existing table, include the following lines in the up() method of the migration:

$table->integer('model_id')->unsigned()->default(1);
$table->integer('version')->unsigned()->default(1);
$table->integer('is_current_version')->unsigned()->default(1);
$table->index('is_current_version');
$table->index('model_id');
$table->index('version');

If your migration was altering an existing table, you should include these lines in the down() method of your migration:

$table->dropColumn(['model_id','version','is_current_version']);
$table->dropIndex(['model_id','version','is_current_version']);

Caveats

If you change the constants in EloquentVersioned\VersionedBuilder to rename the columns, remember to change them in your migrations as well.

Usage

In your Eloquent model class, start by adding the use statement for the Trait:

use EloquentVersioned\Traits\Versioned;

When the trait boots it will apply the proper scope, and provides overrides on various Eloquent methods to support versioned records.

Once the trait is applied, you use your models as usual, with the standard queries behaving as usual.

$project = Project::create([
    'name' => 'Project Name',
    'description' => 'Project description goes here'
])->fresh();

print_r($project->toArray());

This would then output (for example):

Array
(
    [id] => 1
    [version] => 1
    [name] => Project Name
    [description] => Project description goes here
    [created_at] => 2015-05-24 17:16:05
    [updated_at] => 2015-05-24 17:16:05
)

The actual database row looks like this:

Array
(
    [id] => 1
    [model_id] => 1
    [version] => 1
    [is_current_version] => 1
    [name] => Updated project Name
    [description] => Project description goes here
    [created_at] => 2015-05-24 17:16:05
    [updated_at] => 2015-05-24 17:16:05
)

Then if you change the model and save:

$project->name = 'Updated project name';
$project->save();

print_r($project->toArray());

This would then output:

Array
(
    [id] => 1
    [version] => 2
    [name] => Updated project Name
    [description] => Project description goes here
    [created_at] => 2015-05-24 17:16:05
    [updated_at] => 2015-05-24 17:16:45
)

The model mutates the model_id column into id, and hides some of the version-specific columns. In reality this is actually the same database row that now looks like this:

Array
(
    [id] => 1
    [model_id] => 1
    [version] => 2
    [is_current_version] => 1
    [name] => Updated project Name
    [description] => Project description goes here
    [created_at] => 2015-05-24 17:16:05
    [updated_at] => 2015-05-24 17:16:45
)

While a new row is inserted to save our previous version, which now looks like this:

Array
(
    [id] => 2
    [model_id] => 1
    [version] => 1
    [is_current_version] => 0
    [name] => Project Name
    [description] => Project description goes here
    [created_at] => 2015-05-24 17:16:05
    [updated_at] => 2015-05-24 17:16:05
)

So the is_current_version property is what the global scope is applied against, limiting all select queries to only records where is_current_version = 1.

Calling save() on a model replicates the original version into a new row (with is_current_version = 0), then increments the version_id property on our current model, changes the appropriate timestamps, and saves it.

If you are making a very minor change to a model and you don't want to create a new version, you can call saveMinor() instead.

$project->saveMinor(); // doesn't create a new version

Methods for dealing with old versions

If you want to retrieve a list of all versions of a model (or include old versions in a bigger query):

$projectVersions = Project::withOldVersions()->find(1);

If run after our example above, this would return an array with 2 models.

You can also retrieve a list of only old models by using:

$oldVersions = Project::onlyOldVersions()->find(1);

Otherwise, the rest of Eloquent's ORM operations should work as usual, including the out-of-the-box relations.

Methods for moving through a model's versions

If you want to navigate through all of model's versions, in a linked-list manner:

$current = Project::find(1);

$previous = $current->getPreviousModel();
$next = $previous->getNextModel();

// $next == $current

If you are at the most recent version, getNextModel() will return null and likewise if you are at the oldest version, getPreviousModel() will return null.

Support & Roadmap

As indicated at the top, this package is still very experimental and is under active development. The current roadmap includes test coverage and more extensive real-world testing, so pull requests and issues are always welcome!

Comments
  • Add an additional 'AppendedVersioning' trait

    Add an additional 'AppendedVersioning' trait

    The new trait changes the way versions are saved so that instead of creating a new record with a new primary key, the newly created record is actually the old, pre-edited record. The changes are then saved to the existing record to maintain the primary key.

    This is in reference to #14 and #15 . It completely changes the way that versioning happens but should do so in a transparent way for the user. All existing tests pass for this new trait.

    opened by EspadaV8 8
  • function getNextModelId() function will cause issues

    function getNextModelId() function will cause issues

    so,
    current version ( 0.0.7 )
    in the Trait ~line 183 ( https://github.com/sbarre/eloquent-versioned/blob/5cccfa9f29a230945697fd290a66c197bb659e7f/src/Traits/Versioned.php#L255 )

    you are getting the Max of the ID column.
    What happens if a record is inserted elsewhere between the call and the return of this function (and final saving of this model)?
    The model_id will reference the wrong record.
    Or, if the latest model (eg id: 177, previous model being id: 176) has been deleted at some point, return will be 177, but MySQL autoinc will set the model id:178

    Would it not be better to save first, then self-reference the new model & update? at the expense of an extra DB query.. I would love to set up a pull-request, but I have no idea how!

    opened by Towerful 6
  • Implement a previous/next column for versioned models

    Implement a previous/next column for versioned models

    This adds a next_id and previous_id column to versioned models that will store a link between saves. This should allow easier walking of the version history.

    This is mostly a POC for the saving of the next/previous ID columns and to get any feedback about how it's implemented. There isn't any way to actually get the next/previous versions just yet.

    opened by EspadaV8 4
  • Just want to give some feedback..

    Just want to give some feedback..

    EDIT Just wanted to say after looking at it closely I realized this would cause problems because the model_id would have to be updated to reference the newest version of the model (i think)... So my idea here won't work I don't think. I'll need to think of a better way to handle my particular use case.

    I think this package would be really fantastic with some tweaks to the implementation.

    The decision to update the current record and make a new record for the old version is strange to me, as it seems like it would make alot more sense to create a new record for the newer version, and leave the old version as it is.

    Maybe I'm wrong but here is why it makes sense in my use case:

    I am creating agreements, and so I want to keep old versions of agreements. When someone agrees to an agreement I want to be able to associate that agreement to the user. When I make the new version of the agreement I don't want the user to be associated with the new version.. I want them to be associated with the version they actually agreed to.

    In the current package implimentation, that means I would have to store the version and the model_id as a composite key foreign key reference to the model I want to associate.. and eloquent doesn't really support that. It would be much nicer if I could simply associate it with the ID of the model that it was originally saved as, and then if I want to reference the newer version I can reference the model_id and the scope will automatically limit that to the current version.

    I think this would make the current package more flexible without losing any functionality. Then again I probably haven't given this as much thought as I need to. I'm going to try and fork this package and take a look.

    question 
    opened by isaackearl 3
  • Support appended versioning

    Support appended versioning

    This follows on from #14

    In that issue it shows that updating a versioned model could possibly require a number of updates to happen to tables that have foreign key constraints upon it.

    To get around this I was wondering if it would be possible to use what I've called appended history (if there's a real term for it please let me know).

    Using the examples from #14

    Users
    
    +----+------------------+----------+---------+
    | id | email            | model_id | version |
    +----+------------------+----------+---------+
    |  1 | [email protected] |        1 |       1 |
    +----+------------------+----------+---------+
    
    Posts
    +----+-------------------+---------+----------+---------+
    | id | title             | user_id | model_id | version |
    +----+-------------------+---------+----------+---------+
    |  1 | Some awesome post |       1 |        1 |       1 |
    +----+-------------------+---------+----------+---------+
    
    Comments
    +----+----------------+---------+---------+----------+---------+
    | id | comment        | post_id | user_id | model_id | version |
    +----+----------------+---------+---------+----------+---------+
    |  1 | Blah blah blah |       1 |       1 |        1 |       1 |
    +----+----------------+---------+---------+----------+---------+
    

    Updating the posts table would, instead of creating a new record for the updated title, would create a new row for the existing version of the post

    Users
    
    +----+------------------+----------+---------+
    | id | email            | model_id | version |
    +----+------------------+----------+---------+
    |  1 | [email protected] |        1 |       1 |
    +----+------------------+----------+---------+
    
    Posts
    +----+-------------------+---------+----------+---------+
    | id | title             | user_id | model_id | version |
    +----+-------------------+---------+----------+---------+
    |  1 | Updated awesome   |       1 |        1 |       2 |
    |  2 | Some awesome post |       1 |        1 |       1 |
    +----+-------------------+---------+----------+---------+
    
    Comments
    +----+----------------+---------+---------+----------+---------+
    | id | comment        | post_id | user_id | model_id | version |
    +----+----------------+---------+---------+----------+---------+
    |  1 | Blah blah blah |       1 |       1 |        1 |       1 |
    +----+----------------+---------+---------+----------+---------+
    

    By doing things this way the primary keys for a record never change and instead the old version gets added to the bottom of the table.

    If the user wanted to update their email address, again, only 1 row would need to be added

    Users
    
    +----+------------------+----------+---------+
    | id | email            | model_id | version |
    +----+------------------+----------+---------+
    |  1 |  [email protected] |        1 |       2 |
    |  2 | [email protected] |        1 |       1 |
    +----+------------------+----------+---------+
    
    Posts
    +----+-------------------+---------+----------+---------+
    | id | title             | user_id | model_id | version |
    +----+-------------------+---------+----------+---------+
    |  1 | Updated awesome   |       1 |        1 |       2 |
    |  2 | Some awesome post |       1 |        1 |       1 |
    +----+-------------------+---------+----------+---------+
    
    Comments
    +----+----------------+---------+---------+----------+---------+
    | id | comment        | post_id | user_id | model_id | version |
    +----+----------------+---------+---------+----------+---------+
    |  1 | Blah blah blah |       1 |       1 |        1 |       1 |
    +----+----------------+---------+---------+----------+---------+
    

    Again, updating the users table requires just the 1 insert without needing to update any of the tables that have a foreign key on it.

    Can anyone see any downsides to doing versioning this way?

    opened by EspadaV8 2
  • Provide a way to diff between to entity versions

    Provide a way to diff between to entity versions

    This could possibly be another package, but it would be very useful if there was a way to return all fields that have been changed between 2 different versions of an entity, probably as a service, but also being able to call it on an existing model could be useful e.g.

    $post = Post::last();
    $changes = $post->changesSinceVersion(1);
    dd($changes);
    

    would give something like

    array [
        'title' => 'Title for the first version of the post',
        'body' => 'Some text with a smelling mistake that was corrected in a later version',
    ]
    
    enhancement 
    opened by EspadaV8 2
  • Removing the requirement to guess next model ID

    Removing the requirement to guess next model ID

    By using an extra SQL query to save then update, the versioned model_id can be reliably resolved. This removes the potential incorrect IDs used caused by a race condition of multiple concurrent saves, as well as incorrect IDs being guessed by deleting records off the end of the table.

    p.s. my first PR. Hopefully everything is in order. Feedback welcome :)

    opened by Towerful 1
  • Provide a way to diff between to entity versions

    Provide a way to diff between to entity versions

    This is a WIP towards closing #4

    Currently there is a very simple class that takes 2 models and returns an array of any changed attributes between them. It doesn't check any versions in between. Example of returned array

    array:1 [
      "name" => array:4 [
        "left" => "Widget"
        "right" => "Updated Widget"
        0 => "Widget"
        1 => "Updated Widget"
      ]
    ]
    

    Currently a new instance of the VersionDiffer needs to be created, but this can probably come under a Facade or possibly just be changed into a static method.

    Fields related to the versioning and timestamps are ignored (but this could be overridden with a 3rd parameter if you think it's needed public function diff(Model $left, Model $right, array $ignore = [])).

    If the 2 models passed in aren't of the same type then an exception is thrown (I can't think of a reason that we would want to allow diffing between 2 different entities).

    opened by EspadaV8 1
  • Reformat src and text using php-cs-fixer and phpstorm

    Reformat src and text using php-cs-fixer and phpstorm

    I've just run 'php-cs-fixer fix --level=psr2' on the src and test folders and then also used PHPStorms built in reformatting tool to get all the code into PSR 2 format with ordered includes and shortened line lengths.

    opened by EspadaV8 1
  • this commit fixes #22

    this commit fixes #22

    I modified the README as well because the examples said to use find (which always limits to 1 result)...

    Also to fix the issue I realized the update query was always grabbing the model_id column for the where clause. This didn't work because the value in the database was always 1 and the model_id on the object would already be updated to be the same as the new id.

    In order to fix this I removed the getKeyName override in the Versioned Trait.

    Doing this fixed most issues however I noticed that it broke the withOldVersions scope that is included in the trait. I fixed this by updating the reference to the QualifiedKeyName by using the qualifiedModelIdColumn. I've tested the various methods in the package and this seems to fix everything...

    I didn't see the purpose of using the isVersioned check on the new override, since any object using this trait we would assume is being versioned. Right? is there some reason that should be included?

    opened by isaackearl 0
  • Add travis.yml for automated testing

    Add travis.yml for automated testing

    Run PHPUnit on travis, e.g.

    https://travis-ci.org/EspadaV8/eloquent-versioned

    Testing on 5.5, 5.6, 7.0 and HHVM. 7.0 and HHVM have been set to allow failures since they're not set as supported versions just yet.

    opened by EspadaV8 0
  • How to check if there are older versions?

    How to check if there are older versions?

    Hi, I'd like to thank the contributors for this amazing project. It literally has saved me from creating a DB versioning system from scratch, so I'm really grateful.

    After checking the readme, I have a question. I'd like to have something in the result of a query that indicates if there are more than one version of such row. I know there is a field named 'is_current_version' but such field is not retrieved when querying the eloquent model.

    For instance, if I had the model Laptop(id, vendor, model) and I invoke Laptop::all(), I'll get a collection of objects with the attributes id, vendor, and model, but nothing else. What's the proper way of retrieving 'is_current_version' as part or the returned fields?

    Thanks you.

    ------ Edit: ----- I just checked and version field is returned in Eloquent queries. Checking if version is >1 is enough, so feel free to close this question and accept my apologies.

    opened by arrabal 1
  • Problems with model_id always defaulting to 1 when being persisted.

    Problems with model_id always defaulting to 1 when being persisted.

    Hello,

    I experimentally started using the package last night and was attempting to proof of concept what I wanted to accomplish by using artisan tinker... unfortunately I didn't get very far because I realized whenever I create a new model it persists model_id 1 to the database the first time it is persisted.

    example using a simple model in a table that has some rows already: TestModel::create(['name' => 'test', 'content' => 'ha ha']); will immediately output this as it gets created:

    => TestModel {
         id: 14,
         name: "test",
         content: "ha ha",
         model_id: 14,
         is_current_version: 1,
         created_at: "2016-05-23 22:35:04",
         updated_at: "2016-05-23 22:35:04",
         deleted_at: null,
       }
    

    So everything looks good right? well the database row that actually got inserted looksl like this: id: 14, name: test, content: ha ha, model_id: 1, version: 1, is_current_version: 1 etc

    as you can see it just inserts 1 as the model_id. I mean this makes sense to me since you wouldn't know the ID of the model until after it is persisted... so it would require a second save to update the model_id...

    It works the same way when I new up a model and save it the traditional way. I'm wondering is this supposed to be how this behaves? I'm using php 7, and mariadb 10. I'm going to take a look at the code and if I can figure out a fix I'll attempt a pull request.

    Please let me know if I am just trying to use it wrong or if I missed some part of setup (I looked over the readme several times to check).

    Thanks!

    opened by isaackearl 3
  • Problems with foreign keys

    Problems with foreign keys

    So, after lots of playing I've just realised that any versioned model can't actually be used with foreign keys. I shall try to explain with a few simple tables

    Users
    
    +----+------------------+----------+---------+
    | id | email            | model_id | version |
    +----+------------------+----------+---------+
    |  1 | [email protected] |        1 |       1 |
    +----+------------------+----------+---------+
    
    Posts
    +----+-------------------+---------+----------+---------+
    | id | title             | user_id | model_id | version |
    +----+-------------------+---------+----------+---------+
    |  1 | Some awesome post |       1 |        1 |       1 |
    +----+-------------------+---------+----------+---------+
    
    Comments
    +----+----------------+---------+---------+----------+---------+
    | id | comment        | post_id | user_id | model_id | version |
    +----+----------------+---------+---------+----------+---------+
    |  1 | Blah blah blah |       1 |       1 |        1 |       1 |
    +----+----------------+---------+---------+----------+---------+
    

    So, this is a very simple example. A user can have a number of posts and comments. Now, if a post title gets updated we would have something like this

    Users
    
    +----+------------------+----------+---------+
    | id | email            | model_id | version |
    +----+------------------+----------+---------+
    |  1 | [email protected] |        1 |       1 |
    +----+------------------+----------+---------+
    
    Posts
    +----+-------------------+---------+----------+---------+
    | id | title             | user_id | model_id | version |
    +----+-------------------+---------+----------+---------+
    |  1 | Some awesome post |       1 |        1 |       1 |
    |  2 | Updated awesome   |       1 |        1 |       2 |
    +----+-------------------+---------+----------+---------+
    
    Comments
    +----+----------------+---------+---------+----------+---------+
    | id | comment        | post_id | user_id | model_id | version |
    +----+----------------+---------+---------+----------+---------+
    |  1 | Blah blah blah |       1 |       1 |        1 |       1 |
    +----+----------------+---------+---------+----------+---------+
    

    Here we now have a comment that's pointing to the old post_id of 1. We can't have foreign keys pointing to the model_id because foreign keys need to point to a primary or at least a unique column and model_id isn't either. So what we could do is cascade the update down to the comments table too

    Users
    
    +----+------------------+----------+---------+
    | id | email            | model_id | version |
    +----+------------------+----------+---------+
    |  1 | [email protected] |        1 |       1 |
    +----+------------------+----------+---------+
    
    Posts
    +----+-------------------+---------+----------+---------+
    | id | title             | user_id | model_id | version |
    +----+-------------------+---------+----------+---------+
    |  1 | Some awesome post |       1 |        1 |       1 |
    |  2 | Updated awesome   |       1 |        1 |       2 |
    +----+-------------------+---------+----------+---------+
    
    Comments
    +----+----------------+---------+---------+----------+---------+
    | id | comment        | post_id | user_id | model_id | version |
    +----+----------------+---------+---------+----------+---------+
    |  1 | Blah blah blah |       1 |       1 |        1 |       1 |
    |  2 | Blah blah blah |       2 |       1 |        1 |       2 |
    +----+----------------+---------+---------+----------+---------+
    

    This is a small case, but if the user wishes to update their email address we have a larger issue

    Users
    
    +----+------------------+----------+---------+
    | id | email            | model_id | version |
    +----+------------------+----------+---------+
    |  1 | [email protected] |        1 |       1 |
    |  2 |  [email protected] |        1 |       2 |
    +----+------------------+----------+---------+
    
    Posts
    +----+-------------------+---------+----------+---------+
    | id | title             | user_id | model_id | version |
    +----+-------------------+---------+----------+---------+
    |  1 | Some awesome post |       1 |        1 |       1 |
    |  2 | Updated awesome   |       1 |        1 |       2 |
    |  3 | Updated awesome   |       2 |        1 |       3 |
    +----+-------------------+---------+----------+---------+
    
    Comments
    +----+----------------+---------+---------+----------+---------+
    | id | comment        | post_id | user_id | model_id | version |
    +----+----------------+---------+---------+----------+---------+
    |  1 | Blah blah blah |       1 |       1 |        1 |       1 |
    |  2 | Blah blah blah |       2 |       1 |        1 |       2 |
    |  3 | Blah blah blah |       2 |       2 |        1 |       3 |
    |  4 | Blah blah blah |       3 |       2 |        1 |       3 |
    +----+----------------+---------+---------+----------+---------+
    

    Here we needed to create a new version of the user, a new version of the post and finally 2 new version of the comment (this could possibly be optimised to only be 1 version but would be much harder to implement).

    This is the case with just 3 tables, if there were more (e.g. comment/post up/down voting, user profiles, etc.) then the number of updates would ended up being massive, just because a user changed their email address.

    Has anyone else come across this or thought of a better solution?

    opened by EspadaV8 0
  • Readme for dropping columns/indexes

    Readme for dropping columns/indexes

    Rather than create a PR for this I just wanted to check to see if the dropColumn/dropIndex down migrations work for anyone else. For me it tried to concatenate the index names together to give something like users_model_id_version_is_current_version_index. Dropping the columns before the indexes also gives an error about it not existing. I think it needs to be changed to something like

    $table->dropIndex($table->getTable() . 'model_id_index');
    $table->dropIndex($table->getTable() . '_version_index');
    $table->dropIndex($table->getTable() . '_is_current_version_index');
    $table->dropColumn('model_id');
    $table->dropColumn('version');
    $table->dropColumn('is_current_version');
    
    opened by EspadaV8 1
  • Allow a model to set 'minor' attributes that won't create a new version

    Allow a model to set 'minor' attributes that won't create a new version

    This adds a new property to models that allows them to give an array of attributes that should be counted as 'minor'. If a save is requested, the model exists and all the changed attributes are in the $minorAttributes array then only a minorSave will happen.

    Fixes #2

    opened by EspadaV8 0
  • Support non-auto-incrementing models

    Support non-auto-incrementing models

    This is a pull request for #8

    There's a new model 'Foo' that uses UUIDs instead of an auto-incrementing integer column as its primary key. The few changes that need to be made a to make sure that the Laravel model events that a model has set up get fired when being created.

    The addition of orchestra/testbench is to help with that (without it there's no dispatcher for the models). In the NonIncrementingVersionedTest file, the events need to be reset every for every test due to what seems like a bug in laravel/framework#1181.

    The final change in Versioned is due to the testing and needing to be able to set a fixed model_id when creating a model that uses UUIDs. If one has been passed in when creating then it doesn't attempt to get a new model_id.

    opened by EspadaV8 0
Releases(0.1.2)
  • 0.1.2(Feb 16, 2016)

    This new release introduces a few new changes:

    • Laravel 5.2 compatibility
    • Two new methods, getNextModel() and getPreviousModel() allow you to walk the list of versions for a given model (thanks Andrew!)
    • better model_id determination to avoid potential race conditions (thanks Andrew!)
    Source code(tar.gz)
    Source code(zip)
  • 0.0.7(May 25, 2015)

Owner
Seb Barre
Pragmatic technology advocate and enthusiast.
Seb Barre
Curso Laravel Eloquent ORM

Curso Laravel Eloquent ORM

EspecializaTi 4 Nov 18, 2022
Laravel package for creating Word documents with Eloquent ORM dependencies.

Laravel Eloquent Word This package provides an elegant way to generate Word documents with Eloquent Models. Uses PHPOffice/PHPWord package to generate

Marvin Quezon 6 Aug 5, 2022
cybercog 996 Dec 28, 2022
Add eloquent model events fired after a transaction is committed or rolled back

Laravel Transactional Model Events Add transactional events to your eloquent models. Will automatically detect changes in your models within a transac

Mark van Duijker 62 Dec 22, 2022
Use Laravel's built-in ORM classes to query cloud resources with Steampipe.

Laravel Steampipe Use Laravel's built-in ORM classes to query cloud resources with Steampipe, an open source CLI to instantly query cloud APIs using S

Renoki Co. 13 Nov 8, 2022
A Laravel 5.1 ORM example with Nerds as users.

laravel-nerds A Laravel 5.1 ORM example with Nerds as users. App Features Show all Nerds Add a Nerd Edit a Nerd Delete a Nerd Keeps Nerd's Name Keeps

Jeremy Kenedy 6 Aug 20, 2022
Laravel Breadcrumbs - An easy way to add breadcrumbs to your @Laravel app.

Introduction Breadcrumbs display a list of links indicating the position of the current page in the whole site hierarchy. For example, breadcrumbs lik

Alexandr Chernyaev 269 Dec 21, 2022
Laravel 2-Step Verification is a package to add 2-Step user authentication to any Laravel project easily.

Laravel 2-Step verification is a package to add 2-Step user authentication to any Laravel project easily. It is configurable and customizable. It uses notifications to send the user an email with a 4-digit verification code. Laravel 2-Step Authentication Verification for Laravel. Can be used in out the box with Laravel's authentication scaffolding or integrated into other projects.

Jeremy Kenedy 204 Dec 23, 2022
Easily add a full Laravel blog (with built in admin panel and public views) to your laravel project with this simple package.

Webdevetc BlogEtc - Complete Laravel Blog Package Quickly add a blog with admin panel to your existing Laravel project. It has everything included (ro

WebDevEtc. 227 Dec 25, 2022
Laravel-tagmanager - An easier way to add Google Tag Manager to your Laravel application.

Laravel TagManager An easier way to add Google Tag Manager to your Laravel application. Including recommended GTM events support. Requirements Laravel

Label84 16 Nov 23, 2022
Laravel comments - This package enables to easily associate comments to any Eloquent model in your Laravel application

Laravel comments - This package enables to easily associate comments to any Eloquent model in your Laravel application

Rubik 4 May 12, 2022
This Laravel package merges staudenmeir/eloquent-param-limit-fix and staudenmeir/laravel-adjacency-list to allow them being used in the same model.

This Laravel package merges staudenmeir/eloquent-param-limit-fix and staudenmeir/laravel-adjacency-list to allow them being used in the same model.

Jonas Staudenmeir 5 Jan 6, 2023
Add tags and taggable behaviour to your Laravel app

Add tags and taggable behaviour to a Laravel app This package offers taggable behaviour for your models. After the package is installed the only thing

Spatie 1.4k Dec 29, 2022
This package lets you add uuid as primary key in your laravel applications

laravel-model-uuid A Laravel package to add uuid to models Table of contents Installation Configuration Model Uuid Publishing files / configurations I

salman zafar 10 May 17, 2022
Add variables to the payload of all jobs in a Laravel app

Inject extra info to the payloads of all jobs in a Laravel app This package makes it easy to inject things in every job. Imagine that you want to have

Spatie 62 Dec 9, 2022
A Laravel package helps you add a complete real-time messaging system to your new / existing application with only one command.

A Laravel package helps you add a complete real-time messaging system to your new / existing application with only one command.

Munaf Aqeel Mahdi 1.7k Jan 5, 2023
Add Server-Timing header information from within your Laravel apps.

Laravel Server Timings Add Server-Timing header information from within your Laravel apps. Installation You can install the package via composer: comp

Beyond Code 498 Dec 15, 2022
`dd` is a helper method in Laravel. This package will add the `dd` to your application.

dd dd is a helper method in Laravel. This package will add the dd to your application. Install Run composer require larapack/dd 1.* For Laravel Larave

Larapack 109 Dec 26, 2022
Add Webhooks to your Laravel app, arrr

# Captain Hook ## Add Webhooks to your Laravel app, arrr Implement multiple webhooks into your Laravel app using the Laravel Event system. A webhook i

Marcel Pociot 334 Dec 12, 2022