Symfony query ids from ManyToMany relation table for every entity item - php

I have two entities Article and Tag with a Many to Many relation. For a bulk edit I query some attributes from every Articles. In that query I also want to query all assigned Tag-IDs from every Article.
I read something about the function GROUP_CONCAT() but Doctrine doesn't support that function yet.
My Doctrine statement is currently like that:
$this->getEntityManager()->createQuery('SELECT e.articleId, e.articleTitle, t.tagId FROM App\Entity\Article e LEFT JOIN e.tags t');
It would be best to fetch those assigned Tag-IDs as an array.

So I extended Doctrine with GROUP_CONCAT function from github.com/beberlei/DoctrineExtensions and use following code to get all IDs as an array:
$query = $this->getEntityManager()->createQuery('SELECT e.articleId, e.articleTitle, GROUP_CONCAT(t.tagId) AS tagIds FROM App\Entity\Article e LEFT JOIN e.tags t GROUP BY e.articleId');
$articleArray = $query->execute();
for ($i = 0; $i < count($articleArray); $i++) {
if (strpos($articleArray[$i]['tagIds'], ',')) {
$arr = array_map('intval', explode(',', $articleArray[$i]['tagIds']));
$articleArray[$i]['tagIds'] = ($arr) ? $arr : [];
}
elseif (!is_null($articleArray[$i]['tagIds'])) $articleArray[$i]['tagIds'] = [(int) $articleArray[$i]['tagIds']];
else continue;
}

Related

doctrine select in new object

I'm trying to select multiples objects in a single array result, but i cant see how to select it ...
Well actually I have this DQL:
$dql = ' SELECT obj AS Object1, objExternalRef AS Object2 FROM MyEntity1 AS obj
INNER JOIN obj.objChild AS objChild
INNER JOIN MyEntity2 AS objExternalRef WITH objExternalRef.objChild= objChild
WHERE something
';
$result = $em->createQuery($dql)
->setParameter( ... )
->setHint(\Doctrine\ORM\Query::HINT_FORCE_PARTIAL_LOAD, 1)
->getResult();
returning this array[ Object1 , Object2, Object1, Object2, ... ]:
{
"Object1": {...}
},
{
"Object2": { ...}
},
And i would like to encapsule this in a new object containing theses 2 objects like:
{
"Object1" : { ... },
"Object2" : { ... }
},
{
"Object1" : { ... },
"Object2" : { ... }
},
I think I need to make a select of this select(query) to group theses 2 object in a new object, but i can't figure out how to make it.
I also know that if i just make a for($i = 0; i < sizeof($result); i += 2) i can concat these 2 objs in a new one, but I don't think this is so far a nice fix.
Can someone give-me a light here?
If these two objects are related good practice will be to define this association mapping ie one to many or many to one in your entity relationship. For example
In country entity/object --(of course also defined on state side)
/**
* #ORM\OneToMany(targetEntity="State", mappedBy="stateCountry")
*/
private $states;
You can simply do a
$country->getStates()
See Doctrine Association mapping for more
However if they are not and you want mixed results you will need to use result set mapping/scalar results. I usually use native queries for something like this. For example
$rsm = new ResultSetMapping();
$rsm->addScalarResult('name', 'name');
$rsm->addScalarResult('id', 'id');
$rsm->addScalarResult('slug', 'slug');
$rsm->addScalarResult('num', 'num');
$sql = "SELECT f.name, f.id, f.slug, COUNT( t.demo_id ) AS num FROM tag_demos t LEFT JOIN tag f ON f.id = t.tag_id " .
" GROUP BY t.tag_id ORDER BY COUNT( t.demo_id ) DESC LIMIT 20";
$query = $this->getEntityManager()->createNativeQuery($sql, $rsm);
return $query->getResult();
See Native Query-Result Set Mapping for more examples.

Selecting a single column from model to controller in codeigniter3.0.0

I am new in codeigniter.
I need only the available column from the model than what code I write in the controller to get a single column
My model code is:
public function check_reservation($restaurant_id,$date,$people,$start_time,$end_time){
$sql="SELECT
r.restaurant_id,r.restaurant_name,r.capacity,rs.start_time,rs.end_time,rs.people,rs.date,r.capacity - SUM(IFNULL(rs.people,0)) AS available FROM restaurant r
LEFT JOIN reservation rs ON r.restaurant_id = rs.restaurant_id
AND ".$date." = rs.`date`
AND ".$people." = rs.`people`
AND '".$start_time."' = rs.`start_time`
AND '".$end_time."' = rs.`end_time`
WHERE r.restaurant_id = ".$restaurant_id."
GROUP BY r.`restaurant_id`";
$query=$this->db->query($sql);
return $query->result();
}
Thank you
It's not clear what you need. If you want to get only one column in the Controller, when you iterate with foreach (or for), you ask for your column name.
foreach ( $records as $record ) {
echo $record['restaurant_name'];
echo "<br/>";
}

Doctrine get entity with item

I want to get the field of an entity that is associated with another .
My entity Offers has a last_offer field.
Offers is related to the Products entity.
Then , with a consultation in my entity Products, I want to get the latest offer associated with the entity Offer.
Controller:
public function lastAction($key)
{
$em = $this->getDoctrine()->getManager();
$last_offer = $em->getRepository('MyAppBundle:Products')->findOfferByKey($key);
$response = new JsonResponse();
return $response->setData($last_offer);
}
My repository:
public function findOfferByKey($key){
$em = $this->getEntityManager();
$dql = 'SELECT pr, of FROM MyAppBundle\AppBundle\Entity\Products pr
INNER JOIN pr.offers of
WHERE pr.key = :key';
$query = $this->getEntityManager()
->createQuery($dql)
->setParameter('key', $key)
->setHydrationMode(\Doctrine\ORM\Query::HYDRATE_ARRAY);
return $query->execute();
}
My routing:
last_offer:
path: /{key}/last_offer
defaults: { _controller: "MyAppBundle:Products:last" }
But, this return an array.
I want to return only last_offer element.
Or to return the entity offers without being in an array.
You're specifically telling doctrine to generate/return an array with this line
->setHydrationMode(\Doctrine\ORM\Query::HYDRATE_ARRAY);
I think all you need to do is remove that line and doctrine will generate/return entities instead. However, you will get a Collection back, so make sure to take that into account. Perhaps something like
public function findOfferByKey($key) {
$dql = 'SELECT pr, of FROM MyAppBundle\AppBundle\Entity\Products pr
INNER JOIN pr.offers of
WHERE pr.key = :key';
$query = $this->getEntityManager()
->createQuery($dql)
->setParameter('key', $key)
;
$results = $query->execute();
if (count($results) !== 1)
{
// It's up to you how to handle zero or multiple rows
}
return $results->current();
}
EDIT
I see what's happening - I wasn't paying attention to your SELECT caluse. You're not selecting just the last_offer columns, you're selecting the entirety of the Products and Offers entities = $results is going to be an array of all of these together. In this scenario, $query->execute() will return an array() instead of a collection.
If you want to select just the Offer entities, you need to modify the SELECT
$dql = 'SELECT of
FROM MyAppBundle\AppBundle\Entity\Products pr
INNER JOIN pr.offers of
WHERE pr.key = :key';
But be wary that this still may return more than one row.

query to select from two tables on symfony

I am learning symfony framework. Now I am getting all data from mysql table orders this way:
$c = new Criteria();
$this->items = OrdersPeer::doSelect($c);
Also I have other table orders_complete. How can I get data from tables orders and orders_complete?
I want to do this query:
SELECT * FROM orders, orders_complete WHERE orders.id =
orders_complete.id
If I remember right, with propel you should be able to do something like :
$c = new Criteria();
$orders = OrdersPeer::doSelect($c);
foreach($orders as $order) {
$complete = $order->getOrderCompletes();
// do something with $order and $complete ...
}
This providing that you have defined the two tables relationship within your schema file...
Do check the propel documentation regarding this : http://propelorm.org/documentation/04-relationships.html#using-relationships-in-a-query

Select posts based on selected categories

I have following scenario:
user selects couple categories
user should see posts which belongs to these categories
post belong to one or more categories
I setup the database like this:
users -> category_user <- categories
posts -> categoriy_post <- categories
I managed to accomplish this, but I had to find all ids from these tables to find relevant posts. I need to make it simpler because this approach is blocking some other actions I need to do. This is my code:
$categoryIds = Auth::user()->categories;
$ids = array();
$t = array_filter((array)$categoryIds);
if(!empty($t)){
foreach ($categoryIds as $key => $value) {
$ids[] = $value->id;
}
}else{
return View::make("main")
->with("posts", null)
->with("message", trans("front.noposts"))->with("option", "Latest");
}
$t = array_filter((array)$ids);
if(!empty($t)){
$p = DB::table("category_post")->whereIn("category_id", $ids)->get();
}else{
return View::make("main")
->with("posts", null)
->with("message", trans("front.noposts"))->with("option", "Latest");
}
$postsIds = array();
foreach ($p as $key => $value) {
$postsIds[] = $value->post_id;
}
$t = array_filter((array)$postsIds);
if(!empty($t)){
$postIds = array_unique($postsIds);
$posts = Post::whereIn("id", $postsIds)
->where("published", "=", "1")
->where("approved", "=", "1")
->where("user_id", "!=", Auth::user()->id)
->orderBy("created_at", "desc")
->take(Config::get("settings.num_posts_per_page"))
->get();
return View::make("main")
->with("posts", $posts)->with("option", "Latest");
}else{
return View::make("main")
->with("posts", null)
->with("message", trans("front.noposts"))->with("option", "Latest");
}
How to do this properly without this bunch code?
Yes, there is Eloquent way:
$userCategories = Auth::user()->categories()
->select('categories.id as id') // required to use lists on belongsToMany
->lists('id');
if (empty($userCategories)) // no categories, do what you need
$posts = Post::whereHas('categories', function ($q) use ($userCategories) {
$q->whereIn('categories.id', $userCategories);
})->
... // your constraints here
->get();
if (empty($posts)) {} // no posts
return View::make() ... // with posts
Or even better with this clever trick:
$posts = null;
Auth::user()->load(['categories.posts' => function ($q) use (&$posts) {
$posts = $q->get();
}]);
if (empty($posts)) // no posts
return View... // with posts
Obviously, you can write joins, or even raw sql ;)
You can take those categories directly from the database from user records:
SELECT ...
FROM posts AS p
INNER JOIN category_post AS cp ON cp.id_post = p.id
INNER JOIN categories AS c on c.id = cp.id_category
INNER JOIN category_user AS cu ON cu.id_category = c.id
WHERE cu.id_user = 123 AND p.published = 1 AND ...
Joins in Laravel can be achieved, see the documentation: laravel.com/docs/queries#joins Maybe there is also an Eloquent way, I don't know, try searching :-)

Categories