Coder Social home page Coder Social logo

versionable's Introduction

Versionable

Laravel Model versioning made easy

image image image codecov.io Scrutinizer Code Quality Build Status

Keep track of all your model changes and revert to previous versions of it.

// Restore to the previous change
$content->previousVersion()->revert();

// Get model from a version
$oldModel = Version::find(100)->getModel();

You can install via composer:

composer require mpociot/versionable

Run the migrations.

php artisan migrate --path=vendor/mpociot/versionable/src/migrations

Alternatively, publish the migrations.

php artisan vendor:publish --provider="Mpociot\Versionable\Providers\ServiceProvider" --tag="migrations"

Then customize and run them.

php artisan migrate

Let the Models you want to set under version control use the VersionableTrait.

class Content extends Model {
	
	use Mpociot\Versionable\VersionableTrait;
	
}

That's it!

Every time you update your model, a new version containing the previous attributes will be stored in your database.

All timestamps and the optional soft-delete timestamp will be ignored.

Versionable creates a version on update() of the updated model. So, if you're installing this on an already existing application, you may want to create a version of the current model:

    $model->createInitialVersion();

If no version exists, this will create the initial version.

If you want to do this for all instances of a model:

    Model::initializeVersions();

Sometimes you don't want to create a version every time an attribute on your model changes. For example your User model might have a last_login_at attribute. I'm pretty sure you don't want to create a new version of your User model every time that user logs in.

To exclude specific attributes from versioning, add a new array property to your model named dontVersionFields.

class User extends Model {
	
	use Mpociot\Versionable\VersionableTrait;
	
	/**
	 * @var array
	 */
	protected $dontVersionFields = [ 'last_login_at' ];

}

There are times you might want to include hidden fields in the version data. You might have hidden the fields with the visible or hidden properties in your model.

You can have those fields that are typically hidden in the rest of your project saved in the version data by adding them to the versionedHiddenFields property of the versionable model.

class User {

    use VersionableTrait;

    // Typically hidden fields
    protected $hidden = ['email', 'password'];

    // Save these hidden fields
    protected $versionedHiddenFields = ['email', 'password'];

}

You can control the maximum number of stored versions per model. By default, there will be no limit and all versions will be saved. Depending on your application, this could lead to a lot of versions, so you might want to limit the amount of stored versions.

You can do this by setting a $keepOldVersions property on your versionable models:

class User {

    use VersionableTrait;

    // Keep the last 10 versions.
    protected $keepOldVersions = 10;

}

To retrieve all stored versions use the versions attribute on your model.

This attribute can also be accessed like any other Laravel relation, since it is a MorphMany relation.

$model->versions;

If you want to know, what exactly has changed between two versions, use the version model's diff method.

The diff method takes a version model as an argument. This defines the version to diff against. If no version is provided, it will use the current version.

/**
 * Create a diff against the current version
 */
$diff = $page->previousVersion()->diff();

/**
 * Create a diff against a specific version
 */
$diff = $page->currentVersion()->diff( $version );

The result will be an associative array containing the attribute name as the key, and the different attribute value.

Saving versions is pretty cool, but the real benefit will be the ability to revert to a specific version.

There are multiple ways to do this.

Revert to the previous version

You can easily revert to the version prior to the currently active version using:

$content->previousVersion()->revert();

Revert to a specific version ID

You can also revert to a specific version ID of a model using:

$revertedModel = Version::find( $version_id )->revert();

In some situations you might want to disable versioning a specific model completely for the current request.

You can do this by using the disableVersioning and enableVersioning methods on the versionable model.

$user = User::find(1);
$user->disableVersioning();

// This will not create a new version entry.
$user->update([
    'some_attribute' => 'changed value'
]);

Some times we want to have models versions in differents tables. By default versions are stored in the table 'versions', defined in Mpociot\Versionable\Version::$table.

To use a different table to store version for some model we have to change the table name. To do so, create a model that extends Mpociot\Versionable\Version and set the $table property to another table name.

class MyModelVersion extends Version
{
    $table = 'mymodel_versions';
    // ...
}

In the model that you want it use this specific versions table, use the VersionableTrait Trait and add the property $versionClass with value the specific version model.

class MyModel extends Eloquent
{
    use VersionableTrait ;
    protected $versionClass = MyModelVersion::class ;
    // ...
}

And do not forget to create a migration for this versions table, exactly as the default versions table.

Versionable is free software distributed under the terms of the MIT license.

versionable's People

Contributors

adamjgriffith avatar coffe4u avatar coolgoose avatar cyrille37 avatar derhofbauer avatar dubcanada avatar emilv avatar fedeisas avatar geoffbeaumont avatar iateadonut avatar laravel-shift avatar marcelweidum avatar maximal avatar merlinblack avatar michaelachrisco avatar mpociot avatar nhowell avatar nonoesp avatar oschettler avatar pheeque avatar roxayl avatar rumeau avatar stojankukrika avatar williamoliveira avatar yellowwilson avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

versionable's Issues

Upgrade from 3.2 to 3.3 - Migration error

Hi,
I recently upgrade my package to the newest version 3.3 from 3.2.

Since this upgrade, I can't migrate anything. Everytime, this package wants to run a migration. I think it's depends on the changes in this file: 3.2.0...3.3.0#diff-a7505c5dff7a02c1c00ae5db2cf5a005R30

...
 Illuminate\Database\Migrations\Migrator::runUp("/var/www/laravel/vendor/mpociot/versionable/src/Mpociot/Versionable/Providers/../../../migrations/2014_09_27_212641_create_versions_table.php")
      /var/www/laravel/vendor/laravel/framework/src/Illuminate/Database/Migrations/Migrator.php:165
....

SQLSTATE[42S01]: Base table or view already exists: 1050 Table 'versions' already exists (SQL: create table `versions` (`version_id` int unsigned not null auto_increment primary key, `versionable_id` varchar(191) not null, `versionable_type` varchar(191) not null, `user_id` varchar(191) null, `model_data` blob not null, `reason` varchar(100) null, `created_at` timestamp null, `updated_at` timestamp null) default character set utf8mb4 collate 'utf8mb4_unicode_ci')

Issues with sql server

Trying to save to a model breaks after adding VersionTrait. It seems to not like the datatype for model possibly here is an error I get:

Illuminate\Database\QueryException: SQLSTATE[42000]: [Microsoft][ODBC Driver 13 for SQL Server][SQL Server]Implicit conversion from data type nvarchar to varbinary(max) is not allowed. Use the CONVERT function to run this query. (SQL: insert into [versions] ([versionable_id], [versionable_type], [user_id], [model_data], [updated_at], [created_at]) values (1, App\Database\Models\Operational\Runbook, 133, a:11:{s:2:"id";i:1;s:7:"user_id";i:133;s:4:"name";s:37:"How to be LALAs";s:4:"body";s:10:"This isBAD";s:8:"category";i:3;s:11:"subcategory";i:3;s:10:"attachment";i:1245;s:9:"published";O:13:"Carbon\Carbon":3:{s:4:"date";s:26:"2019-10-07 14:33:32.378148";s:13:"timezone_type";i:3;s:8:"timezone";s:3:"UTC";}s:8:"archived";i:0;s:10:"created_at";s:23:"2019-09-26 21:35:22.373";s:10:"updated_at";s:23:"2019-10-07 14:33:32.378";}, 2019-10-07 14:33:32.387, 2019-10-07 14:33:32.387)) in file /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php on line 664

Caused by
Doctrine\DBAL\Driver\PDOException: SQLSTATE[42000]: [Microsoft][ODBC Driver 13 for SQL Server][SQL Server]Implicit conversion from data type nvarchar to varbinary(max) is not allowed. Use the CONVERT function to run this query. in file /var/www/html/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php on line 119

Caused by
PDOException: SQLSTATE[42000]: [Microsoft][ODBC Driver 13 for SQL Server][SQL Server]Implicit conversion from data type nvarchar to varbinary(max) is not allowed. Use the CONVERT function to run this query. in file /var/www/html/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php on line 117

Problem with multi connections

I have 2+x (client databases) db connections in my project.
I want to version only some of my models, but it always uses the default db connection.
Please change this, so that version uses the model db connection by default, where the "version" table is.

create versions without updating the current model?

hi,
Can one use versionable to create versions without updating the current model?
My thoughts are for saving drafts without affecting the currently approved/ published model.
If so, any hints on the procedure? (no code required).
thanks.

Morph Map ignored

I have a model that is set at 'report' in Morph Map. When adding the VersionableTrait to this model, versioning breaks. On save, it saves the full model class path which is incorrect.

This means that when loading versions there are none mapped causing it to break entirely. The only way to resolve it for me is to remove it from the morph map which is a deal breaker for my implementation at this time.

why diff() method return current values

Hi ,
I used $page->previousVersion()->diff() to show previous version of contents but it shows current contents so what is the correct way to show previous model data?

Thanks

disableVersioning() is not working

I'm implementing a method to go back to previous version of a model, and like we know, do that actually create a new version of the model.
So, in order to avoid that, I'm doing this:

        $block = Block::findOrFail($block_id);
        if ($block->previousVersion()) {
            $block->disableVersioning()->previousVersion()->revert();
            return response()->json(
                [
                    'message' => 'Version reverted!'
                ],
                200
            );
        }

And still I'm getting a new version when revert.

Setting the $reason

Hi,
Great package working out-of-the-box with little effort.

Yet, I can't figure out how and where one can set the $reason value. I tried in the model, and in the controller, and none is saved. The table shows the reason the field is always null.

Question: because it's not in the documentation, where and how to set the $reason value?

Thanks.

Versions not changing when I try to update the model

I tried to update my model and the version remains the same when I try to call the previousVersion() it returns me null and when I call the versions property it always return the same version.

Sorry if I misuse your plugin or boilerplate. I am just new in using your boilerplate or plugin. Or could you give me some real examples on how to use it. I gotta be honest that I didn't understand the examples in the documentation.

Various actions don't respect dontVersionFields

There are a few functions that do not respect dontVersionFields.

For example, diff() and revert(). Diffing with a previous version after saving shows that the fields that shouldn't be versioned have changed when they either shouldn't be serialized at all or unset before the diff. Reverting overwrites the values of the fields specified in dontVersionFields.

Looking at the Version model, the issue is there. unset is hardcoded for the date fields which may not be desirable in all cases. Instead, I would propose that dontVersionFields is respected in these functions.

The default functionality in my mind would be to exclude timestamps, however, if a user specifies dontVersionFields then it should use the fields in that array instead of assuming timestamps only. This would give more flexibility as well and then the array could be used to unset any values that shouldn't be versioned.

Another suggestion taking a page from Eloquent, is it would be nice to have a version and dontVersion attribute that could be set. Where you could do the inverse should you only want to version a specific field.

[feature] Create version between others and have a ripple effect

I have a usecase where if for any reason a version isn't created in the laravel tool, but is registred somewhere else (excel spreadsheet :D) , I need my users to be able to create a version between other prexisting versions, for example between versions 3 and 4 (so 3.5) and have the modifications of 3 -> 3.5 still apply to number 4 or even be able to pass a callback to regenerate version 4 data based on 3.5 ones.

Any chance to point me in the right direction on how to do it cleanly ? I don't mind making a PR once the perimeter is set, and have like a feature config to allow this edge case feature.

serialize() vs json_encode()

just wanted to know if there is a particular benefit that made you prefer serialize() over json_encode() ? I am currently looking into doing some analytics and machine learning over the versions and it would be convenient to be able to use JSON RDBMS functions to examine the data etc.

in this spirit would you be open to a PR that makes it optional if the encoding is done with serialize() or json_encode() ?

unserialize(): Error at offset 0 of 893 bytes

While the setup on my local machine (using Xampp with php PHP 7.3.2) works fine, trying to use it on AWS EC2 (using PHP 7.2) results in the following error:

message: "unserialize(): Error at offset 0 of 893 bytes" exception: "ErrorException" file: "/var/app/current/vendor/mpociot/versionable/src/Mpociot/Versionable/Version.php" line: 56

This happens apparently when calling getModel() on a version. Storing new versions seem to work without errors, I can see them in the database.

My guess is that this bug is due to the PHP version.

automatically persist the user

I would like to automatically store the user that made the version in a new field. Is this an optional feature you would accept if I would supply a PR?

Versionable_id force use of integer. What about models with protected $primary_key as varchar()?

How could I use this if I have the following defined on a model:

class Product extends BaseModel
{
    protected $primaryKey = 'sku';
...
}

I have a few tables in my system that do not use integers as their primary key. It is not something I have the ability to change for these tables either, so they must remain varchar().

This constraint forces an integer.

$table->integer('versionable_id');

Get specific version for diff

I think it's usable to have an method to return version based on version_id (not only current and previous) - somethimes we just need every change to our Model (step by step).

For example:

   /**
     * Returns version based on the version id
     * @return Version
     */
	public function getVersion($version_id)
    {
		$class = $this->getVersionClass();
		return $this->versions()->where("version_id", "=", $version_id)->first();
    }

Versioning of child elements

Hi,

can you please help me how to setup versioning for child model in various relationships.

For example, I have a model "Page" and another model "PageWidget" which has a page_id field. I would like to init versioning of PageWidget when I version Page model and keep the connection.

I am willing to hack it if it's not possible out of the box, but I would be happy to get some directions.

And thanks for a great plugin!

Regards,
Mark

Migration errors out on Laravel 4

The migration 2016_07_05_213644_change_versionable_id_and_type_fields.php leaves me with the error

[Illuminate\Database\QueryException]
SQLSTATE[42S21]: Column already exists: 1060 Duplicate column name 'version
able_id' (SQL: alter table versions add versionable_id int unsigned not
null, add versionable_type varchar(255) not null)

[PDOException]
SQLSTATE[42S21]: Column already exists: 1060 Duplicate column name 'version
able_id'

This is because Laravel 4 doesn't support the ->change() syntax. In Laravel 4 you have to use raw SQL to change columns.

Hidden attributes are not being versioned

Sometimes, I want to see the version changes in attributes that have been hidden from the rest of the application using hidden and. visible eloquent properties.

What I have made work for my use case is to provide an override array that makes visible attributes that should be versioned even though they have been configured to be hidden.

I have provided a pull request for my solution in #80

Or is it by design to leave hidden columns out of the versioned model?

Versions table versionable_id and versionable_type

I believe versionable_id should be unsigned. increments() creates an unsigned integer column.

I also think it would be better, at least for performance, if versionable_type was a string (varchar) instead of text. Varchars can usually be stored in the row inline so they require one less disk seek than a text or blob column. This is especially important if one wants to search based on the column.

getModel() can only be called once.

When getModel() is called again - the unserialize() call on line 56 of Version.php fails when model data is a resource.

stream_get_contents() in this case returns an empty string, as the stream has already been read.

Using:
stream_get_contents($this-model_data, -1, 0)
i.e. a stream offset of zero returns the data every time - at least with Postgresql and php 7.4.5

Request: make version data serialization customizable

Currently the serialization is done in VersionableTrait::versionablePostSave() with

$version->model_data = serialize($this->getAttributes());

and deserialization is done in Version::getModel() with

$model->fill(unserialize($modelData));

It would be nice if the method of serialization can be customized by overriding methods, for example to use JSONB column, or even a versions table with all the columns of the versioned model.

trait VersionableTrait
{
    protected function copyAttributesToVersion(Version $version)
    {
       $version->model_data       = serialize($this->getAttributes()); // default implementation
       // or
       $version->model_data = $this->getAttributesData(); // with a JSONB model_data column
       // or
       $version->fill($this->getAttributes()); // versions table with columns for all versioned attributes
    }
}

class Version
{
    protected function copyAttributesToVersionable($model)
    {
         $model->fill(unserialize($modelData));  // default implementation
         $model->fill($modelData); // with a JSONB model_data column
         $model->fill(array_only($this->getAttributes(), $versionedAttributes)); // versions table with columns for all versioned attributes
    }
}

[3.3.1] Migrations not working

With version 3.3.0 the custom migration command was substituted with

$this->loadMigrationsFrom(__DIR__.'/../../../migrations');

in ServiceProvider. Therefore an update from 3.2.x to 3.3.0 was not possible because the migrations file was not added to the migrations table. When doing php artisan migrate, an error occurred as artisan tried to recreate the the versions table. (see #62)

In Version 3.3.1, above code was removed (see 6f5c542), therefore when you create a new project with the current version, migrations are not done at all and the plugin is not usable.

Suggested fix:

  1. Add above code to ServiceProvider again
  2. change migration file to check if table already exists before creating it.

Model with existing record but no version does not create a version on save()

Hi,

I have a database with existing records and we add the VersionableTrait.

I would expect to get a version if we save an existing record?

However I get this with tinker:

$z->versions
=> Illuminate\Database\Eloquent\Collection {#4160
all: [],
}

$z->save()
=> true

$z->versions
=> Illuminate\Database\Eloquent\Collection {#4160
all: [],
}

DD of relevant information on record:

+exists: true
+wasRecentlyCreated: false
-updating: true
-versionableDirtyData: []
-reason: null
#versioningEnabled: true

How can I create a version on this record

Can migration command in documentatio be changed so it doesn't run migrations but move them to the migration folder with current date

Change:

php artisan migrate --path=vendor/mpociot/versionable/src/migrations

to something like

cp vendor/mpociot.../migrations database/migrations

but also to update the dates in the filenames so they get ran when I run the php artisan migrate next time.

The way things are organized now are that I have to run this command whenever I move my code to another server. I had dev server for some time before going to staging and I completely forgot to run these migrations. I suppose the same thing will happen to me when I start the production server.

Installation: migrations won't be executed

Hi,

I want to use this package and followed the install instructions, but php artisan migrate says "Nothing to migrate."

I saw that the migrations are not loaded in the provider. It seems to break updates?
maybe you can use

if (!Schema::hasTable('versions')) {
}

in the migration

Pivot tables

Right now i cant find a way to handle pivot tables and relations. Is this something you are considering to add in a near future or can give an example on how to do?

Usually when i want to version control stuff in my projects i need a version to include a number of models. Would be nice to be able to specify what models that makes a version. And if any of them is changed we would save a new version for all of them.. including pivot tables.

As an example: If i create a model called "Education", where each row is connected to a number of "Subject" with the help of a pivot table, where each "Subject" have some "Teacher" connected to them connected through a pivot table.

Then i would love the possibility to define that a version would consist of the tables:
[educations,
education_subject,
subjects,
subject_teacher
teachers]

So if any of this tables are changed, create a new version.

Or go by Models like this:
[
'Education' => ['subjects'],
'Subject' => ['teachers']
]
where subjects and teachers is relations in this example.

Any thoughts?

'Class auth does not exist' when saving some models

I have two models, both using versionable's VersionableTrait.

One model can be saved without a problem - the other can be saved from a front end component which updates it, but cannot be saved within the backend. The error I get is:

exception 'ReflectionException' with message 'Class auth does not exist' in \vendor\laravel\framework\src\Illuminate\Container\Container.php:741

and looking back up the stack trace, this is triggered by the call to Auth::check() in VersionableTrait's getAuthUserId() method:
#5 \vendor\laravel\framework\src\Illuminate\Support\Facades\Facade.php(120): Illuminate\Support\Facades\Facade::resolveFacadeInstance('auth')
#6 \vendor\laravel\framework\src\Illuminate\Support\Facades\Facade.php(205): Illuminate\Support\Facades\Facade::getFacadeRoot()
#7 \vendor\mpociot\versionable\src\Mpociot\Versionable\VersionableTrait.php(190): Illuminate\Support\Facades\Facade::__callStatic('check', Array)
#8 \vendor\mpociot\versionable\src\Mpociot\Versionable\VersionableTrait.php(190): Illuminate\Support\Facades\Auth::check()
#9 \vendor\mpociot\versionable\src\Mpociot\Versionable\VersionableTrait.php(157): qca\Applicants\Models\Assessment->getAuthUserId()
#10 \vendor\mpociot\versionable\src\Mpociot\Versionable\VersionableTrait.php(79): qca\Applicants\Models\Assessment->versionablePostSave()

Obviously, removing the VersionableTrait from the model allows it to save correctly, but what's a whole lot more puzzling is that the other model works fine... Both models are fairly simple, and also very similar.

The controller involved doesn't seem to be important - before I implemented mk-conn's workaround from issue #11 I got the same error when saving both models (the second model has a relationship to this one), now it's not also trying to save a version for the first model the second saves fine.

I could understand if something was screwed up in my environment and Auth could never be found - but I'm stumped as to how it can be found when saving a version for one model and not another!

Any ideas?

New version will be created when 'touched' by related model

class ModelA extends Eloquent {
    use VersionableTrait;

    protected $touches = ['ModelB'];

}

class ModelB extends Eloquent {
    use VersionableTrait;
}

ModelA will be updated and touches ModelB and the VersionableTrait also creates a version for ModelB because of this:

/**
     * Save a new version.
     * @return void
     */
    protected function versionablePostSave()
    {
        /**
         * We'll save new versions on updating and first creation
         */
        if (
            ( $this->versioningEnabled === true && $this->updating && $this->isValidForVersioning() ) ||
            ( $this->versioningEnabled === true && !$this->updating )
        ) {
            // Save a new version
            $version                   = new Version();
            $version->versionable_id   = $this->getKey();
            $version->versionable_type = get_class($this);
            $version->user_id          = $this->getAuthUserId();
            $version->model_data       = serialize($this->getAttributes());

            if (!empty( $this->reason )) {
                $version->reason = $this->reason;
            }

            $version->save();
        }
    }

It assumes, its the first creation of the ModelB because of $this->versionEnabled === true && !$this->updating will resolve to true which is not really wanted in this case...

Version Limit

Would it be possible to limit the number of versions that are stored for a model? Alternatively, having a method to purge items older than X, or after N number of versions.

The limit could be stored on a property of the model.

Apart from that, this package seems great so far, thanks!

Error when running migrations

The command php artisan migrate --package=mpociot/versionable does not work on Laravel 5.1

Returns this error:

[RuntimeException]                      
The "--package" option does not exist.

Update the README file suggesting php artisan migrate --path=vendor/mpociot/versionable/src/migrations

Thanks!

reason in updated() event

I am using the reason inside an updated event. It seems like reason is reset before this event is triggered, So I figured I just fetch it from the current version, but for some (likely stupid) reason, I sometimes then get the previous and not the current version. I assume there is some caching going on, so I wonder how I can reliably ensure I get the actual current version and not some cached instance that is no longer valid after the update?

public function updated(Foo $foo)
{
    $version = $foo->currentVersion();
    $action = $version->reason;

How to get the current version ID of a model?

This seems like a very simple question, but I don't see any documented option to get the current version ID.

I currently use $model->versions()->count() to get the current version count, but this does not seem right and I can't use it to reference to retrieve the version of the model needed.

Thanks in advance!

Roy

unserialize() expects parameter 1 to be string, resource given

I am receiving this error using Postgres:
PHP warning: unserialize() expects parameter 1 to be string, resource given in /my-project/vendor/mpociot/versionable/src/Mpociot/Versionable/Version.php on line 52

I managed to get it working by changing Version's getModel() method with this before unserializing it:
$modelData = is_resource($this->model_data) ? stream_get_contents($this->model_data) : $this->model_data;

do you know of a better way to get around it or can I make a PR with this fix?

Unable to load auth-model

The Auth-Model in Version.php (method: "getResponsibleUserAttribute()") can't be loaded. The return value of the Config::get() method just returns "null".

In Laravel 5.3 the config option should be however "auth.providers.users.model" instead of just "auth.model".

So the method should be like this:

/**
 * Return the user responsible for this version
 * @return mixed
 */
public function getResponsibleUserAttribute()
{
    $model = Config::get('auth.providers.users.model');
    return $model::find($this->user_id);
}

JSON columns with array cast are double encoded

When a model has a "JSON array castable field", for example by defining protected $casts = ['field' => 'array'], the stored versions will be double JSON encoded. For example, if the original model's column value was {"a": "b"}, the version's getModel() will have the column value "{\"a\": \"b\"}".

This happens because when saving a version, VersionableTrait::versionablePostSave() uses getAttributes(), and when restoring a version, Version::getModel() uses fill($attributes). fill will do conversions based on $casts (JSON encoding in this case), but getAttributes returns attributes as-is (already JSON-encoded string in this case). To fix this, VersionableTrait::versionablePostSave() should use attributesToArray() instead, which would return array castable columns as arrays, so that fill() works expectedly.

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.