Configuration observer in Laravel - php

I am beginner in Laravel. I use in my project Laravel 8.
I have this code:
Controller
public function index(Request $request)
{
$query = $this->model
->orderBy($request->column ?? 'created_at', $request->order ?? 'desc');
if ($request->search) {
$query->where(function ($query) use ($request) {
$query->where('name', 'like', '%' . $request->search . '%')
->orWhere('id', 'like', '%' . $request->search . '%');
});
}
return DictionaryResource::collection($query->paginate($request->per_page));
}
public function create()
{
$statuses = DB::table('status')->select('status.name as label', 'status.id as value')->get();
$types = DB::table('dictionary_types')->select('dictionary_types.name as label', 'dictionary_types.id as value')->get();
return response()->json([$statuses, $types]);
}
public function store(DictionaryRequest $request)
{
$data = $request->only([
'name',
]);
if($request->status == 2) $status = 2;
else $status = 1;
if(is_null($request->type)) $type = 1;
else $type = $request->type;
$data['status'] = $status;
$data['type'] = $type;
$this->model->create($data);
return response()->json(['status' => 'success']);
}
Model
class Dictionary extends Model
{
use ScopeActiveTrait,
SoftDeletes;
protected $guarded = ['id'];
protected $fillable = [
'name',
'type',
'status'
];
protected $dates = [
'deleted_at',
'created_at',
'updated_at'
];
}
Observer
class DictionaryObserver
{
public function created(Dictionary $dictionary)
{
Log::info('yyyyyyyyy');
}
public function retrieved(Dictionary $dictionary)
{
Log::info('xxxxxxxxxx'.$dictionary);
}
public function updated(Dictionary $dictionary)
{
//
}
public function deleted(Dictionary $dictionary)
{
//
}
}
ServiceProvider
public function boot()
{
Paginator::useBootstrap();
Dictionary::observe(DictionaryObserver::class);
}
I have 2 questions / problems:
How can I disable following in the controller (index method)? I only need to record the moment when someone opens one record for editing, and does not list all the records in the list
I have model Action:
class Action extends Model
{
use ScopeActiveTrait,
SoftDeletes;
protected $guarded = ['id'];
protected $fillable = [
'company_id',
'user_id',
'ip',
'user_agent',
'description'
];
protected $dates = [
'deleted_at',
'created_at',
'updated_at'
];
}
I need save to this model information about user ip, user_agent itp (user is logged).
How can I make it?

As you've found, the "retrieved" method on the observer is called when you load the model instance, whether you load one or many (if you load many, it is called once for each model loaded).
You can suppress events being fired (and, having tested it, this includes both Events and Observers) by wrapping it in a callback function using the ::withoutEvents() static method.
So (using code from one of my sites) if I use :
$games = Game::where('id', '>=', 4900)->where('id', '<=', 4910)->get();
then the GameObserver will be called 11 times (because there are 11 models which are loaded). But if I wrap it in the ::withoutEvents method like so :
$games = Game::withoutEvents(function () {
$games = Game::where('id', '>=', 4900)->where('id', '<=', 4910)->get();
return $games;
});

Related

Laravel Eloquent map in query

I have a problem with mapping objects in a Laravel eloquent query.
How to map relations in a query builder.
How to connect two separate collections.
For example. Having models:
class CartProduct extends Model
{
protected $fillable = [
'quantity',
'cart_id',
'product_id',
'unit_price',
'product_code'
];
function product(){
return $this->belongsTo(Product::class);
}
function cart(){
return $this->belongsTo(Cart::class);
}
}
class Cart extends Model
{
function productsInCart()
{
return $this->hasMany(CartProduct::class);
}
public function products()
{
return $this->belongsToMany(
Product::class,
'cart_products',
'cart_id',
"product_id");
}
}
class Product extends Model
{
protected $fillable = [
'name',
'code',
'description',
'price',
];
}
The tasks are:
Get a set of products that are in the same cart (doesn't matter which one) as $product_id (excluding $product_id)
Get a set of products that were in any cart together with $product_id (excluding $product_id, without duplications)
I would solve it like this:
1.
public function task_one($product_id)
{
return $products = CartProduct::where('product_id', $product_id)->first()->cart->products
->filter(function (Product $p) use ($product_id) {
return $p->id !== $product_id;
});
}
public function task_two($product_id)
{
$cartProducts = CartProduct::where('product_id', $product_id)->get();
$products = collect(new Product);
foreach ($cartProducts as $cartProduct) {
$productsInCart = $cartProduct->cart->products
->filter(function (Product $p) use ($product_id) {
return $p->id !== $product_id;
});
$products = $products->merge($productsInCart);
}
return $products->unique();
}
However, the 2nd function seems to be awful. How can I do this properly, to achieve fast execution and a good style of code?
Is there any method to "map" the whole collection to related model objects? For example by
$carts = CartProduct::getByProductId($product_id)->"mapByRelationship('cart)";
//The result should be a collection od Carts
$products = CartProduct::getByProductId($product_id)->"mapByRelationship('cart)"->"mapByRelationship('products')"->unique();
//The result should be the same as task_two($product_id);
Thank you in advance
I think I have done this Controller-Model Relationship.
Controller:
class MakeAWishController extends Controller
{
public function getMakeAWishes(Request $request)
{
$limit = (int) ($request->limit ?? 1);
$offset = (int) ($limit * (($request->page ?? 1) - 1));
$wishes = MakeAWish::with('product')
->offset($offset)->limit($limit)->where('product_quantity', '>' , '0')->get()
->map(function ($wish) {
$wish->children_image = asset(Storage::url($wish->children_image));
if(!empty($variant = $wish->product->variant())) {
$wish->product->variant_id = $variant->variant_id;
$wish->product->variant_price = $variant->variant_price ?? "0.00";
$wish->product->variant_compare_at_price = $variant->variant_compare_at_price ?? "0.00";
}
return $wish;
});
$response = [
'status' => 200,
'data' => $wishes
];
return response()->json($response);
}
}
Model:
class MakeAWish extends Model
{
protected $collection = 'make_a_wishes';
protected $fillable = [
'children_name',
'children_name_for_isis',
'age',
'country',
'children_image',
'product_id',
'quantity'
];
protected $casts = [
'product_id' => 'string'
];
public function product()
{
return $this->hasOne(Product::class, 'product_id', 'product_id');
}
public function orders()
{
return $this->hasMany(OrderHistory::class, 'type_id', '_id');
}
public function orderCount()
{
return $this->orders()->where('type', 'M')->count();
}
}

Laravel : How to get all users who have a certain role?

I have three roles: 1. Admin 2. Client 3. Store
I have three tables: 1. users 2. roles 3.role_user
How can I get all users who have the role Client?
I tried this
$clients = User::roles()->where('App\Models\Role',Role::CLIENT)->get();
I'm getting following error.
Non-static method App\Models\User::roles() should not be called
statically
Role Model
class Role extends Model
{
public const ADMIN = 'Admin';
public const CLIENT = 'Client';
public const STORE = 'Store';
public function users()
{
return $this->belongsToMany('App\Models\User')->using('App\Models\UserRole');
}
}
User Model
class User extends Authenticatable
{
use Notifiable;
protected $fillable = [
'name',
'first_name',
'last_name',
'email',
'password',
'activated',
'token',
'signup_ip_address',
'signup_confirmation_ip_address',
'signup_sm_ip_address',
'admin_ip_address',
'updated_ip_address',
'deleted_ip_address',
];
protected $hidden = [
'password', 'remember_token',
];
protected $casts = [
'email_verified_at' => 'datetime',
];
public function hasRole(String $roleName)
{
return $this->roles()->where('name', $roleName)->exists();
}
public function roles()
{
return $this->belongsToMany('App\Models\Role');
}
public function addRole(String $roleName)
{
$role = Role::where('name', $roleName)->first();
if ($role) $this->roles()->save($role);
}
}
You can do it with whereHas() method. it's a way to condition on relation using exists in query
$clients = User::whereHas('roles', function($role) {
$role->where('name', '=', Role::CLIENT);
})->get();
If you want to get the role too, stack the with() method
$clients = User::whereHas('roles', function($role) {
$role->where('name', '=', Role::CLIENT);
})->with(['roles' => function($role) {
$role->where('name', '=', Role::CLIENT);
}])->get();
That's because you're trying to call the roles method on the Model class and not the instance, here's how it should be
$clients = Role::whereName('client')->first()->users;

how to get id of table in relationship to use in other table in this relation?

i have relation between Service and Services_Gallery one to many, and i want to use id of Service when i insert new image to Services_Gallery, and this is my Controller:
public function save(Request $request)
{
$this->validate($request,[
'image' => 'required|image|mimes:jpeg,jpg,png,svg|max:1024'
]);
$services_Gallery = new Services_Gallery();
$services_Gallery->image = $request->image->move('Uploads', str_random('6') . time() . $request->image->getClientOriginalName());
$services_Gallery->Service::all(id) = $request->service_id; //The problem here
$services_Gallery->save();
return back();
}
this is my Models:
class Service extends Model
{
protected $table = 'services';
protected $fillable = [
'en_main_title',
'ar_main_title',
'en_sub_title',
'ar_sub_title',
'en_content_title',
'ar_content_title',
'en_content',
'ar_content',
'priority',
];
public function gallery()
{
return $this->hasMany('App\Services_Gallery','service_id');
}
}
class Services_Gallery extends Model
{
protected $table = 'services_galleries';
protected $fillable = [
'image',
'service_id',
];
public function gallery(){
return $this->belongsTo('App\Service','service_id');
}
}
Exapmle:
$modelOfService = Service::where('param_x', $request->service_id)->first();
$id = $modelOfService->id;
Is that you need?

Laravel : Select from two tables where column in table two =value using eloquent

I have two tables
table 1 = NewsCollection
table 2 = NewsConllectionTranslation
here is the models
NewsCollection
class NewsCollection extends \Eloquent
{
use \Dimsav\Translatable\Translatable;
public $translatedAttributes = ['title', 'content'];
public $translationModel = 'NewsCollectionTranslation';
public function newsTrans()
{
return $this->hasMany('NewsCollectionTranslation', 'news_collection_id');
}
}
NewsConllectionTranslation
class NewsCollectionTranslation extends \Eloquent
{
public $timestamps = false;
protected $table = 'news_collection_translations';
protected $fillable = ['title', 'content'];
public function transNews()
{
return $this->belongsTo('NewsCollection', 'news_collection_id');
}
}
and here is the show controller
public function show($title)
{
$news = NewsConllectionTranslation::with('newsTrans')->where('title', $title)->first();
return View::make('portal.news.show', compact('news'));
}
What I need to do is
->where('title', $title)->first();
should be selected from NewsConllectionTranslation and I don't want to lose the translation so I don't want to select from NewsConllectionTrnslation first
You should try this:
$news = NewsConllectionTranslation::whereHas('newsTrans', function ($query) use ($title) {
$query->where('title', $title);
})->first();
Change your function like this
public function show($title)
{
$news = NewsConllectionTranslation::with(['newsTrans' => function ($query) use($title) {
$query->where('title', $title)->first();
}])
return View::make('portal.news.show', compact('news'));
}

Laravel 5 Eloquent hasMany relation returns array:1[0 => null]

I have the following classes as models:
class WorkOrder extends Model {
protected $connection = 'qcmms-epdevl';
protected $primaryKey = "workorder-id";
public $table = "PUB.pm-work-card";
public function jobs(){
return $this->hasMany('pm-work-job', 'workorder-id', 'workorder-id');
}
}
class WorkJobs extends model {
protected $connection = 'qcmms-epdevl';
protected $table = "PUB.pm-work-job";
protected $primaryKey = "workjob-id";
}
(*) There is a field "workorder-id" in this table.
WorkorderController is as follows:
class WorkorderController extends Controller {
private $repo;
public function __construct(WorkOrderRepository $repo)
{
$this->repo = $repo;
}
public function artisan()
{
$workorders = $this->repo->getArtisanRecords();
foreach ($workorders as $workorder){
$data = array($workorder->jobs);
app('debugbar')->warning($data);
}
}
}
And the WorkorderRepository is like this:
class WorkOrderRepository
{
public function __construct(WorkOrderModel $workOrderModel)
{
$this->model = $workOrderModel;
}
public function getArtisanRecords()
{
$user = \Auth::user()->getAttribute('emp-id');
return ($this->model->select(
'pm-work-card.wo-number',
'pm-work-card.wo-initial-date',
'pm-work-card.emp-id',
'pm-work-card.workorder-id',
'pm-assets.asset-no',
'pm-assets.asset-desc',
'pm-employee.emp-name',
'pm-employee.emp-surname',
'sys-code.cde-desc',
'pm-work-spares.qty-used'
)
->join('PUB.' . 'pm-assets' , function($join)
{
$join->on('pm-assets.asset-number-id', '=', 'pm-work-card.asset-number-id');
})
->leftjoin('PUB.' . 'pm-employee' , function($join2)
{
$join2->on('pm-employee.emp-id', '=', 'pm-work-card.emp-id')
;
})
->join('PUB.' . 'sys-code' , function($join3)
{
$join3->on('pm-work-card.wo-status', '=', 'sys-code.tab-cde')
->where('sys-code.tab-no', '=', 9300);
})
->leftjoin('PUB.' . 'pm-work-spares' , function($join4)
{
$join4->on('pm-work-spares.workorder-id', '=', 'pm-work-card.workorder-id')
;
})
->where('pm-work-card.emp-id', '=', $user)
->where(function($query){
$query->where('pm-work-card.wo-status', '=', 'O')
->orwhere('pm-work-card.wo-status', '=', 'S');
})
->orderBy('wo-number', 'desc')
->get());
}
The problem I have is that $data returns arrays of null while $workorders in returns all the correct data in the controller.
I need this (mobile ability) to work without renaiming fields to Laravel's spec as the app is already deployed.(Dashes is used and not underscores)
I am new to Laravel & PHP and any help will be appreciated.

Categories