I have a problem I try to get list of posts with trashed posts through Resource API. Code example here
public function index(Request $request)
{
$perPage = (int) $request->get('per_page');
if ($perPage < 1 or $perPage > 1000) {
$perPage = config('database.paginate');
}
$clubId = (int)$request->get('club');
$query = Playground::query();
if ($clubId) {
$query = $query->where('club_id', $clubId);
}
return PlaygroundResource::collection($query->paginate($perPage));
}
I cant add ->withTrashed() method in collection, So how can i get all posts???
UPD::
Playground Model
protected $fillable = [
'slug',
'name',
'club_id',
'links',
'playground_types',
'services',
'equipments',
'surfaces',
'sports',
'type',
'description'
];
protected $dates = ['deleted_at'];
Have you tried putting the ->withTrashed() behind the $query? For example right after you define it?
$query = Playground::query();
$query->withTrashed();
Related
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();
}
}
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;
});
I am trying to update my data into my database where the relationship is that I have many schools, so when I try to save inside my database, I want to get something like this:
[![enter image description here][1]][1]
But I only know how to use implode function to do it, and I can only make it like this:
I tried doing this but it doesn't work:
public function update1(Request $request, $user_id){
$rows = qualification::where('user_id', $user_id)->get();
foreach ($rows as $row){
switch ($row['meta_key']){
case 'school_name':
$row['meta_value'] = $request->input('School');
break;
case 'start_date':
$row['meta_value'] = $request->input('SDate');
break;
case 'end_date':
$row['meta_value'] = $request->input('EDate');
break;
case 'qualification_list':
$row['meta_value'] = $request->input('qualification');
break;
}
$row->save();
}
return redirect('/home');
}
When I try using that code it will give me this error, Array to string conversion
PersonalInfo model:
class PersonalInfo extends Eloquent
{
use SoftDeletes;
protected $table = 'personal_infos';
protected $primaryKey = 'id';
protected $dates = ['deleted_at'];
public function userQualifications()
{
return $this->hasMany('App\Qualification','user_id');
}
Qualification model:
class Qualification extends Model
{
protected $table = "qualifications";
public function PersonalInfos() {
return $this->belongsTo('App\PersonalInfo');
}
}
No error message:
Assuming you have your relationship setup properly in your User model, you could try something like this (not tested):
public function update1(Request $request, $user_id){
// get the user
$user = PersonalInfo::find($user_id);
// create the new array of meta data
$data = array();
// loop through the inputs array count
for($i=0; $i < count($request->input('School')); $i++) {
$data[] = [
'meta_key' => 'school_name',
'meta_value' => $request->input('School')[$i]
];
$data[] = [
'meta_key' => 'start_date',
'meta_value' => $request->input('SDate')[$i]
];
$data[] = [
'meta_key' => 'end_date',
'meta_value' => $request->input('EDate')[$i]
];
$data[] = [
'meta_key' => 'qualification_list',
'meta_value' => $request->input('qualification')[$i]
];
}
// create the relationships
$user->userQualifications()->createMany($data);
return redirect('/home');
}
I have a project that has a project model which looks like this:
class Product extends Model
{
public $timestamps = true;
protected $guarded = ['id'];
protected $table = 'products';
protected $hidden = ['created_at', 'updated_at'];
protected $fillable = ['name', 'category_id', 'units', 'b_price', 's_price', 'warn_count', 'added_by'];
public function category()
{
return $this->belongsTo('App\Category');
}
public function stock(){
$product_id = $this->id;
$filter = ['product_id' => $product_id];
//STOCK PLUS
//credit purchases
$cr_purchases = CreditPurchase::where($filter)->sum('qty');
//purchases
$purchases = Purchase::where($filter)->sum('qty');
//returns in
$re_in = ReturnIn::where($filter)->sum('qty');
//STOCK MINUS
//credit sales
$cr_sales = CreditSale::where($filter)->sum('qty');
//sales
$sales = Sale::where($filter)->sum('qty');
//returns out
$re_out = ReturnOut::where($filter)->sum('qty');
//damaged
$damaged = DamagedProduct::where($filter)->sum('qty');
return $cr_purchases + $purchases + $re_in - ($cr_sales + $sales + $re_out + $damaged);
}
}
As can be seen stock is a calculated value for each model. I wish to make queries based on it as though it were a column of the products table.
Method 1
Change the stock method to be an Laravel model accessor.
public function getStockAttribute(){
//code logic
}
Fetch the results as a Collection and perform filters on the 'stock; attribute
I would do something like.
Products::where('product','like','miraa') //where
->get()
->filter(function($item) {
return $item->stock > 100;
});
Read about filtering collections
Method 2
Use dynamic query scopes
See scopes in laravel.
public function scopeAvailbaleStock($query, $type)
{
return $query->where('type', $type);
// could perform filters here for the query above
}
Fetch using scope
$users = Products::available_stock()->get();
Method 3
I saw out this package jarektkaczyk/eloquence
public function scopeWhereStock($query, $price, $operator = '=', $bool = 'and'){
$query->where('info1', $operator, $price, $bool);
}
// then
Products::whereStock(25); // where('info1', 25);
Products::whereStcok(25, '>'); // where('info1', '>', 25);
Products::whereStock(25, '=', 'or'); // orWhere('info1', 25);
Howerever, i would recomend to use method 1 or 2. The 3rd solution works but not sure if it is the best
I solved it by overriding $appends on the model and using an accessor for the stock field. So that the model now looks like:
class Product extends Model
{
public $timestamps = true;
protected $guarded = ['id'];
protected $table = 'products';
protected $hidden = ['created_at', 'updated_at'];
protected $fillable = ['name', 'category_id', 'units', 'b_price', 's_price', 'warn_count', 'added_by'];
protected $appends = ['stock'];
public function category()
{
return $this->belongsTo('App\Category');
}
public function getStockAttribute(){
$product_id = $this->id;
$filter = ['product_id' => $product_id];
//STOCK PLUS
//credit purchases
$cr_purchases = CreditPurchase::where($filter)->sum('qty');
//purchases
$purchases = Purchase::where($filter)->sum('qty');
//returns in
$re_in = ReturnIn::where($filter)->sum('qty');
//STOCK MINUS
//credit sales
$cr_sales = CreditSale::where($filter)->sum('qty');
//sales
$sales = Sale::where($filter)->sum('qty');
//returns out
$re_out = ReturnOut::where($filter)->sum('qty');
//damaged
$damaged = DamagedProduct::where($filter)->sum('qty');
return $cr_purchases + $purchases + $re_in - ($cr_sales + $sales + $re_out + $damaged);
}
}
I built this solution on #samueldervis answer. A simple example can be seen here: http://laraveldaily.com/why-use-appends-with-accessors-in-eloquent/
How do I query more than two tables. What I want to do is have a list of products queryed by a genre and then query productvariations - where a product variation has a producttype_id = $producttype->id
Route::get('browse/{producttype_slug}/{genre_slug}', array(
'as' => 'products.viewbygenre',
function($productype_slug, $genre_slug)
{
$producttype = ProductTypes::where('slug', '=', $productype_slug)->firstOrFail();
$genre = GenreTypes::where('slug', '=', $genre_slug)->firstOrFail();
// error below
$products = Product::with(array('ProductVariations', 'GenreTypes'))
->where('genre', '=', $genre->id)->get();
return View::make('products.viewbygenre')->with(compact('productvariations', 'genre', 'producttype'));
}))->where('producttype_slug', '[A-Za-z\-]+')->where('genre_slug', '[A-Za-z\-]+');
products class
class Product extends \Eloquent {
protected $table = "products";
protected $fillable = ['keywords', 'description', 'title', 'slug', 'release_date', 'clip'];
public function productvariations() {
return $this->hasMany("ProductVariations");
}
public function variations() {
$variations = $this->productvariations()->get();
return $variations;
}
public function genres() {
return $this->belongsToMany('GenreTypes', 'product_genretypes', 'product_id', 'genretype_id')->withTimestamps();
}
}
I didn't quite understand the issue so I will just refer to this bit:
// error below
$products = Product::with(array('ProductVariations', 'GenreTypes'))
->where('genre', '=', $genre->id)->get();
I believe you cannot use a where clause this way on a 'with' array. I am not 100% sure if this works when you have more than one parameter in your with method but this is worth trying:
$products = \Product::with(array('ProductVariations', 'GenreTypes' => function ($query)
{
// Note I think you also had a mistake in your column name
// (genre should be genretype_id?)
// Also ... not sure how you are getting the $genre->id variable
// as I cannot see the the $genre object / collection in this method you provided !
$query->where('genretype_id', '=', $genre->id);
}))->get();
Let us know how you get on.