Doctrine Query builder get field of foreign entity - mysql

I have a query like :
$qb = $this->createQueryBuilder('m');
$qb->select('m.id', 'IDENTITY(m.home)');
return $qb->getQuery()->getResult();
m.home field is a foreign key to another table (This other table has a field ID and another name).
With this I get Id of m and id of the foreign key.
How can I get the name field of my other instead of id ?

You can fetch the data of the associated entity with a join:
SELECT m.id, home.name
FROM YourEntity AS m
JOIN m.home AS home

Use a leftJoin to get data from a relationship:
$qb = $this->createQueryBuilder('m');
$qb = $qb->leftJoin('AppBundle\Entity\Home', 'h');
$qb->select('m.id', 'IDENTITY(m.home)', 'h.name');
return $qb->getQuery()->getResult();
Replace 'AppBundle\Entity\Home' by the namespaced class of your entity "home".

Related

Laravel GroupBy and Count using eloquent model

I have a table
'new_comments'
with fields
id,user_id,
title,
comment_description
I have another table named
'comments_upvote'
having
field user_id,
post_id,
likes
id of new_comments and post_id of comments_upvote table are same. we have to take those comments which have the most likes. how we fetch that data.
$ud = Comments_upvote::select('post_id')->groupby('post_id')-
>orderby(DB::raw('count(likes)'), 'desc')->get();
$postid = array();
foreach ($ud as $key => $value) {
$postid[] = $value->post_id;
}
$data = DB::table('new_comments')->whereIn('id',$postid)->get();
but the problem is that i have to count all likes whose value = 1 how can we do that.
If you showed us some code you'd get a more concrete answer, but here's a quick outline of what you need: define your relationships (make sure you use your custom foreign key), use whereHas, group by post_id count, and sort by count descending.
So I'm guessing you have at least two models NewComment and CommentUpvote (you should). In the NewComment define a 1:n relationship:
public function upvotes(){
$this->hasMany('App\CommentUpvote', 'post_id');
}
Then in your controller (again, guessing, since you didn't show any code):
$bestComments = NewComment::whereHas('upvotes', function($query){
$query->select('post_id', DB::raw('count(*) as total'))->groupBy('post_id')->orderBy('total', 'desc');
})->get();
Disclaimer: this is untested and off the top of my head, but should nugde you in the right direction.

How to specify value in model relation keys?

I have tables user and profile,
one user has max one profile,
and is specified by user_id and table name in profile.
I do not use foreign keys there.
The reason I do it this way, is because I have other tables like company which also uses table profile, so reference is specified by relation_id = primary key of related table and relation = table name
profile
relation_id
relation
What I want to achieve is to set model relation to be equal to string user, so not to use key there, but to use value instead.
User.php
public function getProfile()
{
return $this->hasOne(Profile::className(),
['relation_id' => 'user_id', 'relation' => User::tableName()]);
}
Error I get:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'user.user' in 'on clause'
The SQL being executed was:
SELECT COUNT(*) FROM `user_login`
LEFT JOIN `user` ON `user_login`.`user_id` = `user`.`user_id`
LEFT JOIN `profile` ON `user`.`user_id` = `profile`.`relation_id`
AND `user`.`user` = `profile`.`relation`
It is for generating GridView so sql fails on count first, but error would be the same for select *
SQL I want to achieve:
SELECT * FROM `user_login`
LEFT JOIN `user` ON `user_login`.`user_id` = `user`.`user_id`
LEFT JOIN `profile` ON `user`.`user_id` = `profile`.`relation_id`
AND `profile`.`relation` = 'user'
So the question is, How to specify value in model relation keys?
if your User has a relation hasOne with profile you should use only
public function getProfile()
{
return $this->hasOne(Profile::className(),
['relation_id' => 'user_id']);
}
and if you need a on condition use
public function getProfile()
{
return $this->hasOne(Profile::className(),
['relation_id' => 'user_id'])->andOnCondition(['relation' => User::tableName()]);
}

How to fetch records from two different tables in laravel5.2

I have two tables 'approval' and 'renewal', both having a common column 'applicant_id'.
When new application comes-in, it stores a data-record in table 'approval' alongwith the 'applicant_id' for whom the record has been added.
Now, when there is a renew applied for that same applicant, the row gets created in the table 'renewal' referencing the 'applicant_id'
Note: There can be a single record in the table 'approval' for a 'applicant_id' but there can be more than one record for the same 'applicant_id' in the table 'renewal'.
Now, my requirement is:
I need to fetch the records from both the table for all the applicants.
Conditions: If there is a data for the 'applicant_id' in both the table and 'renewal' table has multiple row for the same 'applicant_id', then I need to get the records from 'renewal' table only that too the latest one.
If there is no data in 'renewal' table but exists in 'approval' table for the 'applicant_id', then the fetch record should get the data present in 'approval' table.
Basically, if there is record for the applicant in 'renewal' table, get the latest one from there, if there is record present only in 'approval' table, then get that one but the preference should be to get from 'renewal' if exists.
I am trying to do this in laravel 5.2. So, is there anyone who can help me in this?
If you're using Eloquent, you'll have 2 models:
Renewal.php
<?php
namespace App;
use Illuminate\Eloquent\Model;
class Renewal extends Model
{
protected $table = 'renewal';
public static function findMostRecentByApplicantId($applicantId)
{
$applicant = self::where('applicant_id', '=', $applicantId)
->orderBy('date_created', 'desc')
->first();
return $applicant;
}
}
Approval.php
<?php
namespace App;
use Illuminate\Eloquent\Model;
class Approval extends Model
{
protected $table = 'approval';
public static function findByApplicantId($applicantId)
{
$applicant = self::where('applicant_id', '=', $applicantId)
->first();
return $applicant;
}
}
Then, in the code where you want to get the approval/renewal record, use the following code:
if (! $record = Renewal::findMostRecentByApplicantId($applicantId)) {
$record = Approval::findByApplicantId($applicantId);
}
//$record will now either contain a valid record (approval or renewal)
//or will be NULL if no record exists for the specified $applicantId
After few try, I got one way to do it using raw:
SELECT applicant_id, applicant_name, applicant_email, applicant_phone, renewed, updated_at
FROM (
SELECT renewal_informations.applicant_id, renewal_informations.applicant_name, renewal_informations.applicant_email, renewal_informations.applicant_phone, renewal_informations.renewed, renewal_informations.updated_at
FROM renewal_informations
UNION ALL
SELECT approval_informations.applicant_id, approval_informations.applicant_name, approval_informations.applicant_email, approval_informations.applicant_phone, approval_informations.renewed, approval_informations.updated_at
FROM approval_informations
) result
GROUP BY applicant_id
ORDER BY applicant_id ASC, updated_at DESC;
For every single Approval id, there can b multiple records for renewal table suggests you have One to Many relation. which you can define in the your Model like
Approval.php (App\Models\Approval)
public function renewal()
{
return $this->hasMany('App\Models\Renewal', 'applicant_id')
}
Having defined this relation. you can get the records from the table using applicant_id.
$renewal_request_records = Approval::find($applicant_id)->renewal();
This will get all records from renewal table against that applicant_id.
Finding the latest
$latest = Renewal::orderBy('desc', 'renewal_id')->first();
Further Readings Eloquent Relations

How to join a many to many relationship

Entities :
Model
Category
Keyword
Model has a many to many relationship to keyword as well as category has a many to many relationship to keyword.
The orm generates following tables
model
category
keyword
keyword_model
keyword_category
When a category is given, how can I get all models related to this category? I would do it like this
get all keyword id's from keyword_category by category.id
join the result with the keyword_model table
the result of the join should be all relevant model id's
Since symfony2 deals with entities and not tables it seems hard to create a mysql query. I tried with something like
SELECT x,y FROM MyBundle:Category x, MyBundle:Model y
JOIN x.keywords
JOIN y.keywords
WHERE
x.id = " . $category . "
however this is invalid mysql syntax. Any ideas how to get the models here?
You could try the following:
SELECT
y
FROM
MyBundle:Model y
WHERE
EXISTS (
SELECT
x
FROM
MyBundle:Category x
JOIN
x.keywords xk
WHERE
xk MEMBER OF y.keywords AND
x = :category
)
Or if your relations are bidirectional:
SELECT
y
FROM
MyBundle:Model y
JOIN
y.keywords yk
JOIN
yk.categories c
WHERE
c = :category
From a given category (I suppose that you have the id)
$category_repo = $this->getDoctrine()->getManager()->getRepository('YourBundleName:Category');
$category = $category_repo->findOneById($id); //$id is your entity id
$keywords = $category->getKeywords(); //getKeywords() is the name of the method that you should have inside your class
$models = new ArrayCollection(); //or use a simple array
foreach($keywords as $keyword) {
foreach($keyword->getModels() as $model) {
$models->add($model);
}
}
however use sql directly should be more performing as you'll do a single query instead of a query (lazy-loading concept) for each object

Get Unique rows using Entity framework

I am using 3 tables to set roles for users.
1. module
Id, Name
2. actions
Id , Name ,ModuleId (Foreign key with modules)
3. userActions
Id,UserId,ActionId (Foreign key with actions)
I want to get the unique list of modules for a user from the userActions table . I am using Entity Framework and my database is Mysql
I used the query
var result = (from p in my_accountEntities.useractions
where p.UserId == item.Id
select p.action.module).ToList();
List<module> modules = new List<module>();
if (result != null)
{
modules = (List<module>)result;
}
Its not returning a Unique list , but its returning all the rows in Useraction table.
How can i get the unique list of modules(based on moduleId)
try using the linq .Distinct() extension method
var result = (from p in my_accountEntities.useractions
where p.UserId == item.Id
select p.action.module)
.Distinct().ToList();