Please help me want to left join two table in Codeigniter with Orm docrtrine 2 libray.
Doctrine entity model doesn't give association for one to many and vice-versa. To allow these feature you have to update your entities with valid association. Below is an example for such two tables which contains user information in users table and there favorite meals in UserFavoriteMeals
For Left JOIN update needed in both entities for association explained below :
In user entity add onetomany association of UserFavoriteMeals where mappedby is the key on basis of which association happens in db.
/**
* #var \Entity\UserFavoriteMeals
*
* #OneToMany(targetEntity="Entity\UserFavoriteMeals", mappedBy="userid" )
* #JoinColumns({
* #JoinColumn(name="id", referencedColumnName="userId", nullable=true)
* })
*/
private $UserFavoriteMeals;
Simillary, Put manyToOne association in UserFavoriteMeals entity
/**
* #var \Entity\Users
*
* #ManyToOne(targetEntity="Entity\Users")
* #JoinColumns({
* #JoinColumn(name="userId", referencedColumnName="id", nullable=true)
* })
*/
private $userid;
In these manner we have to manage associations for Left JOIN, now simply write a Left JOIN query in below format :
$left_query = $this->em->createQuery("SELECT fm,u FROM Entity\userFavoriteMeals fm LEFT JOIN fm.userid u WHERE fm.userId = 231 ")->getArrayResult();
print_r($left_query);
$left_query_inverse = $this->em->createQuery("SELECT u,fm FROM Entity\Users u LEFT JOIN u.UserFavoriteMeals fm WHERE u.id = 4")->getArrayResult();
print_r($left_query_inverse);
First you need to integrate Doctrine into CodeIgnitor.
http://docs.doctrine-project.org/en/2.0.x/cookbook/integrating-with-codeigniter.html
This is how you use custom query to left join two tables in Doctrine.
<?php
$query = $em->createQuery('SELECT u.id, a.id as article_id FROM CmsUser u LEFT JOIN u.articles a');
$results = $query->getResult(); // array of user ids and every article_id for each user
More on custom query :- http://docs.doctrine-project.org/en/2.1/reference/dql-doctrine-query-language.html
If you want DQL way, which is preferred, it should be something like this.
$qb->select('u')
->from('Entity_User', 'u')
->leftJoin('u.profile','p')
->leftJoin('a.user_details','ud')
->where('u.id = :id')
->setParameter('id','100')
->getQuery();
More on DQL :- http://docs.doctrine-project.org/en/2.0.x/reference/query-builder.html
I hope this helps,
Cheers!
Related
everybody!
What should I do if I need to make select from junction table?
For example, I develop project and I need to make chats between users. I have two entities: User and Chat, and many-to-many relation between them (accordingly, I have three tables: user, chat, chat_user). I try to get all chats, which user is member, and to get all users from these chats.
I made the following SQL query:
SELECT *
FROM chat c
INNER JOIN chat_user cu ON c.id = cu.chat_id
INNER JOIN user u ON u.id = cu.user_id
WHERE c.id IN (SELECT chat_id
FROM chat_user
WHERE user_id = <idUser>);
But I don't know how to translate in DQL subquery SELECT chat_id FROM chat_user WHERE user_id = <idUser>, because a haven't additional entity for table chat_user.
And I tried to add entity ChatUser and get data in ChatRepository smt. like this:
public function getChatsData($idUser)
{
$subQuery = $this->getEntityManager()
->getRepository(ChatUser::class)
->createQueryBuilder('chus')
->select('chus.chat')
->andWhere('chus.user = :idUser')
->setParameter('idUser', $idUser)
;
$qb = $this->createQueryBuilder('c');
return $qb
->innerJoin('c.chatUsers', 'cu')
->addSelect('cu')
->innerJoin('cu.user', 'u')
->addSelect('u')
->innerJoin('c.messages', 'm')
->addSelect('m')
->andWhere('u.id = :idUser')
->andWhere($qb->expr()->in(
'c.id',
$subQuery->getDQL()
))
->setParameter('idUser', $idUser)
->getQuery()
->getResult()
;
}
but it doesn't work. I get error [Semantical Error] line 0, col 12 near 'chat FROM App\Entity\ChatUser': Error: Invalid PathExpression. Must be a StateFieldPathExpression.
Have Doctrine standard tools for such tasks?
Using spatie/laravel-tags plugin (https://docs.spatie.be/laravel-tags/v2/basic-usage/using-tags) in my Laravel 5.7 app.
My Vote model (app/Vote.php) has tags:
<?php
namespace App;
use DB;
use App\MyAppModel;
...
use Spatie\Tags\Tag as SpatieTag;
use Spatie\Tags\HasTags;
class Vote extends MyAppModel
{
use HasTags;
protected $table = 'votes';
protected $primaryKey = 'id';
and I try by found Tag get all related Votes, which has this tag, like:
$activeTag = Tag::containingSlug($tag_slug)->first();
$tagRelatedVotes= Vote::withAnyTags( [$activeTag->slug], 'votesTagType' )->get();
But tagRelatedVotes is empty and looking at sql trace I see next:
SELECT *
FROM `tags`
WHERE LOWER(JSON_EXTRACT(slug, "$.en")) like '"%animals%"' limit 1
SELECT *
FROM `tags`
WHERE `name`->'$."en"' = '{"en": "animals"}' AND `type` = 'votesTagType' limit 1
SELECT *
FROM `votes`
WHERE
EXISTS ( SELECT *
FROM `tags`
INNER JOIN `taggables` on `tags`.`id` = `taggables`.`tag_id`
WHERE `votes`.`id` = `taggables`.`taggable_id` AND `taggables`.`taggable_type` = 'App\Vote' AND `id` in (''))
The 1st statement find the row, but the second statement finds nothing and that is strange why name field is used in request ?
So the 3rd statement is invalid. Which is the valid way?
MODIFIED BLOCK # 2:
Thank you for your feedback!
I tried as you wrote, but I got empty results.
I sql trace I see next:
SELECT *
FROM `tags`
WHERE LOWER(JSON_EXTRACT(slug, "$.en")) like '"%thriller%"' limit 1
SELECT *
FROM `tags`
WHERE `name`->'$."en"' = '{"en": "Thriller"}' AND `type` = 'votesTagType' limit 1
SELECT *
FROM `votes`
WHERE
EXISTS ( SELECT *
FROM `tags`
INNER JOIN `taggables` on `tags`.`id` = `taggables`.`tag_id`
WHERE `votes`.`id` = `taggables`.`taggable_id` AND `taggables`.`taggable_type` = 'App\Vote' AND `id` in (''))
The 1st statement returned 1 row, but the second returned nothing, but I have 1 row with name= 'Thriller' and type = 'votesTagType'.
I am not sure what expression
`name`->'$."en"' = '{"en": "Thriller"}'
means, that is beyond my mysql expierence. CXan it be some mysql or this plugin options?
I have :
SELECT version() : 5.7.23-0ubuntu0.18.04.1
Thanks!
You have to pass the name of the Tag to the withAnyTags() method. docs
$activeTag = Tag::containingSlug($tag_slug)->first();
$tagRelatedVotes= Vote::withAnyTags( [$activeTag], 'votesTagType' )->get();
I have 2 tables SjohlLBzads_products & SjohlLBzads_products_meta connected by column (post_id) as foreign key.
How do I create queries on multiple tables ?
Controller function which I have right now only makes query to a single table (SjohlLBzads_products).
I would like to display shipping column in SjohlLBzads_products_meta together with other columns from the current table.
public function index(){
$this->load->library('lib_pagination');
$pg_config['sql'] = "SELECT * from SjohlLBzads_products";
$pg_config['per_page'] = 50;
$data = $this->lib_pagination->create_pagination($pg_config);
$this->load->view("product_listing", $data);
Thanks!
Use a JOIN statement
$pg_config['sql'] = "SELECT * FROM SjohlLBzads_products
JOIN johlLBzads_products_meta
ON johlLBzads_products.post_id = johlLBzads_products_meta.post_id ";
I have a standard many-to-many relationship set up. Entity A can have many of Entity B, and vice versa.
I'm trying to get a list of all Entity A that do NOT have any corresponding Entity B. In SQL, I'd run a query like this:
SELECT a.* FROM entity_a a LEFT JOIN a_b r ON r.AID = a.id WHERE r.BID IS NULL
In this query, a_b is the linking table.
I'm trying to write a DQL statement (or use some other method) to get the same result, but the following does not work:
SELECT s FROM VendorMyBundle:EntityA s LEFT JOIN VendorMyOtherBundle:EntityB u WHERE u IS NULL
How can I achieve what I'm trying to do?
First, I have to underline that usually you should JOIN on the property of the entity (i.e. s), e.g. instead of:
SELECT s FROM VendorMyBundle:EntityA s
LEFT JOIN VendorMyOtherBundle:EntityB u WHERE u IS NULL
you should have something like:
SELECT s FROM VendorMyBundle:EntityA s
LEFT JOIN s.mylistofb u WHERE u IS NULL
where I'm supposing that in entity A you have defined your relationship as:
class A{
// ...
/**
* #ManyToMany(targetEntity="Vendor\MyBundle\Entity\EntityB")
* #JoinTable(name="as_bs",
* joinColumns={#JoinColumn(name="a_id", referencedColumnName="id")},
* inverseJoinColumns={#JoinColumn(name="b_id", referencedColumnName="id", unique=true)}
* )
**/
private $mylistofb;
This stated, if the query is not working yet, then try the following:
SELECT s FROM VendorMyBundle:EntityA s
WHERE SIZE(s.mylistofb) < 1
It is simplest than the previous and also comes from the official docs (i.e. see "phonenumbers example").
I have three tables:
Clients: (id, name, ...)
Files: (id, filename, type, data)
and join table:
Clients2Files (id, id_clients, id_files, created_at, deleted_at)
in php class Clients I want to get access to all client's files, but only to the files that hasn't been deleted (in sql speak WHERE deleted_at IS NULL)
Now I have code like this (in entity class Client), which selects all (even deleted) files:
/**
* #ManyToMany(targetEntity="File")
* #JoinTable(name="Clients2Files",
* joinColumns={#JoinColumn(name="id_clients", referencedColumnName="id")},
* inverseJoinColumns={#JoinColumn(name="id_files", referencedColumnName="id")}
* )
*/
private $files;
How can I add condition WHERE deleted_at IS NULL to this doctrine code? To select only files that are not "deleted".
The annotations you added don't actually "SELECT" anything. All they do is tell Doctrine about your objects and their relations. What you want to do is:
$qb = $em->createQueryBuilder();
$qb->select('clients, files')
->from('Clients', 'clients')
->join('c.files', 'files')
->where('files.deleted_at IS NULL');
If you find yourself doing this often, and are using Doctrine 2.2+, you can take a look at filters: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/filters.html