I create a scope function like this:
scopeSearch($query, $input)
{
$query->orWhere('title' , 'LIKE' , '%' . $input['q'] . '%')
retrun $query;
}
top function return a list of results in articles table.
articles table structure:
id | title | parent_id
1 title1 null
2 title2 1
3 title3 null
I want return all records that they do not have any child and parent_id is null!
for example in top example I only want return third record (id=3).
I know I must try something like this (I define articles() in Article model before)
$query->whereHas('articles' , function ($query) use ($id){$query->where('parent_id' , $id );})
but I do not know how can I get right $id to insert in top code to return right results.
EDIT
public function articles()
{
return $this->hasMany(Article::class , 'parent_id' , 'id');
}
public function childArticles()
{
return $this->belongsTo(Article::class , 'parent_id' , 'id');
}
Create a relationship with child articles too.
$query->doesnthave('articles','childArticles')->get();
Hope this helps.
Related
This is a little complex for me,so I decided to get some help.
Taxonomy has :
public function products()
{
return $this->belongsToMany(
Product::class,
'term_relationships',
'term_taxonomy_id',
'object_id'
);
}
And Product has :
public function taxonomies()
{
return $this->belongsToMany(
Taxonomy::class,
'term_relationships',
'object_id',
'term_taxonomy_id'
);
}
This will select all products with all its taxonomies where taxonomy starts with pa_.
\Corcel\WooCommerce\Model\ProductCategory::find(401)->products()->with(['taxonomies'=> function ($query) {
$query->where('taxonomy', 'like', "pa_%");
}])->get(['ID'])->makeHidden(['pivot']);
All I want is to select only taxonomies which all have the same taxonomy column value.
like they all have : taxonomy -> pa_shirt_size and taxonomy -> pa_shirt_color
Here's the sql output of eloquent :
select * from `wp_posts` inner join `wp_term_relationships` on `wp_posts`.`ID` = `wp_term_relationships`.`object_id`
where `post_type` = 'product' and `wp_term_relationships`.`term_taxonomy_id` = 401 and exists (select * from
`wp_term_taxonomy` inner join `wp_term_relationships` on `wp_term_taxonomy`.`term_taxonomy_id` =
`wp_term_relationships`.`term_taxonomy_id` where `wp_posts`.`ID` = `wp_term_relationships`.`object_id` and `taxonomy`
like 'pa_%')
So I think using something like :
group by `taxonomy` having count(*) = count(wp.posts.ID)
I can get the number of posts and if that is equal to taxonomy count it means we're good.
But how to access wp.posts.ID from the subquery in with function I couldn't find a way yet.
I suggest you get the products' count, then get all the taxonomies that have all the products count:
$Products_count = Product::count();
$sharedTaxomies = Taxonomy::has('products', '=', $Products_count)->get();
note: I suppoe the relation in Taxonomy called products not posts.
first: i think you mean products() instead posts() ?
public function products()
{
return $this->belongsToMany(
Product::class,
'term_relationships',
'term_taxonomy_id',
'object_id'
);
}
Secound: if you have access to products like:
$products = Product::all();
you can after iterate the $products and you have access to the taxonomies like:
print_r( $products[0]->taxonomies );
I'm using this query to get data using relation
return Product::with('attributes')
->whereHas('attributes', function ($query) use ($attribute_id,$attribute_value){
$query->whereIn('attribute_id', $attribute_id);
$query->whereIn('value', $attribute_value);
})
->paginate(10);
$attribute_id and $attribute_value are arrays, i'm getting data using this relation but when $attribute_id and $attribute_value are empty then i'm not getting any result but it should return result through product table if there are no attributes.
I have changed it to something like this:
if(!empty($attribute_id))
{
$query->whereIn('attribute_id', $attribute_id);
}
if(!empty($attribute_value))
{
$query->whereIn('value', $attribute_value);
}
model relation :
public function attributes()
{
return $this->hasMany(ProductsAttribute::class, 'product_id ');
}
Table:
id | Title | Price
1 Title 1 5000
2 Product 2 7000
this is related to product_attribute table
id | product_id | attribute_id | attribute_name | value
1 1 5 Color Red
2 1 6 Size XL
3 2 5 Color Green
Is there any other way to make a check in query so that if attributes are not provided then atleast product data should return.
A cleaner way might be to use local scopes. That way, your controllers will look cleaner. It also makes the code easily testable. Here is how I might approach this.
NOTE: Code hasn't been tesed.
In your controller:
return Product::with([
'attributes' => function ($query) use ($attribute_id, $attribute_value) {
return $query->inAttributeId($attribute_id)
->inAttributeValue($attribute_value);
}
])->paginate(10);
In your ProductsAttribute model:
public function scopeInAttributeId($query, $attributeId)
{
if (empty($attributeId)) {
return $query;
}
return $query->whereIn('attribute_id', $attributeId);
}
public function scopeInAttributeValue($query, $attributeValue)
{
if (empty($attributeValue)) {
return $query;
}
return $query->whereIn('value', $attributeValue);
}
As you can see, the scopes modify the query only if there are values in the passed in array. If the passed in array is empty, it returns the original query.
I have 2 tables
lets say the 1st one have something like id_teacher_a, id_teacher_b
the 2nd table have the detailed information from table 1 (teacher name, teacher address, etc)
i want to show only the teacher name, so how to join them?
my controller
$data['getid'] = Classroom::select(
'classroom.id',
'teacher.id as tchr_id',
'teacher.name as tchr_name'
)
->join('teacher', 'classroom.teacher_id', '=', 'teacher.id')
->first();
when i want to show table of classroom it would be like
#classroom id #teacher_name_a #teacher_name_b
1 a b
The following should work just fine:
DB::table('classrooms')
->join('teacher as ta', 'ta.id', '=', 'classrooms.id_teacher_a')
->join('teacher as tb', 'tb.id', '=', 'classrooms.id_teacher_b')
->select([
'classrooms.id as classroom_id',
'ta.name as teacher_name_a'
'tb.name as teacher_name_b'
])->get();
Alternatively if you have the following to your Classroom model:
class Teacher extends Model
{
public function teacherA()
{
return $this->belongsTo(Teacher::class, 'id_teacher_a');
}
public function teacherB()
{
return $this->belongsTo(Teacher::class, 'id_teacher_b');
}
}
Then you can also do:
Classroom::query()
->with(['teacherA', 'teacherB'])
->map(function ($classroom) {
return [
'classroom id' => $classroom->id,
'teacher_name_a' => $classroom->teacherA->name,
'teacher_name_b' => $classroom->teacherB->name
];
});
I have the table followers, with:
id, user_id, follower_id, type
type = type of follow, if follow user = 0, page = 1, group = 1
I use the user_id to put the page_id and group_id too.
Now is the problem, I want to make different relations if type is different... If type = 0, will relate with users table and share table, if type = 1, will relate with pages table...
I'm try like this:
Model:
public function page_links()
{
return $this->hasMany(Link::class, 'page_id', 'user_id')->Select('links.id', 'links.title', 'links.photo', 'links.country', 'links.friendly_url', 'links.clicks', 'links.description', 'links.suggestions', 'links.count_comments', 'links.url', 'links.shares', 'links.page_id', 'links.tag_id', 'links.created_at')->where('sponsored', 0)->where('scheduled', 0)>where('status', 1)->take(3)->orderBy('id','desc');
}
public function user_links()
{
return $this->hasMany(Share::class, 'user_id', 'user_id')->Select('id', 'link_id', 'user_id', 'shared_in', 'content', 'created_at')->take(3)->orderBy('id', 'desc')->where('type', '=', 0);
}
public function scopeProfile($query) {
return $query
->when($this->type == 0, function($q){
return $q->with('user_links');
})
->when($this->type == 1, function($q){
return $q->with('page_links');
})
->when($this->type == 2, function($q){
return $q->with('group_links');
});
}
Controller:
$feed = Feed::Profile()->where('follower_id', auth()->user()->id)
->take(10)
->get();
But ALL, even the type 1 returns "user_links" relation. I don't know if the relation is correct...
Someone can help me?
Well, in my point of view, you should modify your migration.
Instead of have your table with :
id, user_id, follower_id, type
I'll do this :
id, user_id, page_id, group_id, follower_id, type
Don't do weird stuffs like that in your database, just add 2 fields and / or relations in your migration table. Set it to unsigned() AND nullable(), this way you'll be able to know quickly if there is a relation or not with each one of your page or group, and you won't have to make weird stuff to check for it :D
I want to write a query based on optional condition that will fetch data from different tables. My schema looks like
myboxes Table
id,
type_id --> foreign key to box_type table
postal_code
po_box
created_at
updated_at
mybox_access table
id
mybox_id -> foreign key to myboxes table
email
box_type table
id
type_name
And here are my models
MyBox.php
class MyBox extends Model {
public function type() {
return this->hasOne(BoxType::class, 'id', 'type_id');
}
public function access() id
return this->hasOne(MyBoxAccess::class, 'mybox_id', 'type_id');
}
}
MyBoxType.php has following relation ship
public function mybox() {
return this->hasOne(MyBox::class, 'id', 'type_id');
}
And MyBoxAccess.php has following relationship
public function vbox() {
return $this->belongsTo(MyBox::class, 'id', 'mybox_id');
}
Now I want to get based on following condition
I have email as required param and postal_code and po_box as optional params (but one of them will be must and both can also be present).
So I want to get data of all my_boxes that have type_id 3 OR all myboxes whoes id matches to email in mybox_access table AND postal_code or po_box matches to params in myboxes table
For simple match of params postal code and po_box I can write some thing like
$result = new MyBox();
if(!empty($request['postal_code'])) {
$result->where('postal_code', like, '%'.$request['postal_code']);
}
if(!empty($request['po_box'])) {
$result->where('po_box', like, '%'.$request['po_box']);
}
$result = $result->get();
But I don't know how to get data for above mentioned condition. When I try to do using with() like
MyBox::with(['access' => function(Builder $query) use ($request){
$query->where('mybox_id',$request['id']);
}])->get();
I get
`Argument 1 Passed to {closure} () must be an instance of Illuminat\Database\Query\Builder, instance of Illuminate\Databaase\Eloquent\Relation\HasOne given`
Can any body please let me know how can I get data based on above mentioned condition
$query is a relationship, not a builder instance.
So this should not throw any Exception.
MyBox::with(['access' => function ($query) {
$query->where('mybox_id', $request['id']);
}])->get();
But I don't think it'd resole your issue because your Box <=> Access relationship is not right. It should be HasMany.
// MyBox.php
public function type()
{
return $this->hasOne(BoxType::class, 'id', 'type_id');
}
public function access()
{
return $this->hasMany(MyBoxAccess::class, 'mybox_id', 'id');
}
Then in your Controller you could do this.
// $results where type_id is 3
$results = MyBox::where('type_id', 3)->get();
// List of boxes accessible by email
$results = MyBox::whereHas('access', function ($query) {
$query->where('email', request()->input('email'));
})->get();
// Results where postal_code and po_box matches the request
$results = MyBox::with('access')->where(function ($query) {
if (request()->has('postal_code')) {
$query->where('postal_code', 'like', '%' . request()->input('postal_code'));
}
if (request()->has('po_box')) {
$query->where('po_box', 'like', '%' . request()->input('po_box'));
}
})->get();
And if you want to merge all conditions:
$results = MyBox::where(function ($query) {
if (request()->has('type_id')) {
$query->where('type_id', request()->input('type_id'));
}
if (request()->has('email')) {
$query->whereHas('access', function ($query) {
$query->where('email', request()->input('email'));
});
}
if (request()->has('postal_code')) {
$query->where('postal_code', 'like', '%' . request()->input('postal_code'));
}
if (request()->has('po_box')) {
$query->where('po_box', 'like', '%' . request()->input('po_box'));
}
})->get();
I always use the request() facade when using in closures, it feels cleaner to me.
Try this query:
MyBox::with('access')->get();