I have this DB:
[Database model]
This is the query I want to make in Laravel:
SELECT
product_translations.name,
product_translations.description,
products.ean_code
FROM product_translations, products, languages
WHERE product_translations.language_id = languages.id
AND products.id = product_translations.product_id
AND languages.language_code = "en";
Relationships in Laravel:
class Product extends Model
{
public function translations ()
{
return $this->hasMany(ProductTranslation::class, 'product_id');
}
}
class ProductTranslation extends Model
{
public function product()
{
return $this->belongsTo(Product::class, 'product_id');
}
public function language()
{
return $this->belongsTo(Language::class, 'language_id');
}
}
class Language extends Model
{
public function ProductTranslations()
{
return $this->hasMany(ProductTranslation::class, 'language_id');
}
}
is this correct? the raw query works.
thanks
The query syntax you are using is an old style syntax and will produce inner joins for tables. Using laravel you can use builtin methods to query data from your related models.
For your question I believe you need products list but with specific translation
$products = Product::with(['translations' => function($query)
{
$query->join('product_translations as pt', 'products.id', '=', 'pt.cart_id')
->join('languages as l', 'l.id', '=', 'pt.language_id')
->where('l.language_code', '=', 'en')
->first();
}])->get();
Or if you want to go with query builder you can write as
$products = DB::table('products AS p')
->select([
'p.id',
'p.is_organic',
'pt.name',
'pt.description',
'pt.ean_code'
])
->join('product_translations AS pt', 'pt.product_id', '=', 'p.id' )
->join('languages AS l', 'pt.language_id', '=', 'l.id')
->where('l.language_code','en')
->get();
In SQL
SELECT
p.id,
p.is_organic,
pt.name,
pt.description,
pt.ean_code
FROM products p
INNER JOIN product_translations as pt ON pt.product_id = p.id
INNER JOIN languages l ON pt.language_id = l.id
WHERE l.language_code = "en";
Related
I'm having great difficulty in trying to convert the following query into an Eloquent one.
SELECT Sum(t.amount) AS amount,
m.name
FROM transactionsv2 t
JOIN channels c
ON t.entityid = c.uuid
JOIN merchants m
ON c.sender = m.uuid
WHERE t.paymenttype = 'DB'
AND t.status = 1
AND t.processing_time >= '2019-01-01'
AND t.processing_time < '2019-01-21'
GROUP BY m.name;
This is what I have but the result set is not right...
public function getTransactionsVolumeReport()
{
$report = Transaction::select(DB::raw('sum(amount) as amount, entityId'))
->where('paymentType', '=', 'DB')
->where('status', 1)
->where('processing_time', '>=', '2019-01-01 00:00:00')
->where('processing_time', '<=', '2019-01-21 23:59:59')
->with(['channel' => function ($q) {
$q->select('uuid', 'name', 'sender');
}])
->with(['channel.merchant' => function ($q) {
$q->select('uuid', 'name')
->groupBy('name');
}])
->get();
echo $report;
}
These are the queries that Laravel debugbar is showing...
Below are my Eloquent relationships...
Transaction Model
protected $with = ['channel', 'statusPayment'];
public function channel() {
return $this->hasOne(Channel::class, 'uuid', 'entityId');
}
-----
Channel Model
protected $with = ['merchant', 'attachedMerchantAccount'];
public function merchant() {
return $this->hasOne('App\Merchant', 'uuid', 'sender');
}
This is my simple db schema. Now in my group table i have 'group_A' and 'group_B'. In questions table i have 10 questions 5 for group_A and 5 for group_B. Users table is one user with ID = 1. What i try to do is get data like this:
SELECT answer
FROM answers
JOIN questions q ON (q.id = answer.question_id)
JOIN group g ON (g.id = q.group_id)
WHERE user_id = 1 AND g = 'group_A'
I have model in users class and i would like create method to get answers depend from group:
public function getAnswers($group) {
return $this->hasMany('App\Answers', 'question_id', 'id');
}
How can i get this in that method ? Should i create method group in questions class ?
Not sure about how to define such relation in model which takes input parameter but you could define a scope in your model to get the answers filtered by group like
class Answer extends Model {
public function user()
{
return $this->belongsTo('App\User');
}
public function question()
{
return $this->belongsTo('App\Question');
}
public function scopeGroup($query, $name)
{
return $query->whereHas('question.group', function($q) use($name){
$q->where('name', '=', $name);
});
}
}
I assume in answers model you have defined relationship for question and similarly in question model you have defined relationship for group model.
In query builder you could write it as
$answers = Answer::group('group_A')
->whereHas('user', function($q) use($userid){
$q->where('id', '=', $userid);
})->get();
Or you could apply filter on eager loaded relations as
$users = User::with(['answers' => function($query)
{
$query->whereHas('question.group', function($q){
$q->where('name', '=', 'group_A');
});
}])->get();
If you already have user object you can get answers for specific group as
$answers = $user->answers()
->whereHas('question.group', function($q){
$q->where('name', '=', 'group_A');
})->get();
I read this post which helped, but need more guidance please.
I need a set of Results for a particular $batteryid (on Result) and a particular $age (on Test model) and a particular $gender (from Athlete). Each Test belongs to one athlete. Each test has many results.
Model Battery:
class Battery extends Model{
public function results(){
return $this->hasMany('App\Result');
}
}
Model Result:
class Result extends Model{
public function test(){
return $this->belongsTo('App\Test', 'test_id');
}
public function battery(){
return $this->belongsTo('App\Battery', 'battery_id');
}
}
Model Test:
class Test extends Model{
public function athlete(){
return $this->belongsTo('App\Athlete', 'athlete_id');
}
public function results(){
return $this->hasMany('App\Result');
}
}
I get the correct results with the following, but it's two queries:
$tests = Test::whereHas('Athlete', function($query) use($gender){
$query->wheregender($gender);
})->where('age', $age)->get();
$test_ids = $tests->pluck('id');
$results = Result::where('battery_id', '=', $battery)
->whereIn('test_id', $test_ids)
->get();
I'd like to use model approach, but am completely stuck. test.age not recognised and not sure how to get the age from athlete model. My attempt:
$results = Result::with('test')
->where('test.age', '=', $age)
->join('batteries', 'batteries.id', '=', 'test.battery_id')
//->where('test->athlete().gender', '=' $gender)
->where('battery_id', '=', $battery)
->get();
You can use whereHas for the condition and with method for eager loading it.
$results = Result::whereHas('test', function($q) use ($age) {
$q->where('age', '=', $age);
$q->whereHas('athlete', function ($q) {
$q->where('gender', 'male');
});
})
->with('test')
->whereHas('battery', function($q) use($battery) {
$q->where('battery_id', '=', $battery);
})
->with('battery')
->get();
I have two tables: films and actors. Thy have a n-m relation.
I have a connection table actor_film with two columns film_id and actor_id.
In order to get the list of films added in the current month with the actors that play in each film I did this:
$current_month_film = DB::table('films')
->join('actor_film', 'actor_film.film_id', '=', 'films.id')
->join('actors', 'actors.id', '=', 'actor_film.actor_id')
->select('films.*', 'actors.name as actors_name')
->whereMonth('films.created_at', '=', Carbon::now()->month)
->orderBy('films.created_at', 'desc')
->groupBy('films.name')
->get();
return view('statistics.month')->withCurrent_month_film($current_month_film);
I get 40 films each of it showing just ONE actor, even if I know there are several actors in one film.
If I delete the "->groupBy('films.name')" I get 132 record: one film several times and each time one actor.
How could I get a list of actors inside each film, joinig the two tables? something like:
[
{
film.id: 1,
film.name,
film.actors
{
actor[1].name: Morgan Freeman,
actor.[2].name: Meryl Streep
actor [n].name: ....
}
},
{
film.id: 2,
film.name,
film.actors
{
actor[1].name: Morgan Freeman,
actor.[2].name: Meryl Streep
actor [n].name: ....
}
}
]
If you want to use Eloquent and you have your relation in place then your can do it as:
Film::whereMonth('created_at', Carbon::now()->month)
->orderBy('created_at', 'desc')
->with(['actors' => function($q) {
$q->select('name');
}])
->get()
Docs
As you're using Laravel, you should make the use of Laravel Relationships. You should have a models like this:
class Actor extends Model
{
public function films() {
return $this->belongsToMany(Film::class, 'actor_film');
}
}
class Film extends Model
{
public function actors() {
return $this->belongsToMany(Actor::class, 'actor_film');
}
}
and to get the film with their respective actors, you can use with method like this:
$films = Film::with(['actors' => function($q) {
$q->select('name');
}])
->whereMonth('created_at', Carbon::now()->month)
->orderBy('created_at', 'desc')
->get();
foreach($films as $film) {
$film_name = $film->name;
$actors_arr = $film->actors->toArray();
}
See more about Laravel's Eloquent Relationships & Eager Loading
Hope this helps!
In Controller
$current_month_film = Film::select('*')->with(['actor_film','actors'])
->whereMonth('films.created_at', '=', Carbon::now()->month)
->orderBy('films.created_at', 'desc')
->groupBy('films.name')
->get();
In App\Model\Film Model
namespace App;
use Illuminate\Database\Eloquent\Model;
class Film extends Model
{
//
protected $primaryKey = "id"; //primary key
protected $table = 'film';
public function actor_film(){
return $this->belongsTo('App\Model\ActorFilm','film_id','id');
}
public function actors(){
return $this->hasMany('App\Model\Actors','id','actor');
}
}
How can I make this query in Laravel, using Eloquent ORM?
select * from posts p order by ( select count(*) from likes where flag = 'c' and p.id = post_id ) Desc limit 3
I have this relationship in my models
Post.php
public function likes(){
return $this->hasMany('Like', 'post_id');
}
Like.php
public function post(){
return $this->belongsTo('Post', 'post_id');
}
Thanks! :)
You may try something like this:
$posts = Post::leftJoin('likes', function($join) {
$join->on('posts.id', '=', 'likes.post_id')->where('flag', '=', 'c');
})
->select('posts.*', 'likes.post_id', DB::raw('count(likes.post_id) as pCount'))
->groupBy('post_id')
->orderBy('pCount', 'desc')
->take(3)
->get();