Simple SQL to Eloquent Query (Laravel) - sql

I have two tables: users (Users) and groups (Groups).
Users
-----------------
id | username | group
1 | Bob | 2
Groups
-----------------
id | name
1 | firstgroup
2 | secondgroup
I would like to display: users.ID, users.username, group.name (1, Bob, secondgroup)
An SQL statement like so would work:
SELECT Users.id, Users.username, Groups.name
FROM Users
INNER JOIN
Groups ON Groups.id = Users.group
However, I'm struggling to write this in Eloquent, since there is no "FROM". At the moment I'm going for something along the lines of the below, using JOINS (http://laravel.com/docs/queries#joins)
$users = Users::select('id','username', 'Groups.name')->joins('Groups.id', '=', 'id')->get();
Now this isn't working - I think the joins has to come before the select but I just can't work it out :(

I think you're confusing a few things here...
You're mixing Eloquent with the lower-level DB::table('foo')->select() syntax. When you want to use Eloquent I suggest you take a look at the docs about relationships in Eloquent.
You should define your models like so:
class User extends Eloquent {
public function group()
{
return $this->belongsTo('Group', 'group');
// second parameter is necessary because you didnt
// name the column "group_id" but simply "group"
}
}
class Group extends Eloquent {
public function users()
{
return $this->hasMany('User', 'group');
}
}
This sets up all the joins you might be needing later. You can then simply use User::with('group')->all(); and have the query built and run for you.

Database: Query Builder(DB) is not a Eloquent(ORM):
Database query builder you have to inform the table names and the fields, like it says on in your related link of laravel docs: "...provides a convenient, fluent interface to creating and running database queries." like these query below:
$users = DB::table('users')
->join('contacts', 'users.id', '=', 'contacts.user_id')
->join('orders', 'users.id', '=', 'orders.user_id')
->select('users.*', 'contacts.phone', 'orders.price')
->get();
Eloquent is a ORM - Object related Mapping, it means that your class User is related to the table users (look at you files Migrations) and this class extends the Model Class, thus you can access the methods like these bellow:
class User extends Models
{
public static function usersWithGroups(){
return User::select('id', 'name', 'email')->with('groups')->get();
}
}
Observe that method is into the class User, so you can access that in a static way "User::", using Eloquent you'll have many hidden static methods that will improve you time codding, because you are inheriting de Model methods, to more details visit the Eloquent Docs at: Eloquent Docs

Related

Select from select using Laravel eloquent

I want to get all user's favourite products. The query should be like this:
SELECT *
FROM products
WHERE id IN (SELECT id FROM favourites WHERE user_id == Auth::id())
How can I query with eloquent?
You're trying to achieve something like this:
In the oficial documentation you can find the explanation of Advanced where clauses
DB::table('products')
->whereIn('id', function($query)
{
$query->select('id')
->from('favourites')
->where('favourites.user_id', Auth::id());
})
->get()
The final result will be (you can see this dumping the query using toSql() method instead of get()) :
select * from `products` where `id` in (select `id` from `favourites` where `favourites`.`user_id` = ?)
What do you mean to saying "How can I do it"? Are you asking how to structure it or how to query with eloquent?
If you asking the query:
Product::whereIn('id', Favourite::select('id')->whereUserId(Auth::id())->get()->toArray())->get();
should work.
If you asking structure, you should define relations in models.
On User model;
public function favourites()
{
return $this->hasMany(Favourite::class, 'user_id');
}
and on Favourite model;
public function favoriteProduct()
{
return $this->belongsTo(Product::class, '[the product_id column on favourites table]');
}
and then you can access like;
$userFavourites = User::with('favourites.favoriteProduct')->whereId(Auth::id())->favourites;
on your view:
#foreach($userFavourites as $userFavourite)
{{ $userFavourite->favouriteProduct }}
#endforeach
this is the simplest. on the other hand; you can use Has Many Through relationship.
And this would be the cleanest way.

Retrieve data on many tables - Laravel

Good morning,
Here is my model :
A Chretien can have many Poste. A Poste can belog to many Chretien.
A Poste belongs to many Departement. A Departement has many Poste.
CHRETIEN------------------------POSTE---------------------------DEPARTEMENT
0..* 0..* 1..** 0.. *
How can I retrieve the model like this?
John DOE
---------------------------------------
|**Postes** | **Departements** |
---------------------------------------
|Pianist | Musical Group |
---------------------------------------
| Secretary Curch | council |
---------------------------------------
|Wedding Planer | Organizatin Comite|
When accessing Eloquent relationships as properties, the relationship data is "lazy loaded". This means the relationship data is not actually loaded until you first access the property. However, Eloquent can "eager load" relationships at the time you query the parent model. Eager loading alleviates the N + 1 query problem. To illustrate the N + 1 query problem, consider a Chretien model that is related to Poste:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Poste extends Model
{
/**
* Get the chretien that wrote the poste.
*/
public function chretien()
{
return $this->belongsTo('App\Chretien');
}
}
Now, let's retrieve all chretiens and their postes:
$chretiens = App\Chretien::with('postes')->get();
foreach ($chretiens as $chretien) {
echo $chretien->postes->name;
}
For this operation, only two queries will be executed:
select * from chretiens
select * from postes where id in (1, 2, 3, 4, 5, ...)
Nested Eager Loading
To eager load nested relationships, you may use "dot" syntax. For example, let's eager load all of the poste's and all of the departament's in one Eloquent statement:
$chretiens = App\Chretien::with('postes.departaments')->get();

Join multiple tables used as Indexing - Laravel

I have three tables - Chairman, Designation, Members.
MY requirement is to map the member to chairman and assign member a role.
I was able to fetch the list of members under the chairman when I had chairman_id and designation_id in the members table.
Since the chairman change, most of the members stay intact. So I came up with an idea of indexing them
Table - membermap
id | chairman_id | designation_id | member_id
So the list is preserved how many chairmans come and go. I dont need to create new profile for new chairman rather than map to it.
I am now sure how do I do it,
So far I was able to pull the ID but I am not sure how do I join the tables
Tables
Chairman
id| name
Designation
id|designation
Members
id|members
Here is my controller
$mapmember = Statechairman::findOrFail($id)->statechairmembersmap;
dd($mapmember);
In this Iam getting the statechairmembersmap but it's fetching all the result and not limiting the match.
I also tried to join the query using the DB
$mapmember = DB::table('statechairmen')
->join('state_chairman_members_maps', 'state_chairman_members_maps.chairman_id','statechairmen.id')
->join('statemembers','statemembers.id','state_chairman_members_maps.members_id')
->select('state_chairman_members_maps.*')->get();
but this result show me the Table - membermap but not the other results.
My Models:
Chairman :
public function statechairmembersmap(){
return $this->hasMany('App\StateChairmanMembersMap','chairman_id','id');
}
public function statemembers(){
return $this->hasMany('App\Statemembers','chairman_id', 'id');
}
public function statedesignation(){
return $this->hasMany('App\Statedesignation','id','designation_id');
}
membermap:
protected $table = 'state_chairman_members_maps';
protected $dates = ['deleted_at'];
public function statechairman(){
return $this->belongsTo('App\Statechairman','id');
}
public function statedesignations(){
return $this->belongsTo('App\Statedesignation','designation_id','id');
}
public function statemembers(){
return $this->belongsTo('App\Statemembers','members_id','id');
}
Please assist me where I doing wrong.
Thanks a lot for checking the question out.
Finally after a lot of strugle, I was able to find it by myself.
$mapmembers = DB::table('state_chairman_members_maps')
->join('statechairmen','statechairmen.id','=','state_chairman_members_maps.chairman_id')
->join('statemembers','statemembers.id','=','state_chairman_members_maps.members_id')
->join('statedesignations','statedesignations.id','=','state_chairman_members_maps.designation_id')
->where('chairman_id','=',$id)
->get();
Here is what I came up with.
Here I have joined 3 tables and mapped the id comming from the chairman to filter the result. I getting the results.

How to change Doctrine "findBy/findOneBy" functions's behaviors to reduce the number of queries?

I'm working on a Symfony2 using Doctrine.
I would like to know how to change the behavior of "findBy" functions when retrieving my entities.
For example, if you call "findAll()", it returns all products.
$entities = $em->getRepository('ShopBundle:Product')->findAll();
However, how to reduce the number of queries, because, by default, it will create a new query each time I want to get a member linked to a join column. So if I get 100 entities, it will process 101 queries (1 to get all entities and 1 by entity to get join column).
So today, I use createQuery() function by specifying the joins. Is there a way to configure something about findBy functions to skip createQuery method ?
Thanks in advance !
K4
You can fetch out this in below way
public function findUser() {
$query = $this->getEntityManager()
->createQuery('SELECT us.id as id, us.name as user_name FROM Bundle:User us');
try {
return $query->getResult();
} catch (\Doctrine\ORM\NoResultException $e) {
return null;
}
}

Getting data with CActiveDataProvider in yii

I have 3 tables, standart relation MANY-TO-MANY
Users(id,...) -> Users_Has_Courses(Users_id, Courses_id) -> Courses(id,...)
Courses Model has next relation
'users' => array(self::MANY_MANY, 'Users', 'users_has_courses(Courses_id, Users_id)')
Users Model has next relation
'courses' => array(self::MANY_MANY, 'Courses', 'users_has_courses(Users_id, Courses_id)')
Please, say how I can get list of courses, on which user with specified "id" hasn't been subscribed with CActiveDataProvider ?
Otherwords, I need an analogue of this plain SQL query
select * from Courses where id not in (select Courses_id from users_has_courses where Users_id = 2)
thanks for the help
Instead of a regular "relation", try a parametrized Named Scope to encapsulate the query. In your Courses model, add this scope function to get a list of all the courses the user is not in:
public function userNotIn($user_id)
{
$criteria=new CDbCriteria();
$criteria->condition .= 't.id NOT IN (SELECT users_has_courses.Courses_id FROM users_has_courses WHERE users_has_courses.Users_id = :userid)';
$criteria->params[':userid'] = $user_id;
$this->getDbCriteria()->mergeWith($criteria);
return $this;
}
Then you should be able to do this:
$coursesNotIn=new CActiveDataProvider(Courses::model()->userNotIn($user->id));
This code is completely untested, but it should work in principle. I do this sort of thing often when I have a complex query but I still want to use the AR features, like CActiveDataProvider. Read more about "named scopes" here:
http://www.yiiframework.com/doc/guide/1.1/en/database.ar#parameterized-named-scopes
Good luck!