Giter Site home page Giter Site logo

laravel-binary-uuid's Issues

Expose method to generate binary UUID

Hi,

I have a use case where I need to insert lots of rows to a table. To do so, my approach is to use Eloquent's insert method and provide it an array of data to insert, instead of creating lots of instances of my model and then save() each - which will run a single query per row. The goal is to optimize my INSERT process, since I require lots of data to be inserted to the table.
Since my table uses binary UUID as IDs, I need to include a binary ID in my array which I pass to the insert method. To do this, I used:
MyModel::encodeUuid(\Ramsey\Uuid\Uuid::uuid1())

It would be nice if the package provide a way to generate binary UUIDs.
Else - any suggestions for an alternative approach for INSERTing lots of rows?

Thanks a lot

Composite Key Not Working

Just basically doing a sanity check here because I'm assuming the changes were tested.
In the README it states that composite keys are supported, thus steps:

  1. Create a model and make it extend Illuminate\Database\Eloquent\Relations\Pivot
  2. Add use Spatie\BinaryUuid\HasBinaryUuid;
  3. Change the getKeyName method, as stated in README
public function getKeyName()
{
    return ['key_id', 'key_id_two'];
}
  1. Try to create Model with tinker and receive

PHP Notice: Array to string conversion in vendor/spatie/laravel-binary-uuid/src/HasBinaryUuid.php on line 14

Can't store values in a model with UUID in it

So I set it up everything perfectly but when I create a 'store' function it says this

``SQLSTATE[HY000]: General error: 1364 Field 'id' doesn't have a default value (SQL: insert into users (`name`, `email`, `password`, `uuid`, `updated_at`, `created_at`) values\

Do i also need to specificy the uuid inside the add function? Doesn't it get generated automatically like 'id' use to?

Make models with HasBinaryUuid trait serializable when the model key is not selected

Right now this injects the key to the returned array, even when the key is not selected. Which makes Model::select(fields) a pain to use when the primary key is not selected.

Problem:

// Model with `HasBinaryUuid` trait
Model::select('created_at')->first()->toArray();

Throws an error saying uuid cannot be null:

TypeError: Argument 1 passed to Model::decodeUuid() must be of the type string, null given, called in spatie/laravel-binary-uuid/src/HasBinaryUuid.php on line 89

JSON serialization still doesn't work

PHP Fatal error:  Method App\Models\Demo\Account::__toString() must not throw an exception, caught Illuminate\Database\Eloquent\JsonEncodingException: Error encoding model [App\Models\Demo\Account] with ID [���}E�A����B�� in /var/www/laravel/vendor/laravel/framework/src/Illuminate/Database/MySqlConnection.php on line 80

In MySqlConnection.php line 80:
                                                                                                                                                                                                               
  Method App\Models\Demo\Account::__toString() must not throw an exception, caught Illuminate\Database\Eloquent\JsonEncodingException: Error encoding model [App\Models\Demo\Account] with ID [���}E�A����B��

This is when trying to create the model during a DB seeder. I'm just doing this:

$person = new App\Models\Demo\Account;
$person->identifier = $code;
$person->name = $person;
$person->address = $address;
$person->date_of_birth = date('Y-m-d');
$person->save();

I'm using the latest, v1.1.1

General error: 1215 Cannot add foreign key constraint when using relations

Hi,

I am getting this error when running: php artisan migrate:refresh --seed. If I change back to normal ids I do not get this error.

Full error:
Illuminate\Database\QueryException : SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL: alter tableinvoicerowsadd constraintinvoicerows_invoice_id_foreign foreign key (invoice_id) references invoices (id) on delete cascade)

My old migrations:

// Invoices migration
Schema::create( 'invoices', function ( Blueprint $table ) {
	$table->increments( 'id' );
}
// Invoicerows migration
Schema::create( 'invoicerows', function ( Blueprint $table ) {
	$table->increments( 'id' );

	$table->integer( 'invoice_id' )->unsigned()->nullable();
	$table->foreign( 'invoice_id' )->references( 'id' )->on( 'invoices' )->onDelete( 'cascade' );
}

New migration after installing `spatie/laravel-binary-uuid':

// new Invoices migration
Schema::create( 'invoices', function ( Blueprint $table ) {
	$table->uuid('uuid');
        $table->primary('uuid');
}
// New Invoicerows migration
Schema::create( 'invoicerows', function ( Blueprint $table ) {
	$table->uuid('uuid');
        $table->primary('uuid');

	$table->integer( 'invoice_uuid' )->unsigned()->nullable();
	$table->foreign( 'invoice_uuid' )->references( 'uuid' )->on( 'invoices' )->onDelete( 'cascade' );
}

When I now run php artisan migrate:refresh --seed I get that error.

I have tried to add my original id field: $table->increments( 'id' ); but I suppose you do not need an id field anymore when using binary uuids?

Incorrect string value error when inserting into table

I created a table in MySQL 5.7 using the following migration class:

class CreateGroupsTable extends Migration
{
    public function up()
    {
        Schema::create('groups', function (Blueprint $table) {
            $table->uuid('id')->primary();
            $table->string('name', 50);
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('groups');
    }
}

For MySQL, Laravel creates an id column of type CHAR(36) set as the primary key.

Unfortunately, when attempting to save a model, I received an error:

>>> $group = new Group();
=> App\Group {#744}
>>> $group->name = 'PUG Foo';
=> "PUG Foo"
>>> $group->save();

Illuminate\Database\QueryException with message 'SQLSTATE[HY000]: General error: 1366 Incorrect string value: '\xE7\xCF\xEA\x06\xE2\x0B...' for column 'id' at row 1 (SQL: insert into `groups` (`name`, `id`, `updated_at`, `created_at`) values (PUG Foo, ����
                                                    ��<���v, 2017-11-23 01:02:50, 2017-11-23 01:02:50))'

I tried several Laravel column type definition variations, including binary(), which uses MySQL's BLOB type instead of BINARY or VARBINARY and generates this error when attempting to set it as a primary key:

$ php artisan migrate

  [Illuminate\Database\QueryException]
  SQLSTATE[42000]: Syntax error or access violation: 1170 BLOB/TEXT column 'id' used in key specification without a key length (SQL: alter table `groups` add primary key `groups_id_primary`(`id`))

I was finally able to successfully save the model and use spatie/laravel-binary-uuid only after using raw SQL to create the id column as a BINARY(16) column in MySQL, like this:

class CreateGroupsTable extends Migration
{
    public function up()
    {
        Schema::create('groups', function (Blueprint $table) {
            $table->string('name', 50);
            $table->timestamps();
        });

        DB::statement('ALTER TABLE `groups` ADD COLUMN `id` BINARY(16) NOT NULL PRIMARY KEY FIRST');
    }

    public function down()
    {
        Schema::dropIfExists('groups');
    }
}

Now, my models save properly with binary UUIDs as primary keys.

I don't think there's anything to change in spatie/laravel-binary-uuid to fix this, but maybe the documentation should be updated.

Perhaps adding binary and varbinary types to Illuminate\Database\Schema\Blueprint in laravel/framework would help make this easier to use. Should I recommend this directly on laravel/framework? It appears it's been rejected in the past (laravel/framework#3297), but it seems MySQL deals with binary data differently in CHAR/VARCHAR fields fromBINARY/VARBINARY fields.

"Malformed UTF-8 characters, possibly incorrectly encoded" with uuid relations

I have some hard times with uuid relations and json representation.

My work model has two foreign keys (user_id and workstation_id) in binary format.
My user model has a hasMany relationship with the work model.

My controller looks like :

public function show($uuid)
{
    $user = User::withUuid($uuid)
        ->with('profile')
        ->with('works')
        ->first();

    if (! $user) {
        abort(404);
    }

    return compact('user');
}

It throw the error mentionned in the title.

But it works well with tinker :

$user = User::withUuid('2094a25a-efde-11e7-8005-f156302fb27e')->with('profile')->with('works')->paginate(10)->first();
[!] Aliasing 'User' to 'App\User' for this Tinker session.
=> App\User {#795
     id: b"\x11çïÞ ”¢Z€\x05ñV0/²~",
     username: "amber.pagac",
     email: "[email protected]",
     firstname: "Kip",
     lastname: "Lindgren",
     group: "e",
     profile_id: 1,
     login_count: 0,
     created_at: "2018-01-02 16:58:16",
     updated_at: "2018-01-02 16:58:16",
     deleted_at: null,
     profile: App\Profile {#808
       id: 1,
       name: "neque",
       description: "Aut mollitia quis amet necessitatibus aliquid consequatur. Cum eum a voluptas incidunt iusto magnam quasi. Quia quis maiores sit ut omnis dolor. Quis doloremque aut totam unde hic sed sunt.",
       created_at: "2018-01-02 16:58:16",
       updated_at: "2018-01-02 16:58:16",
       deleted_at: null,
     },
     works: Illuminate\Database\Eloquent\Collection {#807
       all: [
         App\Work {#805
           id: b"\x11çðg‰EC*–…]`¯!\x11w",
           user_id: b"\x11çïÞ ”¢Z€\x05ñV0/²~",
           workstation_id: b"\x11çïÞ l\x15ˆ©'!¨ÅKÁ‹",
           started_at: "2017-12-12 10:24:41",
           ended_at: "2017-12-12 11:05:37",
           grade_id: 2,
         },
         App\Work {#802
           id: b"\x11þ­gë\DlØ╣몡║:\x7F",
           user_id: b"\x11çïÞ ”¢Z€\x05ñV0/²~",
           workstation_id: b"\x11þ´Ì bsHèØsq─╣óî",
           started_at: "2017-12-13 12:46:31",
           ended_at: "2017-12-17 20:53:32",
           grade_id: 3,
         },
         App\Work {#801
           id: b"\x11çðg‰k³„³³Áâ\x07”˜ˆ",
           user_id: b"\x11çïÞ ”¢Z€\x05ñV0/²~",
           workstation_id: b"""
             \x11çïÞ mTR¢\n
             iF±ïQz
             """,
           started_at: "2017-12-16 03:18:59",
           ended_at: "2017-12-25 22:40:29",
           grade_id: 1,
         },
       ],
     },
   }

If I append the toJson() method on the tinker command line, it throw an error Illuminate\Database\Eloquent\JsonEncodingException with message 'Error encoding model [App\User] with ID [��� ��Z��V0/�~] to JSON: Malformed UTF-8 characters, possibly incorrectly encoded'.

If I append the toArray() method, only the work id is translated to a string.

I guess the problem comes from the json encoding of the user_id and workstation_id in the Work model.

I tried to use the withUuid mentionned in the README, but I don't have a work_id in my users table.

Is there a way to encode the faulty uuid ?

Forget to mention, I work with PHP7.2 and Laravel 5.5

Using pivot tables help with uuid

So my User model has uuid enabled and its successfully migrating and has a binary uuid
Now my Role model has a Pivot relation with User as role_user table with role_id and user_id.

My question is instead of user_id, what will I have to use?

    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->uuid('uuid');
            $table->primary('uuid');
            $table->string('name');
            $table->string('email')->unique();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }

My role_user table
   public function up()
    {
        Schema::create('role_user', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('role_id')->unsigned()->nullable()->index();
            $table->uuid('user_uuid')->unsigned()->nullable()->index();
            
        });
    }

My Roles Table

 public function up()
    {
        Schema::create('roles', function (Blueprint $table) {
            $table->increments('id');
           // $table->string('display_name');
            $table->string('name');
            $table->timestamps();
        });
    }

Problem: When I try to save the relation like this it gives me error:
Route::get('/test', function(){

    $uuid = '478d7068-ae64-11e8-a665-2c600cf6267b';

    $model = User::withUuid($uuid)->first();

    $model->roles()->save(new Role(['name' => 'Admin']));

 });

Using Eloquent find* methods with string UUID

Hi,

Currently we can only use the find* methods (find, findOrFail, etc) with binary UUIDs.

It would be nice to get those methods to work when given a valid UUID string too.

Would you be ok for a PR which would override those find methods in the trait to make use of the withUuid scode instead of the withKey scope when a UUID string is detected?

Migration ignoring table prefix

After installing this package, and runing php artisan migration

 SQLSTATE[HY000]: General error: 1005 Can't create table 'boljacij_new.#sql-357d_1c82b7' (errno: 150) (SQL: alter table `promotion_pages` add constraint `promotion_pages_image_id_foreign` foreign key (`image_id`) references `images`
  (`id`) on delete restrict on update restrict)

config/database.php:

'connections' => [

        'mysql' => [
            'driver' => 'mysql',
            'host' => env('DB_HOST', 'localhost'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'charset' => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix' => 'bc_',
            'strict' => false,
            'engine' => 'InnoDB',
        ],

db migration file

Schema::create('promotion_pages', function (Blueprint $table) {
            $table->uuid('uuid');
            $table->string('title');
            $table->text('content');
            $table->integer('image_id')->unsigned()->default(1);
            $table->foreign('image_id')->references('id')->on('images')
                ->onUpdate('restrict')->onDelete('restrict');
            $table->primary('uuid');
        });

When I remove this package, everyting runs normal.

laravel passport support

i add this to app provider boot function

 Passport::ignoreMigrations();
   
 Passport::$tokenModel= \App\Token::class;

and changed user_id in oauth_access_tokens to uuid in migration

the problem is i need to leave the string token index in the \App\Token::class;

<?php

namespace App;

use Laravel\Passport\Token as BaseToken;

use App\Traits\HasBinaryUuid;

class Token extends BaseToken
{
    use HasBinaryUuid;

    protected $uuids = [
        'user_id' // foreign or related key
    ];

}

but i am getting this error i am sure its problem because of uuid

RuntimeException
Error while encoding to JSON: Malformed UTF-8 characters, possibly incorrectly encoded

i need to use the trait HasBinaryUuid
but disable primary key just for foreign one

Rename typeUuid to typeUuidBinary to allow use of normal UUIDs

Currently it is not possible to use normal UUIDs for other fields as the typeUuid method overwrites the original uuid method that Laravel comes with.

It would be good if it would be possible to have 2 distinct functions for uuid and uuidBinary to allow use of both as the package doesn't automatically store every uuid type field as an optimised UUID.

A use case for that would be invite codes where you maybe choose to use UUIDs as tokens but if you use this package you will have to either use string or char(36).

Incompatible with Laravel Horizon

Laravel Horizon has a feature where it tries to tag a jobs intelligently if it sees that the object passed into the job is an Eloquent model. When they do this, they use $model->getKey(). With binary UUIDs, getKey() returns a binary string, so things kinda explode in there when it tries to pass the string to Redis.

I'm not sure what other side effects overriding getKey() to instead pass the UUID as a string would have, but I think this needs to be fixed in some way or another.

Edit: Did a quick find in all files for ->getKey()... Apparently it gets used all over the place to do WHERE SQL queries, so I don't think overriding it would do much good (without additional changes). I'm not sure where to go from here. I reported it on laravel/horizon to see what happens.

Laravel Scout: Issue with newQueryForRestoration($id) (Add Array Support)

Greetings,

Firstly, excellent package and nice work being done here!

The issue:

I am trying to get this to play nice with Laravel Scout and am encountering an issue when using queues with Scout. In the HasBinaryUuid trait, the following function is implemented in your package:

public function newQueryForRestoration($id)
{
		return $this->newQueryWithoutScopes()->whereKey(base64_decode($id));
}

When performing operations on models with the Searchable trait, it seems to be passing an array to this function and causing an exception. It seems to be a one element array based on my testing as such:

array(1) { [0]=> string(36) "2d6a1fc0-b4a8-11e8-8375-ac220bbf9530" } (example)

The error: base64_decode() expects parameter 1 to be string, array given

The (very quick) workaround for me:

public function newQueryForRestoration($id)
{
		if ( is_array($id) ) {
			$id = $id[0];
		}
	  return $this->newQueryWithoutScopes()->whereKey(base64_decode($id));
}

This is the official source of this function from Laravel:

public function newQueryForRestoration($ids)
{
	return is_array($ids)
			? $this->newQueryWithoutScopes()->whereIn($this->getQualifiedKeyName(), $ids)
			: $this->newQueryWithoutScopes()->whereKey($ids);
}

https://github.com/laravel/framework/blob/5.6/src/Illuminate/Database/Eloquent/Model.php#L972

Does it make sense to make your function override support arrays as well?

Thanks

Can we have an incremental id (for internal relations) too?

The package handles UUID greatly but using UUID for everything doesn't make sense.

For example, we can use UUID as external key to requested resource and an incremental id to handle internal requests (and relations). But by disabling $incrementing, we're unable to have both.

So my question is how is it possible to have an incremental id alongside an optimized UUID and actually use them?

Lumen support

What is the reason for the dependency "laravel/framework": "~5.5.22"? I created a fork and replaced it with "laravel/lumen-framework": "~5.5" and it works successfully.

And reasons not to include Lumen support?

Model using the HasBinaryUuid trait is not booted correctly

Problem occurs when you try to convert newly created model instance to an array:

(new App\SomeModel(['foobar' => 'whatever']))->toArray();
TypeError: Argument 1 passed to App\SomeModel::decodeUuid() must be of the type string, null given, called in […]/vendor/spatie/laravel-binary-uuid/src/HasBinaryUuid.php on line 81

This happens because toArray() tries to get an "uuid text" attribute which is null at this point:

public function getUuidTextAttribute(): string
{
    return static::decodeUuid($this->{$this->getKeyName()});
}

[BUG]Stop overriding `getKeyName` method of Model class.

Hi!
Thanks for the great works!!

I found a problem to redefine primary key of models.

In the spatie/laravel-binary-uuid/src/HasBinaryUuid.php

where this getKeyName method is overriding Illuminate\Database\Eloquent\Model::getKeyName. Which cause problems.

trait HasBinaryUuid{
    public function getKeyName()
    {
        return 'uuid';
    }
}

according to your documentation:

If don't like the primary key named uuid you can manually specify $primaryKey. Don't forget set $incrementing to false.

use Illuminate\Database\Eloquent\Model;
use Spatie\BinaryUuid\HasBinaryUuid;

use Illuminate\Database\Eloquent\Model;
use Spatie\BinaryUuid\HasBinaryUuid;

class TestModel extends Model
{
    use HasBinaryUuid;

    public $incrementing = false;
    
    public $primaryKey = 'uuid';  // THIS WON'T WORK! Because primaryKey is hardcoded in the `getKeyName` method.
}

To fix it just remove the getKeyName method from the HasBinaryUuid trait.

Am I missing something…!? Because obviously overriding parent's method and hardcoding options is a bad idea in the first place… or maybe providing a config file would be nicer just like the https://github.com/EmadAdly/laravel-uuid/blob/master/src/LaravelUuidServiceProvider.php#L25 dose so.

Can't work with Laravel Passport

Laravel Passport will throw errors if using binary UUID.
I just created a package laravel-passport-binary-uuid-adapter to allow Passport accept binary UUID to work with this package.

I found some people encountering the same issue here, so if you don't mind, add a link to this package to your README will be helpful for people who are using Passport I think😃

uuid() blueprint method creates a char(36) column instead of binary(16)

I am using v1.3.0 of this package with Laravel v5.6.39.

According to the docs, $table->uuid('uuid') is supposed to create a binary(16) column in database, but for some reason a char(36) is created instead.

I am changing database connections on the fly, so maybe that's the problem? Maybe the override behavior of Laravel's uuid() method is not working or something is not registering correctly?

Usage with Laravel Nova

Has anyone successfully managed to setup Nova with Binary UUIDs?

Currently trying to do so, but it seems to be a loooonnnnnggggg way till I get it to work.

Several reports here and there of people not being able to use it even with String UUIDs ...

Relation model saving causes "UTF-8" Error

I'm struggling with relationship models which contains uuid. Trying to save model which has uuid as FK.
Saving model gives "Malformed UTF-8 characters, possibly incorrectly encoded" as a response.

Model looks like:

class Follow extends Model
{
    use HasBinaryUuid;

    protected $uuids = [
        'corporation_uuid'
    ];
    

    public function user(){
        return $this->belongsTo(User::class);
    }

    public function corporation(){
        return $this->belongsTo(Corporation::class);
    }

Controller function looks like:

public function store($corporation)
    {
        $user = auth('api')->user();
        if($user->isFollowing($corporation)){
            return response([
                'message' => 'Already following'], Response::HTTP_OK);
        }

        $corporation = Corporation::withUuid($corporation)->first();

        $follow = new Follow();
        $follow->user_id = $user->id;

        $corporation->follows()->save($follow);
        
        return response([
            'message' => 'Followed'], Response::HTTP_OK);
    }

Is there any workaround saving with uuid as FK?
Thanks.

`HasUuidPrimaryKey` trait is redundant

The HasBinaryUuid trait already assumes that the primary key of the model should be a binary UUID:

protected static function bootHasBinaryUuid()
{
    static::creating(function (Model $model) {
        if ($model->{$model->getKeyName()}) {
            return;
        }

        $model->{$model->getKeyName()} = static::encodeUuid(Uuid::uuid1());
    });
}

and also more or less expects the primary key name to be uuid (rather than id or whatever).

public function getUuidTextAttribute(): string
public function setUuidTextAttribute(string $uuid)

So HasUuidPrimaryKey trait doesn't influence whether the primary key will be treated as UUID, which is kind of bad, if you just want to use HasBinaryUuid trait for other attributes.
But even if the intention of HasUuidPrimaryKey is just an overkill way to change the primary key name from id to uuid, it makes no sense tha HasUuidPrimaryKey implements

public function getIncrementing()
{
    return false;
}

while HasBinaryUuid doesn't.

The best behavior would be for HasBinaryUuid to leave the primary key alone, unless HasUuidPrimaryKey is set.

json_encode results in JSON_ERROR_UTF8 because of uuid field

Currently it is not possible to json serialize any model that uses this package because the uuid field is in binary format.

json_encode(\App\Announcement::first());

dd(json_last_error()); // Results in 5 which equals JSON_ERROR_UTF8

I am currently solving this issue by using protected $hidden = ['uuid']; and protected $appends = ['id'] where ID is the method from here #12

It might be worth considering to replace the uuid field data with the uuid_text attribute value for the array format to allow working with it without any extra hacks like I do right now.

Unknown database type binary requested, Doctrine\DBAL\Platforms\SqlitePlatform may not support it.

Hey there,

I'm using this alongside Laravel Dusk with SQLite for testing purposes, problem is when I try and run the db migrations I get this error:

Doctrine\DBAL\DBALException: Unknown database type binary requested, Doctrine\DBAL\Platforms\SqlitePlatform may not support it.

I've not really used Dusk or SQLite before and after some digging SQLite doesn't have the "binary" datatype but instead uses "blob".

I checked the SQLiteGrammar file and it specifies binary(16) for the typeUuid - changing this to blob(256) fixes the issue.

Just wondering if it's something I'm doing wrong or should the Grammar file specify the blob data type?

thanks

Relies on static UUID factory not being changed

Currently the library sets the static default Uuid factory with OrderedTimeCodec at boot in the package service provider.

The issue is where somewhere else in the application changes the static factory and uses a different codec.

Solution is to register a singleton OrderedTimeCodec in the service container, and resolve the instance whenever it is needed.

Will submit a PR.

Thanks for the library :) Although it's not quite suitable for my needs, I was able to adapt some ideas for my own project.

Making `_text` available to other secondary UUID columns

Currently, the trait offers some goodies on the main uuid field (the PK). Models may have foreign keys to other models according to their UUID. It would be nice to open some of the features on those attributes too.

The _text computed attribute

other UUID attributes should also have a corresponding computed string representation. e.g. relation_uuid_text would return string version of relation_uuid

This could be handled in the same way as dates are handled. Have a protected $uuids = [ 'relation_uuid' ] on the model to let the trait know which attributes are handled as UUIDs.

Would you be ok for a PR about that?

Error when using with Implicit route model binding

Getting the following error when using implicit route model binding:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'uuid_text' in 'where clause' (SQL: select * from projects where uuid_text = e775e0aa-f407-11e7-8a11-080027a8df8b limit 1)

Seems like it's using uuid_text as defined in getRouteKeyName().

My current workaround is to add a middleware to encode the UUID before the route model binding kicks in, and change the routeKeyName to uuid, which seem to work. But would love to hear if there's any better solution.

Great package for a very common use-case anyhow, thanks!

Error in HasBinaryUuid trait...?

Isn't this method in Spatie\BinaryUuid\HasBinaryUuid likely to cause errors when explicitly setting the primary key...?

    public function getKeyName()
    {
        return 'uuid';
    }

The examples seem to allow for explicitly setting the primary key to something other than uuid:

If don't like the primary key named uuid you can leave off the HasUuidPrimaryKey trait and manually specify $primaryKey.

Use ID and UUID

Its possible use ID and UUID in same table with relations?

I use, but cause Malformed UTF-8 characters, possibly incorrectly encoded on save with relations.

Question - Should I still have a fk defined $casts?

I'm converting a schema to use uuids.

In my model I have

    /**
     * Casts
     *
     * @var array
     */
    protected $casts = [
        'country_id' => 'int',
    ];

I see in the readme that I should add

    /**
     * The binary UUID attributes that should be converted to text.
     *
     * @var array
     */
    protected $uuids = [
        'country_uuid' // foreign or related key
    ];

So I'm removing the column country_id and replacing it with country_uuid.

The question is, do I need to define that in any way in $casts or is that replaced for uuids by the $uuids array?

Running DB::purge() is unloading extension

Using a DB::purge() to reset the database connection is unloading this UUID plugin, causing an issue with multi-database sites.

I'm using a multi-database approach on our website. I'm building a multi-db migration using a method of overloading the migration commands I found online.

However, I discovered an issue when attempting to use this extension in combination with the DB::purge() method for re-initializing the DB resources for the second database. When I use DB::purge() this extension seems to get unloaded. When I try to use DB::disconnect() I run into migration issues, due to latent knowledge of migration table.

Is there anyway to re-instantiate this plugin when I need to purge out existing db connections?

[Question] Infinite recursion for getAttribute when present in multiple traits

I am using this library along with some other libraries which also provide traits for the getAttribute method.

I cannot manage to find the right way to use both traits for the same model class.

Here is the corresponding StackOverflow question: https://stackoverflow.com/questions/51823409/detect-recursion-when-overridding-trait-methods which has some more details about the use case.

Any input? Ideas? You may have already solve that as your libraries often override that method.

Validation not working?

Laravel 5.6
Laravel Binary Uuid 1.1

I'm sure I'm missing something here (I've been back to Laravel for only the past 6 months).

I have a model that uses the HasBinaryUuid trait. In my Request class, I want to check for uniqueness of one of the attributes, so I did:

    public function rules()
    {
        return [
            'name'                      => [
                'required',
                'max:255',
                'unique:model_table,name,'.$this->model_name->id
            ],

Unfortunately, the following error occurs:

[2018-08-10 15:49:01] local.ERROR: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '`?' at line 1 (SQL: select count(*) as aggregate from `model_table` where `name` = Test and `�\';L�` <> 蜱��)

Any ideas?

Accessors for non-primary-key UUID fields

The HasBinaryUuid trait seems to forcefully convert the primary key to its text representation during toArray. Even if this was the wanted behavior, any other UUID fields are left on their own. For example, a "belongs to" scenario, where a user_id or user_uuid binary UUID exists, nothing is done to convert that field to text. That leads to unclear exceptions due to json_decode failing for the binary field.

For consistency, the primary key should probably not forcefully be converted to text. Instead we could add something like public $uuidFields = ['id', 'user_id']; to the models. A default value for $uuidFields could take care of the automatic conversion of the primary key, while the user may set $uuidFields = [] to disable that behavior.

Lack of "ID" in key name results in exception

I'm using a legacy schema that won't be modified. A uuid column named "CreatedBy" does not contain "id" or "uuid", so getRelatedBinaryKeyName doesn't return the attribute with suffix. Commenting out the preg_match line and just returning "{$attribute}{$suffix}" fixes the issue:

    public function getRelatedBinaryKeyName($attribute): string
    {
        $suffix = $this->getUuidSuffix();

      //return preg_match('/(?:uu)?id/i', $attribute) ? "{$attribute}{$suffix}" : $attribute;
        return "{$attribute}{$suffix}";
    }

Since the CreatedBy column is provided in the model's $uuids array, should getRelatedBinaryKeyName really be doing that check for "uuid" or "id"? If so, could this be made to be conditional based on a config setting?

The exception is thrown from here in Illuminate/Http/JsonResponse.php:

if (! $this->hasValidJson(json_last_error())) {
    throw new InvalidArgumentException(json_last_error_msg());
}

Exception:
InvalidArgumentException. Malformed UTF-8 characters, possibly incorrectly encoded

Does it support for lumen 5.5?

I made an installation of this package in my project that I'm using lumen 5.5 and I had this error, but I did not find anything in the documentation talking about lumen support.

composer require spatie/laravel-binary-uuid
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Conclusion: don't install spatie/laravel-binary-uuid 1.0.2
    - Conclusion: don't install spatie/laravel-binary-uuid 1.0.1
    - Conclusion: remove illuminate/auth v5.5.17
    - Installation request for spatie/laravel-binary-uuid ^1.0 -> satisfiable by spatie/laravel-binary-uuid[1.0.0, 1.0.1, 1.0.2].
    - Conclusion: don't install illuminate/auth v5.5.17
    - spatie/laravel-binary-uuid 1.0.0 requires laravel/framework ^5.5.22 -> satisfiable by laravel/framework[5.5.x-dev, 5.6.x-dev, v5.5.22].
    - don't install laravel/framework 5.5.x-dev|don't install illuminate/auth v5.5.17
    - don't install laravel/framework 5.6.x-dev|don't install illuminate/auth v5.5.17
    - don't install laravel/framework v5.5.22|don't install illuminate/auth v5.5.17
    - Installation request for illuminate/auth (locked at v5.5.17) -> satisfiable by illuminate/auth[v5.5.17].

Thank you

[Idea] Split up HasBinaryUUID trait

The HasBinaryUUID trait is quite 'all in'. It's not so easy to mix how your models work.

If your model A does not have binary uuid, but B has, and you're working with relations, it's nice to have the toArray() from the trait, but I don't want the creating listener code.

Ordered UUID for Laravel MySQL grammar query compilation via custom builder

Once pending PRs are reviewed/attended to, it will be pertinent to consider ordered uuids for setting up partial sequential ids in database tables making it easy to sort/index at DB level. The custom eloquent builder and grammar PHP classes in this package will be updated to have this new behaviour. This could be the basis of a version 2 of the package focusing on performance with respect to UUIDs.

For context, see:

https://www.percona.com/blog/2014/12/19/store-uuid-optimized-way

Not compatible with Scout

On laraval 5.6 in combination with Scout I get a json utf 8 error

Imported [App\Models\Users] models up to ID: ���^�҆�����
and
ERROR: JSON parsing error: malformed UTF-8 characters, possibly incorrectly encoded

If i uninstall the packages and use uuid as a string then the combination with scout is not a problem.

How can i fix the malformed utf-8 error?

UUID is not properly formatted

The article linked in the readme describes how to format uuid v1 for mysql, however it does not appear that this library is correctly optimizing. While storing the UUID as a binary is a massive improvement over storing it as a CHAR/VARCHAR, it is only part of the problem.

A standard UUID v1 will generate a very poor primary key as the first half of the UUID is based on time while the second half is based on MAC address. The UUID needs to be reordered going into the database in order to have an efficient binary tree.

For example:

Package breaks Laravel Notifications because of overwrites

Laravels database notifications use $table->uuid('id')->primary(); by default so using this package breaks them which results in SQLSTATE[22001]: String data, right truncated: 1406 Data too long for column 'id' at row 1.

$table->char('id', 36)->primary(); solves the issue but having to change the default migrations is kinda off-putting.

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateNotificationsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('notifications', function (Blueprint $table) {
            $table->uuid('id')->primary();
            $table->string('type');
            $table->morphs('notifiable');
            $table->text('data');
            $table->timestamp('read_at')->nullable();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('notifications');
    }
}

with('relation') . cause utf8 encode error

the problem is that laravel toArray add pivot data and if it include uuid it will make utf8 error

i fixed this by removing pivot from the array
if (isset($array['pivot'])){
unset($array['pivot']);
}

this is the new trait toArray


    public function toArray()
    {
        $uuidAttributes = $this->getUuidAttributes();
        $array = parent::toArray();
        if (! $this->exists || ! is_array($uuidAttributes)) {
            return $array;
        }
        foreach ($uuidAttributes as $attributeKey) {
            if (! array_key_exists($attributeKey, $array)) {
                continue;
            }
            $uuidKey = $this->getRelatedBinaryKeyName($attributeKey);
            $array[$attributeKey] = $this->{$uuidKey};
        }

  if (isset($array['pivot'])){
            unset($array['pivot']);
        }


        return $array;
    }

     Schema::create('roles', function (Blueprint $table) {
            $table->uuid('id');
            $table->string('name')->unique();
        });

        Schema::create('permissions', function (Blueprint $table) {
            $table->uuid('id')->primary();
            $table->string('name');
        });
    Schema::create('permission_role', function (Blueprint $table) {
            $table->uuid('permission_id')->index()->foreign('permission_id')->references('slug')->on('permissions')->onDelete('cascade');;
            $table->uuid('role_id')->index()->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');
        });

class Role extends Model
{
    use HasBinaryUuid;

    protected $uuids = [
        'id'
    ];
  public function permissions()
    {
        return $this->belongsToMany(Permission::class,'permission_role','role_id','permission_id');

    }

}
class Permission extends Model
{
    use HasBinaryUuid;

    protected $uuids = [
        'id'
    ];

 public function roles()
    {
        return $this->belongsToMany(Role::class,'permission_role','permission_id','role_id');
    }

}



    Route::any('roles', function () {
        return Role::with('permissions')->get() ;
    });


Malformed UTF-8 characters, possibly incorrectly encoded
i think the model to Array not working on collections and join

any help

Is it necessary to explicitly set incrementing to false...?

The docs suggest that "[t]o get your model to work with the encoded UUID (i.e. to use uuid as a primary key), you must let your model use the Spatie\BinaryUuid\HasBinaryUuid" but "[i]f [you] don't like the primary key named uuid you can leave off the HasUuidPrimaryKey trait and manually specify $primaryKey. Don't forget set $incrementing to false."

However, Spatie\BinaryUuid\HasBinaryUuid has the following method:

    public function getIncrementing()
    {
        return false;
    }

So...shouldn't it be enough to just use Spatie\BinaryUuid\HasBinaryUuid and not explicitly set $incrementing to false...?

Undefined property when declearing uuid method

Heya, I'm trying to defined the following method on a modal which uses this library's trait but I get the following exception. Any idea why this is happening? Can't seem to wrap my head around it.

    public function uuid(): UuidInterface
    {
        return Uuid::fromString($this->uuid_text);
    }
ErrorException: Undefined property: App\Models\Subscription::$uuid in /Users/driesvints/Sites/laravelio/vendor/spatie/laravel-binary-uuid/src/HasBinaryUuid.php:81

Let me know if you want more info.

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.