I used to get my data using this command so the first array is for find variable and the second array is for the order.
So I need to order with specific column:name of test(that is an object that has many columns: id/name ) But I dont know how !! when I enter _test.name I get unrecognized field
->findBy(
array('_id' => $id),
array('_test' =>'ASC')
);
class model1
{
private $_idModel1;
/**
*
* #ORM\ManyToOne()
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="id1",
* referencedColumnName="id2")
* })
*/
private $_test;
}
You cannot order using a relation with the findBy, but you can do it creating a query builder:
$model1Repository->createQueryBuilder('model1')
->leftJoin('model1._test', 't')
->where('model1._id = :id')
->setParameter('id', $id)
->orderBy('t.name', 'ASC');
The code has not been tested, you should adapt it to your code.
It creates a query builder over the model1 class , then joins it with your ManyToOne relation, filters via _id and then orders the result by the _test relation using the name field.
Aslo you need to declare in the #ManyToOne the target entity (https://www.doctrine-project.org/projects/doctrine-orm/en/2.8/reference/association-mapping.html#many-to-one-unidirectional)
#ManyToOne(targetEntity=TheNameOfTheTestClass)
Related
I have trouble with writing Doctrine Query Builder.
I have a Posts table which is related to the AccountToken table like:
class Posts
/**
* #ORM\ManyToOne(targetEntity="App\Entity\AccountToken")
* #ORM\JoinColumn(name="account_token_id", referencedColumnName="uuid", nullable=false)
*/
protected $accountTokenId;
I am writing a query builder where I want to pull all the results which are related to that table via UUID and have a specific status. The type value is defined in the AccountToken table.
In that table, type has relation also and it's defined in AccountToken table:
class AccountToken
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Types")
* #ORM\JoinColumn(name="type_id", referencedColumnName="id", nullable=false)
*/
protected $type;
It's a tricky one for me because I have to relations.
Does someone know how to pull the results:
"Return me posts which have the type='success' value".
$this->createQueryBuilder('p')
->select('p')
->join('App\Entity\AccountToken', 'at', Expr\Join::WITH, 'at.uuid = p.accountTokenId')
->join('App\Entity\ChannelType', 'ct', Expr\Join::WITH, 'ct.id = at.type')
->where('p.accountTokenId = :accountTokenId')
->setParameter('successStatus', Types::STATUS_SUCCESS)
->getQuery()
->getResult();
This is my draft of how I am trying to accomplish it but as I am new with Doctrine, don't have an idea how to join a table that has value in its related table. It's confusing.
Firstly you don't have any parameter successStatus in your query.
I think you over complicate the things.
return $this->createQueryBuilder('p')
->leftJoin('p.accountToken', 'a')
->leftJoin('a.type', 'ct')
->where('ct.successStatus = :successStatus')
->setParameter('successStatus', Types::STATUS_SUCCESS)
->getQuery()
->getResult()
;
What I need :
I'm building an API that returns users and some relations : I have an entity called "User" which has a lot of relationships. Let's take the "comments" as example :
/**
* #ORM\OneToMany(targetEntity="Comments", mappedBy="idClient", cascade={"persist"})
*/
protected $comments;
In some cases, the client wants to get the user data and the comments data in the same query (by adding "comments" to the "include query param), and wants to sort the comments in a specific order. This order is provided by the client in the query params. In this example, the comments must be sorted by id ASC.
/api/users?include=comments&sort=comments.id
Note that order ASC is implicit in that case.
I have a search() function that build the query :
$qb = $this->createQueryBuilder($this->elementName);
/* SELECTs */
$selects = $this->getSelects($params);
foreach($selects as $select) {
$qb->addSelect($select);
}
/* WHEREs */
$wheres = $this->getWheres($params);
foreach($wheres as $where) {
$qb->andWhere($where);
}
/* ORDER BY */
foreach($sortBy as $column => $order) {
$qb->addOrderBy($column, $order);
}
/* LIMIT and OFFSET */
$qb->setFirstResult($offset)
->setMaxResults($limit);
$query = $qb->getQuery();
$results = $query->getResult();
This function is called to get the primary data of the request : the users data. Then, the users are transformed by a UserTransformer, in order to answer the client in a specific format (JSONAPI).
The relationships (as comments) are called later by querying the entity is the object transformer :
$comments = $user->getComments(); // Returning $this->comments in the User class.
return $this->collection($comments, new CommentsTransformer()); // sends the $comments data to the CommentsTransformer.
What I tried
I tried addOrderBy() to the query builder but I get an error because the DQL does not contains any association named comments.id :
Doctrine\ORM\Query\QueryException: [Semantical Error] line 0, col 110 near 'id ASC': Error: Class Foo\Users has no field or association named comments.id
Here is the DQL :
SELECT e FROM Foo\Users u WHERE [...] ORDER BY u.comments.id ASC
Is there any way I can "see" the comments properties and sort the comments on them in my Query ?
Or is there any way I can inject the sort order in my Users class so it can retrieve the comments data in that dynamical order ? like using $user->getComments($sortBy) and then catch the $sortBy in my Users class (or preferably on my entity mother class) and alter the build-in Doctrine request to add my sorting order ?
PS : sorry for (probably) bad english, it's not my mother tongue.
apply criteria in your getComments function like
use Doctrine\Common\Collections\Criteria;
public function getComments()
{
$criteria = Criteria::create()
->orderBy(['id' => Criteria::ASC]);
return $this->comments->matching($criteria);
}
Introduction
Hello. I'm currently building a FacebookFeedParser, and at the moment I'm trying to build a method in a Controller that lists the Facebook pages with the best post/like ratio from today to the user. To do that, I have built the following query in pure SQL
SELECT pa.facebook_name, COUNT(po.id) AS postCount, SUM(likes) AS likes, SUM(likes)/COUNT(po.id) AS likesPerPost
FROM facebook_posts po
INNER JOIN facebook_pages pa ON pa.id = po.facebook_page_id
WHERE CONVERT_TZ(`facebook_created_time`, 'UTC', 'Europe/Berlin') > '2015-07-16 00:00:00'
GROUP by facebook_page_id
ORDER BY SUM(likes)/COUNT(po.id) DESC;
What I now wanted to do, is to transform this query into Laravel/Eloquent.
Current state
I have the following classes in my project
Controllers: PageController, PostController
Models: FacebookPost, FacebookPage, BaseModel
The FacebookPost and FacebookPage model are both defining their relations like this
FacebookPage
/**
* Defines the relation between FacebookPage and FacebookPost
* One page can have multiple posts
*
* #see FacebookPage
* #see FacebookPost
*
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function posts()
{
return $this->hasMany(FacebookPost::class);
}
FacebookPost
/**
* Defines the association of this object with FacebookPage
* One facebook_post belongs to one facebook_page
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function page()
{
return $this->belongsTo(FacebookPage::class, 'facebook_page_id');
}
In the BaseModel, I have defined a scope, which will be used multiple times in the project
/**
* Query scope to get the database values for today
*
* #param $query
* #return mixed
*/
public function scopeToday($query)
{
return $query->whereRaw('CONVERT_TZ(`'. $this->createDateColumn .'`, "UTC", "'. env('APP_TIMEZONE') .'") > "' . Carbon::today()->toDateTimeString() . '"');
}
And this is the query I've built in order to get those posts, with the filters
$posts = App\Models\FacebookPost::with('page')
->selectRaw('COUNT(id) AS postCount, SUM(likes) AS likes, SUM(likes)/COUNT(id) AS likesPerPost')
->today()
->groupBy('facebook_page_id')
->orderByRaw('SUM(likes)/COUNT(id) DESC')
->get();
Problem
The problem I'm currently having, is, that, when I try to rebuild the above query, I'm not getting all fields I want. As soon as I add an select to the Builder, the relations array, with the index page is null. If I ommit the select method, I'm getting the FacebookPage, but I want to have those specific fields
Now I'm getting an object. I guess this is because I'm using the Eloquent Builder right? Isn't it somehow possible to only get the fields I want to have? The result I'm expecting should look like this (per row)
facebook_name | postCount | likes | likesPerPost
McDonalds 1000 500 0.5
I also tried it like this
$posts = App\Models\FacebookPost::with(['page' => function($query) {
$query->select('facebook_name');
}])
->selectRaw('COUNT(id) AS postCount, SUM(likes) AS likes, SUM(likes)/COUNT(id) AS likesPerPost')
->today()
->groupBy('facebook_page_id')
->orderByRaw('SUM(likes)/COUNT(id) DESC')
->get();
Would I need to use the DB class instead of Eloquent? Or what would be the best solution for this problem?
Alternative solution
$pages = DB::table('facebook_posts')
->select(DB::raw('facebook_pages.facebook_name, COUNT(facebook_posts.id) AS postCount, SUM(likes) AS likes, ROUND(SUM(likes)/COUNT(facebook_posts.id)) AS likesPerPost'))
->join('facebook_pages', 'facebook_posts.facebook_page_id', '=', 'facebook_pages.id')
->whereRaw('CONVERT_TZ(`'. $this->createDateColumn .'`, "UTC", "'. env('APP_TIMEZONE') .'") > "' . Carbon::today()->toDateTimeString() . '"')
->groupBy('facebook_page_id')
->orderByRaw('ROUND(SUM(likes)/COUNT(facebook_posts.id)) DESC')
->get();
This, however, works. Would this be the correct solution for my use case? I'm just asking if it even make sense to use Eloquent here, since I'm not really trying to get an object, but data from multiple sources.
If you want with('page') to work when you specify the list of fields to fetch using select() you need to make sure that the foreign key is in that list, otherwise Laravel is not able to fetch related models. So in your case make sure that page_id is fetched from the database.
I have an Alert Class with some data in it. I then have an Availability class. In my Availability class I have
/**
* #var \Nick\AlertBundle\Entity\Alert
*
* #ORM\ManyToOne(targetEntity="Nick\AlertBundle\Entity\Alert")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="availability_alert_id", referencedColumnName="id")
* })
*/
private $availabilityAlert;
So this is a foreign key back to my Alert class, linked to my Alerts class id.
I am now doing some work on the Availability data, so I have the DQL query
public function getAlertAvailability($id)
{
return $this->getEntityManager()
->createQuery(
'SELECT a.id, a.classLetter, a.flightNumber, a.alertPseudo, a.availability, a.lastUpdated
FROM NickAlertBundle:Availability a
WHERE a.availabilityAlert = :id
ORDER by a.classLetter, a.lastUpdated'
)
->setParameter('id', $id)
->getResult();
}
The way I call that is like this
public function getAvailabilityData(){
$alerts = $this->em->getRepository('NickAlertBundle:Alert')->getActiveAlertIds();
if (!$alerts) {
echo "No Availability";
}
foreach($alerts as $alert){
$alertId = (int)$alert['id'];
$allAvailability = $this->em->getRepository('NickAlertBundle:Availability')->getAlertAvailability($alertId);
}
}
So I essentially get all my active Alerts Ids, and then pass this to get my Availability for these individual Alerts.
Now I have a couple of problems.
Firstly, in the DQL query I make, I need to also get something from my Alert table (a field called command). How would I do a join in this query to get this piece of data?
Secondly, with the data that is returned, how do I access availabilityAlert in my Twig file?
UPDATE
Attempt at join
public function getAlertAvailability()
{
return $this->getEntityManager()
->createQuery(
'SELECT a.id, a.classLetter, a.flightNumber, a.alertPseudo, a.availability, a.lastUpdated, u.searchCommand
FROM NickAlertBundle:Availability a
JOIN a.availabilityAlert u
ORDER BY a.classLetter, a.lastUpdated'
)
->getResult();
}
Doctrine will load that entity as a proxy (for lazy loading) when the Availability entity is loaded.
You can access these via a normal getter / property access, but they will typically be lazy loaded by Doctrine. You can have them joined via a DQL query and the property will be hydrated with all the linked entities already loaded, see Improving Performance with a Join.
You can then access those associated entities in Twig as any other property.
I've got a Many-To-Many relation between two tables but I want to add a join condition on the join table.
/**
* #ManyToMany(targetEntity="Company", inversedBy="Accounts")
* #JoinTable(name="account_company",
* joinColumns = { #JoinColumn(name="account_id", referencedColumnName="id") },
* inverseJoinColumns = { #JoinColumn(name="company_id", referencedColumnName="id") }
* )
*/
protected $companies;
I would have a condition like "account_company.is_deleted = 0", how can I make it ?
Yes, you have the choice to hydrate your object and its ManyToMany collection using custom dql:
make a repository method that adds conditions on your join:
// repository class:
public function getAccountWithNonDeletedCompanies($id)
{
return $this->createQueyBuilder('account')
->leftJoin('account.companies', 'companies', 'WITH', 'companies.deleted = 0')
->andWhere('account.id = :id')
->setParameter('id', $account)
->getQuery()
->getOneOrNullResult()
;
}
From what I can understand, you never want to display deleted companies ? (soft delete).
In this case, you may want to use SQL Filters: http://blog.loftdigital.com/doctrine-filters-and-soft-delete
Have dealt with this before and the only solution I got was creating a custom function that will make the query.
So on your Entity create a custom function getCompanies().