I am using Laravel spark, and I am restricting team access to models by employing a scope that is implemented in a trait
namespace App\Scopes;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
class TeamScope implements Scope
{
/**
* Apply the scope to a given Eloquent query builder.
*
* #param \Illuminate\Database\Eloquent\Builder $builder
* #param \Illuminate\Database\Eloquent\Model $model
* #return void
*/
public function apply(Builder $builder, Model $model)
{
$builder->where('team_id', '=',Auth()->user()->currentTeam->id );
}
}
my issue is that when I run the DB seeder it fails because there is no user to auth against.
The seeder doesn't have any methods to allow me to log in a particular user.
is there a way to disable the global scope whilst seeding, or any other solution for that matter?
THanks
If you're calling the model inside the seed, you can just call ->withoutGlobalScopes() first
more on that here https://laravel.com/docs/5.7/eloquent#query-scopes at the 'Removing Global Scopes' section.
Related
Suppose i have a laravel model that works with a certain (MySQL) database table.
Inside of this table there is a column named 'administration'. (example: could be 1, 2 or 3)
At the moment in my controller im using that modal with eloquent and inside of my eloquent statement i ask only to work with records (crud style) that have administration 2 for instance.
I think it should be possible to add 'where administration = x' to my model instead of my controller so that if i use the model in my controller i would just be dealing with records that have that administration set.
Is this possible? I have tried googling it but could not find an answer yet.
Laravel uses global scopes for this.
You would create a scope for the administration:
<?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
class AdministrationScope implements Scope
{
/**
* Apply the scope to a given Eloquent query builder.
*
* #param \Illuminate\Database\Eloquent\Builder $builder
* #param \Illuminate\Database\Eloquent\Model $model
* #return void
*/
public function apply(Builder $builder, Model $model)
{
$builder->where('administration', '=', 2);
}
}
And then you add it as a global scope to the model
<?php
namespace App\Models;
use App\Scopes\AdministrationScope;
use Illuminate\Database\Eloquent\Model;
class YourModel extends Model
{
/**
* The "booted" method of the model.
*
* #return void
*/
protected static function booted()
{
static::addGlobalScope(new AdministrationScope);
}
}
i have table products.
i need make something in model only return product where approved is equal to 1
this my schema
Schema::create('products', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->text('description');
$table->unsignedInteger('quantity');
$table->unsignedInteger('subcategory_id')
->references('id')->on('subcategories')->onDelete('cascade');
$table->decimal('price');
$table->decimal('discount_price');
$table->decimal('super_discount')->nullable();
$table->string('cover');
$table->unsignedInteger('brand_id')
->references('id')->on('brands')->onDelete('cascade');
$table->unsignedInteger('category_id')
->references('id')->on('categories');
$table->string('color');
$table->string('size_id')->references('id')->on('sizes')->nullable();
$table->decimal('rate');
$table->enum('made_in',['turkey','china','egypt']);
$table->string('serial');
$table->boolean('approved')->default(0);
$table->timestamps();
$table->unique(['name','size_id','color']);
});
i hope this is valid.
You can make use of Global Scopes
Global scopes allow you to add constraints to all queries for a given
model. Laravel's own soft deleting functionality utilizes global
scopes to only pull "non-deleted" models from the database. Writing
your own global scopes can provide a convenient, easy way to make sure
every query for a given model receives certain constraints.
Writing Global Scopes Writing a global scope is simple. Define a class
that implements the Illuminate\Database\Eloquent\Scope interface. This
interface requires you to implement one method: apply. The apply
method may add where constraints to the query as needed:
<?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
class ApprovedScope implements Scope
{
/**
* Apply the scope to a given Eloquent query builder.
*
* #param \Illuminate\Database\Eloquent\Builder $builder
* #param \Illuminate\Database\Eloquent\Model $model
* #return void
*/
public function apply(Builder $builder, Model $model)
{
return $builder->where('approved', 1);
}
}
There is not a predefined folder for scopes in a default Laravel
application, so feel free to make your own Scopes folder within your
Laravel application's app directory.
Applying Global Scopes To assign a global scope to a model, you should
override a given model's boot method and use the addGlobalScope
method:
<?php
namespace App;
use App\Scopes\ApprovedScope;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
/**
* The "booting" method of the model.
*
* #return void
*/
protected static function boot()
{
parent::boot();
static::addGlobalScope(new ApprovedScope);
}
}
After adding the scope, a query to Product::all() will produce the
following SQL:
select * from `products` where `approved` = 1
Docs
Most of my db table contain create_user_id and update_user_id
How can l update this two field automatic when l use save(), update(), insert(), createOrUpdate() and etc method.
For example, l execute this script:
$model = Model::find(1);
$model->model_f = 'update';
$model->save();
then this record's model_f updated, and update_user_id updated, too.
l know eloquent can manage update_time automatic and l have use it already. But l want to do something else when update or insert or delete
PS: l have a constant named USERID to remember current user's id
You could make use of Observers.
You can hook to the following events on your Model:
retrieved
creating
created
updating
updated
saving
saved
deleting
deleted
restoring
restored
Let me give you an example where we are trying to hook into the events emitted by the App/User model. You can change this to match your particular Model later on.
To create an observer, run the following command:
php artisan make:observer UserObserver --model=User
Then you can hook to specific events in your observer.
<?php
namespace App\Observers;
use App\User;
class UserObserver
{
/**
* Handle the User "saved" event.
*
* #param \App\User $user
* #return void
*/
public function saved(User $user)
{
//
}
/**
* Handle the User "created" event.
*
* #param \App\User $user
* #return void
*/
public function created(User $user)
{
//
}
/**
* Handle the User "updated" event.
*
* #param \App\User $user
* #return void
*/
public function updated(User $user)
{
//
}
}
Since, in your particular case, you want to hook into these 3 events, you can define the events above and perform additional operations to your model when those events are called.
Don't forget to register this observer in your AppServiceProvider.
<?php
namespace App\Providers;
use App\User;
use App\Observers\UserObserver;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
User::observe(UserObserver::class);
}
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
//
}
}
There is pretty simple way to automatically update the create_user_id and update_user_id
Step1:
Open you app folder and create the new file named as UserStampsTrait.php
Step:2
and paste the following code
<?php
namespace App;
use Illuminate\Support\Facades\Auth;
trait UserStampsTrait
{
public static function boot()
{
parent::boot();
// first we tell the model what to do on a creating event
static::creating(function($modelName='')
{
$createdByColumnName = 'create_user_id ';
$modelName->$createdByColumnName = Auth::id();
});
// // then we tell the model what to do on an updating event
static::updating(function($modelName='')
{
$updatedByColumnName = 'update_user_id';
$modelName->$updatedByColumnName = Auth::id();
});
}
}
Thats it
Step:3
Open you model which needs to updated the corresponding models automatically
for Example it may be Post
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\UserStampsTrait;
class Post extends Model
{
use UserStampsTrait;
}
Thats it
Im using Laravel 5.4 i have created the auth system guard using the laravel stuff, i have also created a role based registration form.
At this point all works so far, but for example i want to only certains pages to be available only for admin, so i have created a New User page to allow the admin create users.
My RegisteruserControoller:
namespace App\Http\Controllers;
use App\Proveedor;
use App\RubroProveedor;
use Illuminate\Http\Request;
use App\Http\Requests\StoreProveedor;
use App\Http\Requests\UpdateProveedor;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redirect;
use Alert;
use Exception;
use Auth;
class RegisteruserController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct() {
$this->middleware('role:admin');
}
public function index(Request $request)
{
return view('usuarios.registeruser');
}
My problem here is if i use the middleware in construct im always being asked to login again and again, and i need to disable that but keep the guard to allow only admin user create new users.
Im not sure if im clear, im sorry my bad english.
I have created a Middleware called CheckRole:
<?php
namespace App\Http\Middleware;
use Closure;
class CheckRole
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next, $role)
{
if (! $request->user()->hasRole($role)) {
abort(401, 'This action is unauthorized.');
}
return $next($request);
}
}
So, I have an 'is_abandoned' boolean on one of my tables, where if it's true, I'd like the model to be automatically excluded from any query - just like softDeletes does.
Is there something I can set in the model that'd achieve this? I'm leaning towards maybe a mutator?
These are called Global Query Scopes.
Writing a global scope is simple. Define a class that implements the Illuminate\Database\Eloquent\Scope interface. This interface requires you to implement one method: apply. The apply method may add where constraints to the query as needed:
<?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
class AgeScope implements Scope
{
/**
* Apply the scope to a given Eloquent query builder.
*
* #param \Illuminate\Database\Eloquent\Builder $builder
* #param \Illuminate\Database\Eloquent\Model $model
* #return void
*/
public function apply(Builder $builder, Model $model)
{
$builder->where('age', '>', 200);
}
}
To assign a global scope to a model, you should override a given model's boot method and use the addGlobalScope method:
<?php
namespace App;
use App\Scopes\AgeScope;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The "booting" method of the model.
*
* #return void
*/
protected static function boot()
{
parent::boot();
static::addGlobalScope(new AgeScope);
}
}
You can just exclude the record using eloquent where function
$lists = List::where('is_abandoned',false);
Here's an example:
Create a function within the Eloquent
class User extends Eloquent {
public function scopeAbandoned($query)
{
return $query->where('is_abandoned', '=', 1/*true*/);
}
}
Then simply use it like this:
$approvedPosts = Post::abandoned()-><put_your_own_condition>;
For detailed info read Eloquent Query Scopes.
No repeated WHERE function calls. Hope It works.