Select from select using Laravel eloquent - sql

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.

Related

SailsJS manually populate records using Model.query

lets say i have this example as my app
http://sailsjs.org/#!/documentation/concepts/ORM/Associations/OnetoMany.html
For some big reasons(complicated) I cannot use Model.populate() and I'm stuck in using Model.query()
Does anyone know how to get the result as User.find().populate('pets') Using Model.query() Please
Thank you
You can do it like waterline adapters do to populate OneToMany:
Retrieve parents : select * from user ...
Retrieve children for each parent in only one query to not overload DBMS:
select * from pet where user = user1.id union select * from
pet where user = user2.id union ... union select * from pet where user
= userN.id.
Regroup children by parentPk(you can use lodash or underscore.js functions to do it) Ex:
users.forEach(function(user){
user.pets = _.filter(pets,function(pet){
return pet.user === user.id;
});
});

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

Simple SQL to Eloquent Query (Laravel)

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

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!

Nhibernate - How do I get ordered distinct results with QueryOver?

public class City
{
virtual public long Id { get; set; }
virtual public string Name { get; set; }
}
City table contains duplicated Names and I want to remove duplicates. I also want the results to be ordered by Id.
First I thought about the following query.
select distinct Name from City order by Id;
But this breaks with 'ORDER BY items must appear in the select list if SELECT DISTINCT is specified.' exception. After seeing http://weblogs.sqlteam.com/jeffs/archive/2007/12/13/select-distinct-order-by-error.aspx I think I should do:
select Name from City group by Name order by min(Id)
So my question is how can I do this query with QueryOver?
This is possible in ICriteria:
var list =
session.CreateCriteria<City>()
.SetProjection(Projections.Group("Name"))
.AddOrder(Order.Asc(Projections.Min("Id")))
.List<string>();
But this is not currently possible in QueryOver, because the .OrderBy(IProjection) overload is missing. Once the missing overload has been added it should look something like:
var list =
s.QueryOver<City>()
.Select(Projections.Group<City>(p => p.Name))
.OrderBy(Projections.Min<City>(c => c.Id)).Asc
.List<string>();
Note that the Projections overloads are there just now, so you can write the following (typesafe) query in ICriteria:
var list =
session.CreateCriteria<City>()
.SetProjection(Projections.Group<City>(c => c.Name))
.AddOrder(Order.Asc(Projections.Min<City>(c => c.Id)))
.List<string>();
So, what I've found is pretty simple...
var query = session.QueryOver<MyModel>()
// Conditions here
.OrderBy(m => m.GetThisDistinctField).Desc() // ...or Asc()...
.SelectList(m => m.SelectGroup(g => g.GetThisDistinctField));
var result = query.List<FieldDataType>().ToList();
return result;
To get an ordered query in queryover, start with a query that includes whatever criteria you need, but then add the SelectList/SelectGroup setup in order to get the distinct list. In other words, it's sort of like NHibernate can take a regular query, and then do special stuff to make it a select distinct query.
This is a solution I'm using in a current project I'm working on; I hope it helps someone else too.