I have table name payments in this table each row has column named paid which is boolean. When I try to get separate list of paid and unpaid rows based on this paid column it just return all rows regardless.
Code
Get unpaid rows
$purchases = Payment::wherePaid(false)
->where('employee_id', $user->id)
->orWhere('employer_id', $user->id)->with([
'employer',
'employee' => function($q) {
$q->select(['id', 'first_name', 'last_name']);
},
'template',
'training',
'contract',
])->get();
Get paid rows
$purchases = Payment::wherePaid(true)
->where('employee_id', $user->id)
->orWhere('employer_id', $user->id)->with([
'employer',
'employee' => function($q) {
$q->select(['id', 'first_name', 'last_name']);
},
'template',
'training',
'contract',
])->get();
Model
protected $casts = [
'paid' => 'boolean',
];
In both queries I am getting array of 4 which is include 3 unpaid and 1 paid row.
Update
Schema
public function up()
{
Schema::create('payments', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('employer_id')->nullable();
$table->unsignedBigInteger('employee_id')->nullable();
$table->unsignedBigInteger('template_id')->nullable();
$table->unsignedBigInteger('contract_id')->nullable();
$table->unsignedBigInteger('training_id')->nullable();
$table->string('duration')->nullable();
$table->string('amount');
$table->boolean('paid')->default(false);
$table->string('booking_id')->nullable();
$table->string('invoice_no');
$table->timestamps();
});
Schema::table('payments', function (Blueprint $table) {
$table->foreign('employer_id')->references('id')->on('users')->onDelete('cascade');
$table->foreign('employee_id')->references('id')->on('users')->onDelete('cascade');
$table->foreign('template_id')->references('id')->on('contract_templates')->onDelete('cascade');
$table->foreign('contract_id')->references('id')->on('contracts')->onDelete('cascade');
$table->foreign('training_id')->references('id')->on('trainings')->onDelete('cascade');
});
}
I may be wrong, but I think your issue is that you are asking for paid = false AND employee_id = ID OR employer_id = ID. I think MySQL is thinking:
(paid = false AND employee_id = ID) OR (employer_id = ID)
So, try this query instead:
$purchases = Payment::wherePaid((false or true))
->where(function ($query) use ($user) {
return $query->where('employee_id', $user->id)
->orWhere('employer_id', $user->id)
})
->with([
'employer',
'employee' => function($query) {
return $query->select(['id', 'first_name', 'last_name']);
},
'template',
'training',
'contract',
])
->get();
That will change the query to:
(paid = false or true) AND (employee_id = ID OR employer_id = ID)
Related
I want to insert tags in Tags table as well as post_tag table from post creating page. When i create a new post tags are inserting in Tags table but not inserting in post_tag tablbe. it is showing Invalid datetime format.
SQLSTATE[22007]: Invalid datetime format: 1366 Incorrect integer value: 'start,tas' for column anusondhan.post_tag.tag_id at row 1 (SQL: insert into post_tag (post_id, tag_id) values (20, start,tas))
//Store Post
public function storeNewPost(Request $request){
//return $request->all();
$request->validate([
'post_title' => 'required',
'post_details' => 'required',
'category_id' => 'required',
'image' => 'image|max:15360|dimensions:max_width=4000,max_height=3000'
]);
$image = $request->file('post_thumbnail');
$name_gen=uniqid().'.'.$image->getClientOriginalExtension();
Image::make($image)->resize(700,400)->save('frontend/assets/images/post/'.$name_gen);
$save_url = 'frontend/assets/images/post/'.$name_gen;
$post = Post::create([
'user_id' => Auth::id(),
'post_uper_title' =>$request->post_uper_title,
'post_title' =>$request->post_title,
'post_sub_title' =>$request->post_sub_title,
'post_details' =>$request->post_details,
'post_slug' =>str_replace(' ', '-', $request->post_title),
'seo_title' =>$request->seo_title,
'seo_descp' =>$request->seo_descp,
'lead' =>$request->lead,
'lead2' =>$request->lead2,
'featured' =>$request->featured,
'repoter_name' =>$request->repoter_name,
'division_id' =>$request->division_id,
'district_id' =>$request->district_id,
'category_id' =>$request->category_id,
'post_thumbnail' =>$save_url,
'thumbnail_caption' =>$request->thumbnail_caption,
'thumbnail_alt' =>$request->thumbnail_alt,
'created_at' => Carbon::now(),
]);
if($post){
$tags = explode(",", implode($request->tags));
$tagNames = [];
if (!empty($tags)) {
foreach ($tags as $tagName)
{
$tag = Tags::firstOrCreate(['name'=>$tagName]);
if($tag)
{
$tagNames[] = $tag->id;
}
}
}
$post->tags()->sync($request->tags);
$notification = array(
'message' => 'Post Inserted Successfully',
'alert-type' => 'success'
);
return redirect()->route('all.posts')->with($notification);
}else{
return back();
}
}//end insert post
** Here is my Tags table **
public function up()
{
Schema::create('tags', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('slug')->nullable();
$table->longText('description')->nullable();
$table->longText('tag_thumb')->nullable();
$table->text('thumb_caption')->nullable();
$table->text('thumb_alt')->nullable();
$table->softDeletes();
$table->timestamps();
});
}
** Here is my Post_tag Table **
public function up()
{
Schema::create('post_tag', function (Blueprint $table) {
$table->increments('id');
$table->unsignedBigInteger('post_id')->nullable();
$table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade');
$table->unsignedBigInteger('tag_id')->nullable();
$table->foreign('tag_id')->references('id')->on('tags')->onDelete('cascade');
$table->timestamps();
});
}
I think you need to use $tagNames array instead of $request->tags when syncing:
$post->tags()->sync($tagNames);
As per the Laravel documentation, the sync() method expects an array of IDs:
https://laravel.com/docs/8.x/eloquent-relationships#syncing-associations
If you have manyToMany relation in your models use sync() method on update function in your controller.
Example: $post->tags()->sync($request->tags);
If you need more help tell me.
I am beginner webdeveloper.
I have small problem my model.
I have this migration and model:
Schema::create('stopwatches', function (Blueprint $table) {
$table->increments('id');
$table->integer('case_id')->unsigned();
$table->foreign('case_id')->references('id')->on('case_instances')->onDelete('cascade');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
});
Schema::create('timecycles', function (Blueprint $table) {
$table->increments('id');
$table->integer('timecycleable_id');
$table->string('timecycleable_type');
$table->integer('case_id')->unsigned();
$table->foreign('case_id')->references('id')->on('case_instances')->onDelete('cascade');
$table->boolean('status')->default(0);
$table->integer('worked_time')->default(0);
$table->timestamps();
});
class Stopwatch extends Model
{
protected $fillable = [
'case_id',
'user_id'
];
protected $casts = [
'id' => 'int',
'case_id' => 'int',
'user_id' => 'int',
];
protected $dates = [
'created_at',
'updated_at'
];
public function timeCycle()
{
return $this->morphMany(Timecycle::class, 'timecycleable');
}
public function caseInstance()
{
return $this->belongsTo(CaseInstance::class, 'case_id');
}
class Timecycle extends Model
{
protected $fillable = [
'case_id',
'timecycleable_id',
'timecycleable_type',
'status',
'worked_time'
];
protected $casts = [
'id' => 'int',
'case_id' => 'int',
];
protected $dates = [
'created_at',
'updated_at'
];
public function stopwatch()
{
return $this->morphTo();
}
}
In timecycles I have 2 record with status = 0 and status = 1: https://ibb.co/5vyh316
I need my stopwatches with only one timecycles with status = 1.
I make this code:
return $this->stopwatch::with(['timeCycle', 'caseInstance'])
->where('user_id', Auth()->user()->id)
->where('updated_at', '<=', \Carbon\Carbon::now()->subSeconds(30)->toDateTimeString())
->whereHas('timeCycle', function ($q) {
$q->where('status', 1);
})
->get();
In result I have booth items: https://ibb.co/WnJ58Kc
What's wrong in my code?
How can I repair it?
Please help me.
You're actually quite close, but whereHas() doesn't affect the loaded records. Use the same clause on your with() statement:
return $this->stopwatch::with(['timeCycle' => function ($q) {
$q->where('status', 1); // If you only want 1, you can do `->limit(1)` as well
}, 'caseInstance'])
->where('user_id', Auth()->user()->id)
->where('updated_at', '<=', \Carbon\Carbon::now()->subSeconds(30)->toDateTimeString())
->whereHas('timeCycle', function ($q) {
$q->where('status', 1);
})
->get();
Now, when looping over your data, each $record->timeCycle will only include whatever is specified in the with() clause.
It's likely the problem is generated by the with('timeCycle') clause. If you want to constraint your query by a relation, you need to specified it in both the whereHas and the with(), otherwise the eager loading will fetch all the elements making the whereHas irrelevant. Try this:
return $this
->stopwatch::with([
'caseInstance',
'timeCycle' => function ($query) {
$query->where('status', 1);
}
])
->where('user_id', Auth()->user()->id)
->where('updated_at', '<=', now()->subSeconds(30)->toDateTimeString())
->whereHas('timeCycle', function ($query) {
$query->where('status', 1);
})
->get();
Of course, given both constraints are equal, you could store it in a variable and pass it to both methods:
$timeCycleContraint = function ($query) {
$query->where('status', 1);
};
return $this
->stopwatch::with([
'caseInstance',
'timeCycle' => $timeCycleContraint
])
->where('user_id', Auth()->user()->id)
->where('updated_at', '<=', now()->subSeconds(30)->toDateTimeString())
->whereHas('timeCycle', $timeCycleContraint)
->get();
Db schema
users
-id
-name
-email
...
roles
-id
-name
User may have multiple roles and vice-versa (i already defined
relationships in models)
pivot table
role_user
-id
-user_id
-role_id
Validation rule trying to make: user_id must exist in users table and has role id = 4
//...
'user_id' => ['nullable', Rule::exists('users')->where(
function ($query) {
$query->whereHas('roles',
function ($q) {
$q->where('id', 4);
}
);
}
)],
//...
Error message : "SQLSTATE[42S22]: Column not found: 1054 Unknown
column 'has' in 'where clause' (SQL: select count(*) as aggregate from
users where user_id = 0 and (has = roles))"
I would use this. This will solve your problem, but i don't know either is the best way or not.
use Validator; // on the top
$validator = Validator::make($request->all(), [
'user_id' => 'nullable|numeric|exists:users,id',
]);
if ($validator->fails()) {
return response()->json($validator->errors(), 422);
}
$user = User::find($request->user_id);
if(!$user || !$user->roles->first() || $user->roles->first()->id != 4) {
return response()->json(['user_id'=>['You dont have permission.']], 422);
}
Another way you can try
'user_id' => [
'nullable',
'numeric',
'exists:users,id',
function ($attribute, $value, $fail) {
$editorsIDs = User::whereHas('roles', function ($q) {
$q->where('id', 4);
})->pluck('id');
if(! $editorsIDs->contains($value)) {
$fail('You dont have permission.');
}}
]
I resolve it using
$usersWhereHasEditorRole = User::whereHas('roles', function ($q) {
$q->where('id', 4);
})->pluck('id')->unique('id')->toArray();
$validator = Validator::make($request->all(), [
'name' => 'required|alpha', // commun
'email' => 'required|email|unique:users', // commun
'password' => 'required|min:8|regex:/[a-z]/|regex:/[A-Z]/|regex:/[0-9]/|regex:/[#$!%*#?&]/', // commun
'c_password' => 'required|same:password', // commun
//...
'user_id' => ['nullable', Rule::in($usersWhereHasEditorRole)],
//...
]);
if ($validator->fails()) {
return $this->sendError('Validation Error.', $validator->errors(), 400);
}
dd('passes');
Hi I have more than 500k records in items table Its takes more than 9 seconds to execute this query ineed to make it milliseconds to execute this query using mysql index
$products = \App\items::with([
'item_store' => function($query) {
$query->select('size', 'item_id', 'item_store_id');
},
'pics' => function($query) {
$query->select('img_url', 'item_id');
},
'brand' => function($query) {
$query->select('item_id', 'brand_id');
},
'brand.brand' => function($query) {
$query->select('brand_id', 'brand_name');
}
])
->select('item_id', 'short_name', 'price', 'price_above')
->orderBy('Price', 'Asc')->whereIn('category_id', $arr)
->groupBy('Sku')
->paginate(20);
my database structure is [st] https://screenshots.firefox.com/JAmaKENMYRhQkEjx/ourweds.com
this is item table migration
Schema::create('item', function (Blueprint $table) {
$table->bigIncrements('item_id');
$table->string('item_name');
$table->integer('Sku');
$table->text('Description');
$table->text('short_description');
$table->text('category_id');
$table->string('color');
$table->double('price');
$table->double('indian_price');
$table->string('old_price');
$table->string('indian_old_price');
$table->timestamps();
});
item eloquent model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class items extends Model
{
//
protected $table = 'items';
protected $primaryKey = 'item_id';
protected $fillable = [
'category_id',
'item_name',
'Sku',
'Description',
'short_description',
'color',
'kik_cash_percentage',
'status',
'price',
'price_old',
'indian_price',
'short_name',
'price_above',
'short_name_alter',
'availability'
];
public function pics(){
return $this->hasOne( 'App\item_pics', 'item_id' );
}
public function item_store()
{
return $this->hasMany('App\item_store','item_id');
}
public function category()
{
return $this->belongsTo('App\categories','category_id');
}
public function brand()
{
return $this->hasOne('App\item_has_brand','item_id');
}
}
So I have a user table, a role table and an intermediate table for those 2, user_role. It's a many-to-many relationship between the first 2 tables.
I want to return the count of the users which have a specific role but I can't seem to get it right.
My migrations:
user:
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->string('email')->unique();
$table->string('username')->unique();
$table->string('password');
});
role:
Schema::create('roles', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->string('name', 40);
$table->string('description', 255);
});
user_role:
Schema::create('user_role', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->integer('user_id');
$table->integer('role_id');
});
Relationship between them:
public function users(){ //in role model
return $this->belongsToMany('App\User', 'user_role', 'role_id', 'user_id')->withTimestamps();
}
public function roles(){ //in user model
return $this->belongsToMany('App\Role', 'user_role', 'user_id', 'role_id')->withTimestamps();
}
Role Seeder:
public function run()
{
Role::create([
'id' => 1,
'name' => 'Admin',
'description' => 'Admin User.'
]);
Role::create([
'id' => 2,
'name' => 'Vendor',
'description' => 'Vendor User.'
]);
Role::create([
'id' => 3,
'name' => 'User',
'description' => 'Simple User.'
]);
}
in controller:
public function adminDashboard(){
$users = User::all();
return view('admin.dashboard')->withUsers($users);
}
in view:
{{ $users->count() }}
This obviously, returns the total count of users in user table. Any ideas on how to return the count of users which have a specific role?
use $role->users()->count()
To iterate over the roles and display the count of users, you can use this:
public function adminDashboard(){
$roles = App\Role::all();
return view('admin.dashboard', compact('roles'));
}
In your dashboard view:
#foreach ($roles as $role)
<p>Role {{ $role->name }} has {{ $role->users()->count() }} users</p>
#endforeach