Comments (20)
@theoxuan Is there any ways can you share code with me?
from ntrust.
Yes, but what I mean is that the NtrustUserTrait
has a collision with laravel's built-in SoftDeletes
trait. It's because both of them have a method called restore
- overrided from Model
.
This is Laravel's SoftDeletes.php
<?php
namespace Illuminate\Database\Eloquent;
trait SoftDeletes
{
//omitted
/**
* Restore a soft-deleted model instance.
*
* @return bool|null
*/
public function restore()
{
// If the restoring event does not return false, we will proceed with this
// restore operation. Otherwise, we bail out so the developer will stop
// the restore totally. We will clear the deleted timestamp and save.
if ($this->fireModelEvent('restoring') === false) {
return false;
}
$this->{$this->getDeletedAtColumn()} = null;
// Once we have saved the model, we will fire the "restored" event so this
// developer will do anything they need to after a restore operation is
// totally finished. Then we will return the result of the save call.
$this->exists = true;
$result = $this->save();
$this->fireModelEvent('restored', false);
return $result;
}
//omitted
/**
* Determine if the model is currently force deleting.
*
* @return bool
*/
public function isForceDeleting()
{
return $this->forceDeleting;
}
//omitted
}
And here is the provided trait NtrustUserTrait.php
<?php namespace Klaravel\Ntrust\Traits;
use Illuminate\Cache\TaggableStore;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Config;
use InvalidArgumentException;
trait NtrustUserTrait
{
//omitted
public function delete(array $options = [])
{ //soft or hard
parent::delete($options);
if(Cache::getStore() instanceof TaggableStore) {
Cache::tags(Config::get('ntrust.profiles.' . self::$roleProfile . '.role_user_table'))->flush();
}
}
public function restore()
{ //soft delete undo's
parent::restore();
if(Cache::getStore() instanceof TaggableStore) {
Cache::tags(Config::get('ntrust.profiles.' . self::$roleProfile . '.role_user_table'))->flush();
}
}
//omitted
}
There's a public method isForceDeleting()
which you can use in observers to tell if it's a soft deleting. So there is no need to override restore()
and delete()
since that will cause a conflict with SoftDeletes
trait if the model has used both traits(which in my case).
This is how I do in an registerd observer:
<?php
namespace App\Observers;
use App\User;
class UserObserver
{
//omitted
public function deleting(User $user)
{
if($user->isForceDeleting()) {
//hard deleting
info('hard');
}
else {
//soft deleting
info('soft');
}
}
}
Another approach is to use SoftDeletes
trait in a parent model.
from ntrust.
I found issue. I will update you code or give you solution soon.
from ntrust.
Got solution. Use below code and it will well. Let me know if it will generate other issue.
Replace:
// use SoftDeletes;
// use NtrustRoleTrait;
With:
use SoftDeletes, NtrustRoleTrait
{
SoftDeletes::restore insteadof NtrustRoleTrait;
NtrustRoleTrait::restore insteadof SoftDeletes;
}
from ntrust.
Thanks for your solution but I think you are erasing restore()
from both traits.
I did a test:
<?php
trait A
{
function restore()
{
echo "A";
}
}
trait B
{
function restore()
{
echo "B";
}
}
class Model {
function restore()
{
echo "Model";
}
}
class User extends Model {
use A, B {
A::restore insteadof B;
B::restore insteadof A;
}
}
$user = new User;
$user->restore(); //result is 'Model'
from ntrust.
This one will work:
<?php
trait A
{
function restore()
{
parent::restore();
echo "A";
}
}
trait B
{
function restore()
{
parent::restore();
echo "B";
}
}
class Model {
function restore()
{
echo "Model";
}
}
class BaseUser extends Model {
use A;
}
class User extends BaseUser {
use B;
}
$user = new User;
$user->restore(); //result is 'ModelAB'
from ntrust.
But there is one problem class Model don't have restore()
method.
from ntrust.
Hmm sorry I forget that.
In our condition it should be
<?php
trait A
{
function restore()
{
echo "A";
}
}
trait B
{
function restore()
{
echo "B";
}
}
class Model {
}
class User extends Model {
use A, B {
A::restore as restoreA;
B::restore as restoreB;
}
function restore(){
$this->restoreA();
$this->restoreB();
}
}
$user = new User;
$user->restore(); //result is 'AB'
from ntrust.
Great. That one will work perfectly.
Thanks for solution. I did not test on my solution.
I will update document.
Let me know if you will find any other solution directly on trait then I will apply on that on.
I might use restore event $this->fireModelEvent('restored', false);
and it will work.
from ntrust.
There is one more thing. Why is there a parent::restore()
call in NtrustUserTrait::restore
?
from ntrust.
I have actually copied this package from other and fix many laravel 5.0 to 5.3 bugs.
So no idea why they calling parent::restore() event parent don't have restore method. And I did no focus for testing soft delete so missed that area.
I will update this package in day or two with event thing. It will fix all this issue.
Or you can fork package and make pull request and I will merge it.
from ntrust.
Pull request created.
Closed.
from ntrust.
Hey @theoxuan
Thanks for pull request. I have merge that one and applied other setting for all traits also now you can use normal.
use SoftDeletes;
use NtrustUserTrait;
Can you please try with "klaravel/ntrust": "dev-master"
one and let me know if it's work for you with caching.
Thanks for fix and help to build great package.
from ntrust.
Sorry dude I forgot to give you my feedback.
This package is just not Laravel-5.3 ready. A lot of internal function calls are broken.
In the end I implemented my own permission controlling system.
Thanks anyway!
from ntrust.
Hi @seancheung Thanks for feedback.
It would be great if you can give me one or two example like what thing is not working.
I am using in my live project this roles and permission things and working great for me but if it has any bug then I can fix it.
from ntrust.
@ajmerainfo
I actually created my own package:
panoscape/privileges
It's inspired by your package(and the original package you forked).
from ntrust.
Great. Thank you for information.
from ntrust.
Dude I just found a method named bootTraits
when digging Laravel's Mode.php
.
I think it's better to stop overriding boot
method in traits, instead name it as bootTraitName
(TraitName is the name of the trait) and it will be called when the model is being booting.
Here is how it's handled in Model.php
/**
* The "booting" method of the model.
*
* @return void
*/
protected static function boot()
{
static::bootTraits();
}
/**
* Boot all of the bootable traits on the model.
*
* @return void
*/
protected static function bootTraits()
{
$class = static::class;
foreach (class_uses_recursive($class) as $trait) {
if (method_exists($class, $method = 'boot'.class_basename($trait))) {
forward_static_call([$class, $method]);
}
}
}
Also do not override model events but listen to them. Register listening in bootTraitName
.
This will completely remove those collisions with ease.
from ntrust.
Good to know. Thank you for great information.
I will implement that one in this package.
About model event I am using like below is that perfect?
static::saved(function()
{
if(Cache::getStore() instanceof TaggableStore) {
Cache::tags(Config::get('ntrust.profiles.' . self::$roleProfile . '.role_user_table'))
->flush();
}
});
static::deleted(function($user)
{
if(Cache::getStore() instanceof TaggableStore) {
Cache::tags(Config::get('ntrust.profiles.' . self::$roleProfile . '.role_user_table'))
->flush();
$user->roles()->sync([]);
}
});
if(method_exists(self::class, 'restored')) {
static::restored(function($user)
{
if(Cache::getStore() instanceof TaggableStore) {
Cache::tags(Config::get('ntrust.profiles.' . self::$roleProfile . '.role_user_table'))
->flush();
$user->roles()->sync([]);
}
});
}
from ntrust.
It is alright. But I think a separate observer would be cleaner:
<?php
namespace Your\Package;
class YourModelObserver
{
/**
* Listen to the Model saved event.
*
* @param mixed $model
* @return void
*/
public function saved($model)
{
//
}
/**
* Listen to the Model deleting event.
*
* @param mixed $model
* @return void
*/
public function deleting($model)
{
if($model->forceDelete()) {
//softdelete
}
else {
//hard delete
}
//
}
/**
* Listen to the Model restored event.
*
* @param mixed $model
* @return void
*/
public function restored($model)
{
//
}
}
Just register it to the model like this
<?php
namespace Your\Package;
trait YourModelTrait
{
public static function bootYourModelTrait()
{
static::observe(YourModelObserver::class);
}
}
With this you don't event need to check method existence(like restored
in SoftDeletes
trait) .
Another suggestion is to pick Cache
to separate trait.
I think there are some problems(or my misunderstanding?) with the logic in your code.
$user->roles()->sync([]);
detaches all roles of the model, why do you call them in restored
?
I think it should be:
- when deleting, if the model uses
SoftDeletes
, keep the relationships, flush the cache; - when saved, flush the cache;
- when restored, never mind about the relationships, just flush the cache.
from ntrust.
Related Issues (20)
- Admin.php HOT 11
- BadMethodCallException with message 'Call to undefined method Illuminate\Database\Query\Builder::attachRole() HOT 2
- Call to undefined method Illuminate\Database\Query\Builder::restored() HOT 3
- Class name must be a valid object or a string HOT 4
- Class name must be a valid object or a string HOT 5
- Multi Auth migration create HOT 1
- Access to undeclared static property User::$staticRoleProfile HOT 6
- Migration to klaravel/ntrust from Zizaco/entrust HOT 1
- attachRole does not working HOT 6
- error in ntrust:migration
- $roleProfile variable is not present in user object HOT 1
- Access to undeclared static property: $staticRoleProfile HOT 1
- all with the admin role HOT 1
- [BadMethodCallException] Call to undefined method Illuminate\Database\Query\Builder::attachPermissio ns() HOT 1
- ntrust vs laravel built-in authorization HOT 2
- Edit role permissions issue HOT 3
- Route level if condition else redirects to dashboad. HOT 2
- No admin table ? HOT 2
- any plan to support the latest version of Laravel?
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ntrust.