Here is my table structures:
// tickets
+----+------------+----------------------+--------+---------+
| id | subject | content | closed | user_id |
+----+------------+----------------------+--------+---------+
| 1 | subject1 | question1 | 0 | 123 |
+----+------------+----------------------+--------+---------+
// answers
+----+----------------------+---------+-----------+
| id | content | user_id | ticket_id |
+----+----------------------+---------+-----------+
| 1 | answer1 | 123 | 1 |
| 2 | answer2 | 456 | 1 |
+----+----------------------+---------+-----------+
Now I need to get a ticket with along all its answers. I can do that using pure SQL like this:
SELECT t.*, a.*
FROM tickets t
LEFT JOIN answers a
ON t.id = a.ticket_id
WHERE t.id = ?
Now I'm using Laravel and I want to do that using with() class (however not sure it is possible). Any idea what change should I make in the models for doing that?
Noted that I can get just a ticket in Laravel like this:
$ticket = Tickets::where('id', $request->id)->get();
First make a hasMany() relationship in your Tickets model class.
public function answers()
{
return $this->hasMany(Answers::class, 'ticket_id', 'id');
}
And then in your controller query
$tickets = Tickets::with('answers')->where('id', $request->id)->get();
Related
I have 4 tables named: categories, products, blogs, companies.
+-----------+
| Category |
+----+------+
| id | name |
+----+------+
| 1 | Cat1 |
| 2 | Cat2 |
+----+------+
+-----------+
| Company |
+----+------+
| id | name |
+----+------+
| | |
+----+------+
+-------------------------+
| Product |
+----+-------------+------+
| id | category_id | name |
+----+-------------+------+
| 1 | 1 | P1 |
| 2 | 2 | P2 |
| 3 | 1 | P3 |
+----+-------------+------+
+---------------------------+
| Blog |
+----+------------+---------+
| id | product_id | heading |
+----+------------+---------+
| 1 | 1 | H1 |
| 2 | 2 | H3 |
| 3 | 3 | H4 |
+----+------------+---------+
Blog Model
public function product()
{
return $this->belongsTo(Product::class);
}
Product Model
public function company()
{
return $this->belongsTo(Company::class);
}
public function category()
{
return $this->belongsTo(Category::class);
}
Blog::with('product.category')
->where('status', 'Y')
->where('featured_position', 'Y')
->orderBy('id', 'DESC')
->get();
From the above tables the result will show 2 blogs namely blogs having id 1 and 3. But the above code is fetching result for all the blogs from the blog table.
You'll want to use a whereHas to query the relationship.
$categoryId = 1;
$productQuery = function ($query) use ($categoryId) {
// This $query object will be for the Product models, so we can treat it as
// such.
// We can query like we would on a Product, like Product::where([...]).
$query->with('category')->where('category_id', $categoryId);
};
$blogs = Blog::whereHas('product', $productQuery)
->with(['product' => $productQuery])
->get();
I've set the category ID to a variable, in case you need to change it during runtime.
Also, note that the with is completely optional.
If you exclude it, your query will run exactly the same, just without constrained eager loading. The effects of this are just that you will have to perform more database requests. The benefits come if you never actually need the relationship, then it won't have been fetch unnecessarily.
If you're curious what the SQL command will be, it will be:
SELECT * FROM `blogs`
WHERE EXISTS (
SELECT * FROM `products`
WHERE `blogs`.`product_id` = `products`.`id` AND `category_id` = ?
)
In simple terms, it will select everything from the blogs table.
It's then going to query the products table, using an inner join, to select products that have a corresponding blog entry.
The second part of the where clause is going to just get the specific character. The ? is because category_id can be any integer.
Catory with id 1
fetch its products
fetch blogs for each of its products ( map over products )
flatten the results ( since its gonna be nested for each product )
Category::find(1)->products->map->blogs->flatten();
you can use Tinker to interact with you application's query builder and eloquent models from terminal you can use :
$ php artisan tinker
For more clause you can use collection methods :
Category::find(1)->products->map->blogs->flatten()->where('status', 'Y')
->where('featured_position', 'Y')
->sortDesc('id') ;
I have this structure.
class Product extends Model{
public function office()
{
return $this->belongsTo(Office::class,'office_id');
}
}
I want to list products order by office.name.
this is the query
$res = \App\Product::with(['office' => function($q){
$q->orderBy('offices.name','asc');
}])->get();
this is the output loop
foreach($res as $key => $val){
print "<br />user: ".$val->id.", office: ".$val->office->id;
}
this is the Product data:
+----+--------+
| id | name |
+----+--------+
| 1 | Life |
| 2 | Cars |
| 3 | Health |
| 4 | House |
+----+--------+
this is the data in Office
+----+----------------+
| id | name |
+----+----------------+
| 1 | First office |
| 2 | working office |
+----+----------------+
The order by is not affecting the result.
same result, the order by like not existed.
Thanks
In your code you are simply "ordering" the offices by name, which means if each product had many offices, it would sort the offices alphabetically.
To sort (OrderBY()) a collection, the column has to be an attribute of the collection object. One solution could be to Join your models. SOmething like this might help you.
$res = Product::with('office')
->join('offices', 'products.office_id', '=', 'offices.id')
->select('products.*', 'offices.name')
->orderBy('office.name')
->get();
I have tow table first table is posts table and second table is home_posts table so i want to home_posts table (post_id) throw get record in posts table.
I was used hasMany() relationship in post model but not getting any record. I want only home_posts table post id record from posts table. I want home post table to post table record.
Post table
+----+-----------------+
| id | title |
+----+-----------------+
| 1 | Post 1 |
| 2 | Post 3 |
| 26 | Post 4 |
| 27 | Post 5 |
| 28 | Post 6 |
| 29 | Post 7 |
| 30 | Post 8 |
| 32 | Post 9 |
+----+-----------------+
home_post table
+----+------------+
| id | post_id |
+----+------------+
| 1 | 28 |
| 2 | 29 |
| 3 | 2 |
+----+------------+
In Post model:
public function home_posts()
{
return $this->hasMany('App\HomePost', 'post_id', 'id');
}
In HomePost model:
public function post()
{
return $this->belongsTo('App\Post', 'post_id', 'id');
}
To get post through home_post:
$homePost = \App\HomePost::find(1);
$post = $homePost->post;
or
$posts = \App\HomePost::has('post')->get();
To get home_post through post:
$post = \App\Post::find(1);
$homePost = $homePost->home_posts;
or
$homePost = \App\Post::has('home_posts')->get();
For more detail read this: One To Many
Hope it help you :)
I have two simple tables, cats and breeds:
mysql> select * from cats;
+----+--------+---------------+----------+---------------------+---------------------+
| id | name | date_of_birth | breed_id | created_at | updated_at |
+----+--------+---------------+----------+---------------------+---------------------+
| 1 | Rita | 2008-07-06 | 1 | 2015-05-09 20:40:49 | 2015-05-09 20:50:20 |
| 2 | Muni | 1992-05-15 | 3 | 2015-05-09 20:50:54 | 2015-05-09 20:50:54 |
| 3 | Hector | 2005-01-23 | 4 | 2015-05-09 21:08:23 | 2015-05-09 21:08:23 |
+----+--------+---------------+----------+---------------------+---------------------+
3 rows in set (0.00 sec)
mysql> select * from breeds;
+----+------------+
| id | name |
+----+------------+
| 1 | Domestic |
| 2 | Persian |
| 3 | Siamese |
| 4 | Abyssinian |
+----+------------+
4 rows in set (0.00 sec)
All I want to do is get a list of the cats that are of a certain breed. In the cats table, breed_id is a FK that points to the PK of the breeds table. The example code in my book which is supposed to return a view with all cats of a specific breed returns no results:
The url I am trying is /cats/breeds/Domestic
The view that is generated uses this logic in the routes.php file:
Route::get('cats/breeds/{name}', function($name)
{
$cats = Furbook\Cat::with('breeds')
->whereName($name)
->get();
dd($cats);
});
When I dd($cats) I get zero results even though I have a cat with a domestic breed_id of 1. What have I done wrong here?
EDIT:
I can get it to work with the following hacky code, which first gets the id from the breeds table by querying against the name field, then queries the cats table with that id:
$breed = Furbook\Breed::whereName($name)->get();
$id = $breed[0]['attributes']['id'];
$cats = Furbook\Cat::whereId($id)->get();
How do I make this into one Eloquent query? I see no examples for this kind of query on the Laravel site.
For more information this is how the models look:
class Breed extends Model {
public $timestamps = false;
public function cats()
{
return $this->hasMany('Furbook\Breed');
}
}
class Cat extends Model {
protected $fillable = [
'name',
'date_of_birth',
'breed_id',
];
public function breed()
{
return $this->belongsTo('Furbook\Breed');
}
}
You're asking the system to give you all cats with a name of Domestic - not all cats of the breed name Domestic.
Assuming your model relationships are in order, you could do e.g.
$cats = Furbook\Breed::whereName($name)->first()->cats;
Also, my Burmese cat just hit the monitor; I think she's upset that she's not in the breeds list.
I have a form that has a dropdown where the user can select up to 5 countries.
I have two related tables, users and countries, where each user can have multiple countries selected.
The users table:
+----+----------+----------------------+
| id | username | description |
+----+----------+----------------------+
| 1 | user1 | Some description. |
| 2 | user2 | Another description. |
+----+----------+----------------------+
The countries table:
+----+---------+---------------+
| id | user_id | country |
+----+---------+---------------+
| 1 | 1 | Canada |
| 2 | 1 | United States |
| 3 | 1 | France |
| 4 | 2 | Spain |
| 4 | 2 | Italy |
+----+---------+---------------+
As you can see, the country dropdown values should each have their own row in the table.
Here is my UserController so far (it only inserts into the users table for now):
$user = new User;
$user->username = Input::get('username');
$user->description = Input::get('description');
$user->save();
How would I insert multiple dropdown values such that each has its own row? What should my models look like for this to work?
If you're gonna use eloquent to do it, here's a suggestion:
//in your User model
public function countries()
{
return $this->hasMany('Country');
}
//insert from the controller
$countries = json_decode(Input::get('countries'), true); //assuming you use json to submit the multiple countries
$user_countries = array();
foreach($countries as $country)
{
$user_countries[]=new Country(array('country'=>$country));
}
//save the countries into the DB
$user->countries()->saveMany($user_countries);
for more info, do refer to the documentation:
http://laravel.com/docs/4.2/eloquent#inserting-related-models