Laravel current id from query results - laravel

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

laravel eloquent with return only same column values

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 );

Get Data through relation in laravel

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.

how to join table in laravel

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
];
});

Different relation by condition

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

Laravel: get data from variouos tables based on optional conditions

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();

Resources