Code Monkey home page Code Monkey logo

eloquent-uuid's People

Contributors

alsofronie avatar andrzejkupczyk avatar dannyweeks avatar elliotwms avatar golinmarq avatar jimmylagp avatar jvalck avatar rawaludin avatar saf33r avatar silasrm avatar westphalen avatar wvdongen avatar zmorris 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

eloquent-uuid's Issues

UuidBinaryModelTrait error when using toArray or toJSON

I was getting the following error:

PHP warning: preg_match() expects parameter 2 to be string, object given in /home/.../vendor/alsofronie/eloquent-uuid/src/UuidBinaryModelTrait.php on line 105

I had to override the method in my model by adding extra check if the value is not object:

private function deepArray($array)
    {
        foreach ($array as $key => $value) {
            $value = $array[$key];
            if (is_array($value)) {
                $array[$key] = $this->deepArray($value);
            } elseif (!is_object($value) && !preg_match('//u', $value)) {
                // TODO: drop the preg_match because it's slow and
                // what if a binary value in the uuid gets represented
                // by valid ASCII or UTF symbols?
                $array[$key] = (property_exists($this, 'uuidOptimization') && $this::$uuidOptimization) ?
                    self::toNormal($value) :
                    bin2hex($value);
            }
        }

        return $array;
    }

UuidBinaryModelTrait::toArray() throes exception with one-to-many relations.

In the new 1.0.5 release there is the following error, when attempting to call toArray() on an object using the UuidBinaryModelTrait and having at least a one-to-many relation:

preg_match() expects parameter 2 to be string, array given
(...)/vendor/alsofronie/eloquent-uuid/src/UuidBinaryModelTrait.php Line 94

Solution

Probably the right solution would be to check if $key == $this->primaryKey instead of checking with a regex. That would ensure the conversion would be done only for the primary key (which is the only key we know of that contains binary data).
Yes, there might be more than one key containing binary data (for example in a one-to-one relation, there could be a reference to another model using the UuidBinaryModelTrait), but I think at that point it's the developer's duty to use $model->$hidden to hide them (or to provide an accessor method to properly format them). Otherwise, just check that the value is actually a string before using the regex.
If you like my solution I can try to make a pull request during the weekend to fix the bug.

Quick and dirty workaround

In the meantime I have implemented the following workaround, which disables the UuidBinaryModelTrait::toArray() method by renaming it and by using the base Model::toArray() one.

<?php

namespace Blah;

use Alsofronie\Uuid\UuidBinaryModelTrait;
use Illuminate\Database\Eloquent\Model;

trait BinaryUUIDTrait
{
	use UuidBinaryModelTrait {
		// Rename the trait's toArray method so that the parent one can be used.
		UuidBinaryModelTrait::toArray as _brokenToArray;
	}

	/**
	 * @see Model::toArray()
	 * @return array
	 */
	public function toArray()
	{
		// Forward the call to the parent method.
		return parent::toArray();
	}
}

If you copy-paste it to a file, and use this trait instead of the original one, $model->toArray() works again (although you will see binary junk in the array. :)

Queuing models gives invalid payload

Hi,

when working with the binary traits, it is currently impossible to to add them to the queue as the models contain malformed UTF-8. A possible solution is to modify the serialization process (see laravel/framework#19252 and laravel/framework#15065).

I currently created a dirty workaround by creating an extra trait. In my case all the binary fields in the database end with id, this declares the check in the unserialize method:

<?php

namespace App;

/**
* Allows serialization and deserialization for models
* //TODO: fix slow deserialization
*/
trait UuidBinaryModelSerialization
{
	public function serialize()
    {
        return json_encode($this->toArray());
    }

    public function unserialize($stringRepresentationOfObject)
    {
        $decodedArray = json_decode($stringRepresentationOfObject);
        foreach ($decodedArray as $key => $value) {
            if(substr($key, -2) === "id"){//convert to binary
                $this->$key = $this->toOptimized($value);
            }else{
                $this->$key = $value;
            }            
        }
    }

Another possibility is adding an array to the models containing the names of the fields that are binary. This should decrease the amount of checks in the for-loop in unserialize.

Would it be possible to allow an OOTB solution for this serialization process?

toNormal doesn't add dashes back to uuid

During optimisation dashes are removed using regex:
$uuid = preg_replace('/\-/', null, $uuid);

But in the toNormal($uuid) method removed dashes aren't being added back.

Boot events break with Event::fake() when testing

I'm trying to test event dispatching in my application using the PHPUnit tools provided by Laravel.

In a test where Event::fake() is called before creating a new Model (a User for instance) the package's UUID trait's boot method seems to break.

I get MySQL errors relating to field id not having a default value:

QueryException: SQLSTATE[HY000]: General error: 1364 Field 'id' doesn't have a default value (SQL: insert into ...

I'm using Laravel 5.6 as my application base.

Trimmed example code to reproduce:

<?php

class migration_dis_and_dat
{
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->uuid('id');
            $table->string('email')->unique();
            $table->string('password');
            $table->timestamps();

            $table->primary('id');
        });
    }
}
<?php

class User extends Model {
    use UuidModelTrait;

    ...
}
<?php

class UserTest extends TestCase
{
    public function test_user_create_dispatches_event()
    {
        Event::fake();

        User::create(['email' => '[email protected]', 'password' => Hash::make('helloworld'));

        // around here the error should appear,
        // if you comment `Event::fake()` and `Event::assertDispatched`
        // then the user should be created normally

        Event::assertDispatched(MyEvent::class);
    }
}

FindOrFail support

Hi, it's possible to use findOrFail in the same way as find with both the binary version or the string (bin2hex) version???

v1.0.8 Breaks custom attribute on model/More memory required

Although the new release seems to fix the serialization problem (#29), setting a temporarily custom attribute with default PHP syntax is no longer possible.

Unit test:

public function testToArray(){
	$model = EloquentBinOptimizedUserModel::create([
            'username' => 'Model',
       	    'password' => 'secret'
       	]);
	$customModel = EloquentBinOptimizedPostModel::create(['name' => 'bla']);
	$model->cust = $customModel;
		
	$array = $model->toArray();
	static::assertNotNull($array);

	$json = json_encode($array);
	var_dump($json);
	static::assertNotNull($json);

}

The test above passes in v1.0.7, but the new version leads to more memory consumption resulting in:
mmap() failed: [12] Cannot allocate memory
causing the server to hang/crash.

Boot method on Model

I love this package make it easier to save my ID.

Found a problem if I have method boot at my model like example:

protected static function boot()
{
    parent::boot();

    static::addGlobalScope('follows_count', function (Builder $builder) {
        $builder->withCount('follows');
    });
}

The eloquent-uuid won't run if I create new instance. If I remove the boot method it will work properly.

Any solution?

5.3 Support

Hello, thanks for this great package, however I keep getting this error "General error: Field 'id' doesn't have a default value" as it appears the "creating" event is not firing. Has anyone else seen this issue? Any ideas on how to fix?

Laravel 5.5 Uuid not working if there's another static boot function

In my model:

Order.php

use Uuid32ModelTrait;

protected static function boot()
    {
        static::deleting(function ($order) { // before delete() method call this
            $order->items()->delete();
        });
    }

When I save:

 $order = new Order();
 $order->user()->associate($user);
$order->save();

it always return me "message": "SQLSTATE[HY000]: General error: 1364 Field 'id' doesn't have a default value "

If I remove my boot function it works properly.

creating() isn't getting called

I've tried implementing this and it isn't working for me. My model does not have any boot stuff added, so there shouldn't be any conflicts. The methodbootUuidModelTrait() gets called, but I'm getting a SQL error before static::creating() is called.

SQLSTATE[HY000]: General error: 1364 Field 'id' doesn't have a default value (SQL: insert into `sessions` (`user_id`, `updated_at`, `created_at`) values (8, 2016-11-10 21:20:49, 2016-11-10 21:20:49))
<?php
namespace Example\Models;

use Illuminate\Database\Eloquent\Model;
use Alsofronie\Uuid\UuidModelTrait;

class Session extends Model {
  use UuidModelTrait;
}
$session = new \Example\Models\Session();
$session->user_id = 8;
$session->save();
CREATE TABLE `sessions` (
  `id` char(36) NOT NULL,
  `user_id` int(11) NOT NULL,
  `expires_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Traits must use bootTraitName() rather than boot()

Hi this is my first time doing a pull request, the fix is at #6 for your convenience. Here is the background behind the fix:

I'm using a static boot() function in my models and the problem is that the model events for creating() and created() are getting called out of order. This is due to the UuidModelTrait boot() getting called at the incorrect time and registering its creating() event to happen after my created() event. More info:

http://www.archybold.com/blog/post/booting-eloquent-model-traits

https://laracasts.com/discuss/channels/eloquent/cant-use-trait-if-i-have-a-boot-method-declared?page=1

The fix for UuidModelTrait is:

public static function bootUuidModelTrait()
    {
        //parent::boot();
        static::creating(function ($model) {

            // This is necessary because on \Illuminate\Database\Eloquent\Model::performInsert
            // will not check for $this->getIncrementing() but directly for $this->incrementing
            $model->incrementing = false;
            $uuidVersion = (!empty($model->uuidVersion) ? $model->uuidVersion : 4);   // defaults to 4
            $uuid = Uuid::generate($uuidVersion);
            $model->attributes[$model->getKeyName()] = $uuid->string;
        }, 0);
    }

Same goes for bootUuid32ModelTrait() and bootUuidBinaryModelTrait(). This new code works when I call parent::boot(); within my model's boot() function.

Many-to-many relation insert not working

I'm using the UuidBinaryModelTrait for all my models.
Unfortunately the sync method (provided by Laravel) doesn't seem to generate a binary Uuid.

To be more concrete:
I have a class User and a class Organisation. A User has multiple organisations and an Organisation has multiple users. This relationship is saved in the database table user_organisations, which is where the problem occurs. When I call $user->organisations()->sync([$o_id, $o_id2]) to insert a new row, I get an Internal Server Error indicating that the primary key already exists. When I verify the user_organisations table, I noticed that the only row in the table has a key 0x000000000000000000000000000000.

Get uuid of newly created model

How do you get the uuid of a newly created model?
The uuid is saved to the database correctly, but isn't being set on the returned model and reloading from the database doesn't work because the keys don't match.

ErrorException in UuidBinaryModelTrait.php line 94

ErrorException in UuidBinaryModelTrait.php line 94:
preg_match() expects parameter 2 to be string, array given

It indicates it goes wrong here:
at preg_match('//u', array('id' => '6dee1660-b57a-11', 'code' => 'NL', 'name' => 'The Netherlands', 'asset_id' => null, 'created_at' => null, 'updated_at' => null, 'id_string' => '36646565313636302d623537612d3131', 'asset' => null)) in UuidBinaryModelTrait.php line 94

I am currently using Lumen 5.3.

When I comment out these lines in the function toArray(), it seems to work fine:

foreach ($parentArray as $key => $value) {
    if(!preg_match('//u', $parentArray[$key])){//non-valid utf-8
        $parentArray[$key] = (property_exists($this, 'uuidOptimization') && $this::$uuidOptimization)
        ? self::toNormal($parentArray[$key]) : bin2hex($parentArray[$key]);
    }
}

Can we get a new release including the bootTrait() fixes?

I was looking forward to use this library since it's the only one I found that takes into consideration the DB storage optimization for UUIDs.
However, the latest release does not include pull request #6 yet, so I have to write some funny code to make the trait work fine with custom boot logic.

I can't use the master branch or the development release, I am required to use normal releases available from packagist. Is there any chance of a newer release including this fix coming in the near future?
Thanks.

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.