I have three models:
Vehicles:
+--------------------+------------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+------------------+------+-----+---------------------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| registration | varchar(255) | NO | | NULL | |
| vin | varchar(255) | NO | | NULL | |
| titular_id | int(10) unsigned | NO | | NULL | |
| titular_type | varchar(255) | NO | | NULL | |
| renter_id | int(10) unsigned | NO | | NULL | |
| renter_type | varchar(255) | NO | | NULL | |
+--------------------+------------------+------+-----+---------------------+----------------+
SiretCompanies:
+------------------+------------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+------------------+------+-----+---------------------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| siret | varchar(255) | NO | | NULL | |
| siren_company_id | int(10) unsigned | NO | MUL | NULL | |
+------------------+------------------+------+-----+---------------------+----------------+
SirenCompany:
+---------------------+------------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+------------------+------+-----+---------------------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| siren | varchar(255) | NO | | NULL | |
+---------------------+------------------+------+-----+---------------------+----------------+
A vehicle can be related to the SirenCompany either through a titular, or a renter. What I want is to get all related vehicles for a SirenCompany.
In raw MySQL, this is my query:
select count(*) FROM `vehicles`
inner join `siret_companies`
on (
(`vehicles`.`titular_type` = 'SiretCompany' and `vehicles`.`titular_id` = `siret_companies`.`id`)
OR
(`vehicles`.`renter_type` = 'SiretCompany' and `vehicles`.`renter_id` = `siret_companies`.`id`)
)
inner join `siren_companies`
on `siren_companies`.`id` = `siret_companies`.`siren_company_id`
where `siren_companies`.`id` = 410
Now what I would like to do is run that as an Eloquent query, but I cannot seem to figure it out.
If I only consider the titular, I have this:
return Vehicle::join('siret_companies',function($join) {
$join
->where('vehicles.titular_type', '=', 'SiretCompany')
->where('vehicles.titular_id','=', 'siret_companies.id');
})
->join('siren_companies', function($join) {
$join->on('siren_companies.id', '=', 'siret_companies.siren_company_id');
})
->where('siren_companies.id','=',$this->id)
->count();
But I cannot seem to figure out how to write the join so that it corresponds to the above query.
This is what I've come up with
Vehicle::join('siret_companies', function ($q) {
$q->on('vehicles.titular_type', '=', 'SiretCompany');
$q->orOn('vehicles.titular_id','=', 'siret_companies.id');
})->join('siret_companies', function ($q) {
$q->on('siren_companies.id', '=', 'siret_companies.siren_company_id');
})->where('siren_companies.id','=', $id);
Related
I'm working in Laravel and need help with database relations. I have three tables:
projects:
+------------+--------------------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| title | varchar(191) | NO | | NULL | |
| url | varchar(191) | YES | | NULL | |
| updated | bigint(20) unsigned | YES | | NULL | |
| type | enum('adobe','invision','pdf') | NO | | NULL | |
| preview_id | int(10) unsigned | YES | MUL | NULL | |
+------------+--------------------------------+------+-----+---------+----------------+
users:
+----------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| email | varchar(150) | NO | UNI | NULL | |
| password | varchar(179) | NO | UNI | NULL | |
| remember_token | varchar(100) | YES | | NULL | |
+----------------+------------------+------+-----+---------+----------------+
projects_users
+------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| project_id | int(10) unsigned | YES | MUL | NULL | |
| user_id | int(10) unsigned | NO | MUL | NULL | |
+------------+------------------+------+-----+---------+----------------+
Situation: There are several projects, and multiple users can work on multiple projects (ManyToMany).
I need to select (SELECT-statement) all users working on project with e.g ID 1.
How would I do that in plain SQL, and how would I do that in Laravel code (without a raw-sql-query function).
I already looked here but I ain't really catching it.
Thanks!
Use the whereHas() method:
$users = User::whereHas('projects', function($q) use($projectId) {
$q->where('id', $projectId);
})->get();
class Project extends Model{
public function users()
{
return $this->belongsToMany('App\User', 'projects_users');
}
}
class User extends Model{
public function projects()
{
return $this->belongsToMany('App\Project', 'projects_users');
}
}
$project = Project::find(1);
$project->users //list of all the users
I am using Entrust's default table structure:
permissions table:
+--------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | UNI | NULL | |
| display_name | varchar(255) | YES | | NULL | |
| description | varchar(255) | YES | | NULL | |
| created_at | timestamp | NO | | NULL | |
| updated_at | timestamp | NO | | NULL | |
+--------------+------------------+------+-----+---------+----------------+
permission_role table:
+---------------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------------+------+-----+---------+-------+
| permission_id | int(10) unsigned | NO | PRI | NULL | |
| role_id | int(10) unsigned | NO | PRI | NULL | |
+---------------+------------------+------+-----+---------+-------+
roles table:
+--------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | UNI | NULL | |
| display_name | varchar(255) | YES | | NULL | |
| description | varchar(255) | YES | | NULL | |
| created_at | timestamp | NO | | NULL | |
| updated_at | timestamp | NO | | NULL | |
+--------------+------------------+------+-----+---------+----------------+
Now, given a role_id I'd like to get select the following from this database:
permissions.id
permissions.display_name
whether the permission_role table contains an entry with the permission_id and the given role_id
The last one turned out to be a bit tricky in Eloquent.
This SQL query accomplishes exactly what I need (ID is obviously replaced by a valid role ID):
SELECT p.id, p.display_name, IF(pr.role_id = ID, 1, 0) AS has_role
FROM permissions p
LEFT OUTER JOIN permission_role pr ON p.id = pr.permission_id;
Example output:
+----+--------------+----------+
| id | display_name | has_role |
+----+--------------+----------+
| 1 | Edit users | 1 |
| 2 | View users | 0 |
| 3 | Delete users | 0 |
+----+--------------+----------+
Can anyone help me out here, on how to do this using Eloquent?
I've tried this, but it always returns 1 (true) in the third column, unlike the SQL query (as seen above).
$result = DB::table('permissions')
->leftJoin('permission_role', 'permission_role.permission_id', '=', 'permission_role.role_id')
->select(DB::raw('permissions.id, permissions.display_name, IF(permission_role.role_id = ID, 1, 0) AS has_role'))
->get();
Ideally, I'd like to do this without using DB::raw, although it is completely fine if that is what it takes.
Thanks in advance for any help!
Structurally, the Query Builder query you've shown looks fine.
What does not look fine is the left join. Shouldn't this:
->leftJoin('permission_role', 'permission_role.permission_id', '=', 'permission_role.role_id')
be this:
->leftJoin('permission_role', 'permission_role.permission_id', '=', 'permissions.id')
?
I have 3 tables.
1.posts
2.categories
3.category_post.
My Posts Tables here :
+------------+------------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+------------------+------+-----+---------------------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| title | varchar(255) | NO | | NULL | |
| slug | varchar(255) | NO | | NULL | |
| reporter | varchar(255) | NO | | NULL | |
| meta | varchar(255) | NO | | 0 | |
| body | text | NO | | NULL | |
| image | varchar(255) | NO | | 0 | |
| top | tinyint(1) | NO | | 0 | |
| post_count | int(11) | NO | | 0 | |
| created_at | timestamp | NO | | 0000-00-00 00:00:00 | |
| updated_at | timestamp | NO | | 0000-00-00 00:00:00 | |
+------------+------------------+------+-----+---------------------+----------------+
My Categories Table Here:
+---------------+------------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------------+------+-----+---------------------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| category_slug | varchar(255) | NO | | NULL | |
| parrent_id | int(11) | NO | | 0 | |
| created_at | timestamp | NO | | 0000-00-00 00:00:00 | |
| updated_at | timestamp | NO | | 0000-00-00 00:00:00 | |
+---------------+------------------+------+-----+---------------------+----------------+
My category_post table:
+-------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| category_id | int(10) unsigned | NO | MUL | NULL | |
| post_id | int(10) unsigned | NO | MUL | NULL | |
+-------------+------------------+------+-----+---------+----------------+
I can create post with multiple category selected . But When i want to showing post by category, then i can't access category table . That means, i want to view category name with each post .
Here is my Models:
In Category Model:
public function posts()
{
return $this->belongsToMany('Post');
}
In Post Model:
public function categories()
{
return $this->belongsToMany('Category');
}
My Query Helper function is for Post by category:
public static function cat_post($category, $limit, $top)
{
$posts = Post::whereHas('categories', function($q) use ($category, $top)
{
$q->where('name', 'like', $category);
$q->where('top', 'like', $top);
})->with('categories')->take($limit)->orderBy('created_at', 'DESC')->get();
return $posts;
}
I can view all post data . But category name not .
My Post Loops:
<?php $headline = Helper::head_post(10, 1); ?>
#foreach ($headline as $post)
<li>{{ $post->title }}</li>
#endforeach
when i try this for category name not working:
#foreach ($headline as $post)
<li>{{ $post->categories->name }}</li>
#endforeach
Please help me.
Because it's a many to many relation $post->categories->name will not work. It doesn't know which category (of the many) you want the name of.
So you could for example use $post->categories()->first()->name to get the name of the first category or loop over them to get the name of all categories.
I would like to know how can I do joints in this case :
I have a table named : Table_ref that contains the name of all the table in the database, with the structure :
-----------------------------------------------
| Field | Type | Null | Key |
-----------------------------------------------
| tbl_name | varchar(45) | NO | PRI |
| tbl_type | Tinyint(3) | NO | MUL |
-----------------------------------------------
and forteen other table with names like : A1,B1, A2,B2 ... with the same structure :
-----------------------------------------------
| Field | Type | Null | Key |
-----------------------------------------------
| id | int(10) | NO | PRI |
| itime | int(10) | YES | MUL |
| dtime | int(10) | YES | MUL |
| src | varchar(40) | YES | |
| dstname | varchar(255)| YES | |
-----------------------------------------------
The question is how can I do joints in order to extract information where src='192.168.1.2' from all the tables.
This is the combined structure for all your tables
-----------------------------------------------
| Field | Type | Null | Key |
-----------------------------------------------
| id | int(10) | NO | PRI |
| itime | int(10) | YES | MUL |
| dtime | int(10) | YES | MUL |
| src | varchar(40) | YES | |
| dstname | varchar(255)| YES | |
| type | Tinyint(3) | NO | MUL |
-----------------------------------------------
And now you can extract information with a simplist query
SELECT
*
FROM mytable
WHERE src = '192.168.1.2'
It will fetch records from every type. If you need information form
specific type just add another where condition
SELECT
*
FROM mytable
WHERE src = '192.168.1.2'
AND type = 1
It's 3:30 AM in my country so I need to sleep but I can't without this:
I'm trying to get all posts (using Zend_Db) and count comments for each one.
Schema
blog_posts:
+---------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| title | varchar(255) | NO | | NULL | |
| content | text | NO | | NULL | |
| alias | varchar(100) | NO | | NULL | |
| user_id | int(11) | NO | | NULL | |
| created_date | datetime | NO | | NULL | |
| modified_date | datetime | YES | | NULL | |
| thumbnail | varchar(255) | YES | | NULL | |
+---------------+------------------+------+-----+---------+----------------+
And here's blog_comments:
+---------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| user_id | int(11) | NO | | NULL | |
| post_id | int(11) | NO | | NULL | |
| comment | text | NO | | NULL | |
| created_date | datetime | NO | | NULL | |
| modified_date | datetime | YES | | NULL | |
+---------------+------------------+------+-----+---------+----------------+
Note: the blog_comments.post_id is linked with blog_posts.id.
I would like a resulting table like that:
+---------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| title | varchar(255) | NO | | NULL | |
| content | text | NO | | NULL | |
| alias | varchar(100) | NO | | NULL | |
| user_id | int(11) | NO | | NULL | |
| created_date | datetime | NO | | NULL | |
| modified_date | datetime | YES | | NULL | |
| thumbnail | varchar(255) | YES | | NULL | |
+---------------+------------------+------+-----+---------+----------------+
| TEMPOROARY COLUMN IN OBJECT ($post->comment) |
+---------------+------------------+------+-----+---------+----------------+
| comments | | | | | |
+---------------+------------------+------+-----+---------+----------------+
Now, here's the query I have for now:
SELECT `p`.*, `c`.*
FROM `blog_posts` `p`
LEFT JOIN (
SELECT COUNT(*)
FROM `blog_comments` `c`
WHERE c.post_id = p.id
) ON `p`.`comments`;
But it give me an error:
Error Code: 1248. Every derived table must have its own alias
So if someone can help me, it would be very appreciated!
IMPORTANT NOTE
I'm using Zend_Db and Zend_Db_Select so I must be able to use the functions like joinLeft() or anything I need.
This is in my model for the select():
$select = $this->table->select();
if ($alias) {
$select->where('alias = ?', $alias);
return $this->table->fetchRow($select);
}
if ($withComments) {
// I WILL PLACE THE CODE HERE, EXEMPLE:
$select->joinLeft(...);
}
SELECT p.*, x.*
FROM blog_posts p
LEFT JOIN
(
SELECT post_id, COUNT(*) as cc
FROM blog_comments
GROUP BY post_id
) x
ON x.post_id = p.id;