Only join rows that meet certain criteria (left join of data that is left joined) - sql

I have users that have FacebookPage and Application entities associated to them. FacebookPage entities also have Application entities associated with them.
$qb = $this->createQueryBuilder('u')
->addSelect('p', 'a')
->leftJoin('u.facebook_pages', 'p')
->leftJoin('p.applications', 'a')
->leftJoin('a.editors', 'e', 'WITH', 'e = :user')
->where('u = :user')
->setParameter('user', $user)
->orderBy('p.name', $order)
;
$u = $qb->getQuery()->getSingleResult();
return $u->getFacebookPages();
I want to return all of the user's Facebook pages and then show a count of applications associated with that page. I only want to count the applications where the user is an editor.
When run my current query, the pages have a count with all the page's applications (so the count includes applications where the user is not an editor).
If I change the a.editors leftJoin to a join, I get the correct counts for the pages, but it only lists pages that actually have any applications.
How can I show all the pages and only join the applications where the user is an editor?

I solved this by adding a new query to get app ids for the applications where user is an editor.
$user_apps = $this->getEntityManager()->getRepository('Application')->getUserApps($user);
$app_ids = array();
foreach($user_apps as $app) {
$app_ids[] = $app->getId();
}
$qb = $this->createQueryBuilder('u')
->addSelect('p', 'a')
->leftJoin('u.facebook_pages', 'p');
if(count($app_ids)) {
// join with IN statement to include only apps where user is an editor
$qb->leftJoin('p.applications', 'a', 'WITH', sprintf('a.id IN (%s)', implode(',', $app_ids)));
} else {
// join empty anyway to avoid db calls when iterating over pages
$qb->leftJoin('p.applications', 'a');
}
$qb
->where('u = :user')
->setParameter('user', $user)
->orderBy('p.name', $order)
;
try {
$u = $qb->getQuery()->getSingleResult();
} catch (Exception $e) {
throw $e;
}
return $u->getFacebookPages();
This now returns all the user's Facebook pages and only join applications where user is an editor. I am probably going to change this to a DQL query so I can move the ids in IN to a subquery.

Related

Get user data from database codeignter

I have two tables in one database, table one called: ci_admin, and table two called active_ingredient.
I want to get user data from the active_ingredient table where user_id equals admin_id from ci_admin table using the current user session.
this code, get data for all user, I need the data inserted by the user only:
$wh =array();
$SQL ='SELECT * FROM active_ingredient';
$wh[] = "SELECT 1
FROM ci_admin
WHERE ci_admin.admin_id = active_ingredient.user_id";
if(count($wh)>0)
{ $WHERE = implode(' and ',$wh);
return $this->datatable->LoadJson($SQL,$WHERE);
}
else
{
return $this->datatable->LoadJson($SQL);
}
Try this, it will help you.
$this->db->select('ai.*,ca.*');
$this->db->from('active_ingredient ai');
$this->db->join('ci_admin ca', 'ca.admin_id = ai.user_id', 'left');
$this->db->where($data); //pass the session data for exact filter
$query = $this->db->get();
return $query->result();

Laravel/SQL: How to fetch data from multiple table in a single query? that too using 'where'

Working on a search functionality on Laravel App(Blog/Posts).
There are multiple types of posts (each having a separate table in the database)
Like Business posts, Social Life posts etc..
Below is the search function on SearchController
class SearchController extends Controller
{
public function search(Request $request, $query = null)
{
if($query == null)
return redirect()->route('home');
$search = Business::where([['title','like','%'.$query.'%'],['status','=',1]])
->orWhere([['description','like','%'.$query.'%'],['status','=',1]])
->paginate(10);
return view('front.search',[
'results' => $search,
'query' => $query
]);
}
}
So basically my question is how to add other types of Post's table also?
My main motive is that when someone searches for anything, the result should be fetched from all types of posts table(business, nature, life & so on..).
You have to maintain common id in both the table
NOTE: Join is the preferable method
$querys = DB::table('Business')->where([['Business.title','like','%'.$query.'%'],['Business.status','=',1]])
->orWhere([['Business.description','like','%'.$query.'%'],['Business.status','=',1]]);
$querys->join('socialtable','socialtable.userid','=','Business.userid');
// Just join the social table
$querys->where('socialtable.title', 'like','%'.$query.'%');
$result = $querys->paginate(10);
If you have a model called Book, like this:
class Book extends Model
{
/**
* Get the author that wrote the book.
*/
public function author()
{
return $this->belongsTo('App\Author');
}
}
Then you can retrieve all of your books with authors like this:
$books = App\Book::with(['author'])->get();
Check out Eager loading from Laravel documentation.
Just add table name before every field
$querys = DB::table('Business')->where([['Business.title','like','%'.$query.'%'],['Business.status','=',1]])
->orWhere([['Business.description','like','%'.$query.'%'],['Business.status','=',1]]);
$querys->join('socialtable','socialtable.userid','=','Business.userid');
// Just join the social table
$querys->where('socialtable.title', 'like','%'.$query.'%');
$result = $querys->paginate(10);

get user role by user id in moodle

I want to get user role from user id. I am using loop in my code where i want to show all user except admin. i used below code but its not working.
$context = get_context_instance (CONTEXT_SYSTEM);
$roles = get_user_roles($context, $USER->id, false);
$role = key($roles);
$roleid = $roles[$role]->roleid;
Its provide me blank array as like screenshot. Also below my all code.
https://prnt.sc/gq8p12
$allUsers = $DB->get_records('user');
$SQL = "SELECT * FROM `".$CFG->prefix."config` WHERE `name` LIKE 'siteadmins'";
$getSiteAdmins = $DB->get_record_sql($SQL);
$explodeAdminIds = explode(',', $getSiteAdmins->value);
$context = get_context_instance (CONTEXT_SYSTEM);
if(!empty($allUsers))
{
foreach ($allUsers as $allUser)
{
if(!in_array($allUser->id, $explodeAdminIds))
{
$roles = get_user_roles($context, $allUser->id, false);
$role = key($roles);
$roleid = $roles[$role]->roleid;
echo 'USER ID -- '.$allUser->id.' >>> ';
print_r($roles); echo '<br>';
$name = ''.$allUser->id.'_'.$allUser->firstname.' '.$allUser->lastname.'';
$confirmed = ($allUser->confirmed == 1) ? 'Active' : 'In-active';
$table->data[] = array(
$i,
$name,
'Team Name',
$allUser->email,
$allUser->phone1,
'Role',
$confirmed,
//empty($coachusrarr)?'--':implode(',',$coachusrarr),
//empty($tmpleaderarr)?'--':implode(',',$tmpleaderarr),
//$coach,
);
$i++;
}
}
}
The basic problem is that get_user_roles($context, $userid) will only get you a list of roles assigned at that particular context level. Very few users have roles assigned at the system context, it is much more usual for roles to be assigned at a course level. This allows users to have different roles in different courses (a teacher on one course, might be enrolled as a student on another course).
If you want to get all the roles for a user, then you're going to need to do something like this:
$roleassignments = $DB->get_records('role_assignments', ['userid' => $user->id]);
You can then loop through all the $roleassignments and extract the 'roleid' from them (alternatively, you could use the $DB->get_fieldset command, to extract the roleids directly).
Note also that you should be using context_system::instance() instead of the old get_context_instance(CONTEXT_SYSTEM) (unless you are using a very old and insecure version of Moodle).
For getting the site admins, use get_admins() (or, if you really want to access the config value, use $CFG->siteadmins).
If you want to get a user role for a course by user id then this script will help you.
$context = context_course::instance($COURSE->id);
$roles = get_user_roles($context, $USER->id, true);
$role = key($roles);
$rolename = $roles[$role]->shortname;

Codeigniter populate nested associations

this is the results i need from the database
{comment: 'hello there', user: [{name: 'sahan', id: 1}], id: 2}
function used to get comments
public function get_comments(){
$query = $this->db->get('comments');
return $query->result_array();
}
I have a comments table and a users table, When a user comments on something the
comment is saved as follows
comment > Comment text
user: userid
So when the data is shown I need codeigniter to populate the user field with the user data found from the users table
Does anyone know how to do this ?
I used this functionality in SailsJS but dont know how to do it here in CodeIG
Sails.js populate nested associations
Codeigniter 's active record is not as advanced as SailJS active record, but you can achieve what you are asking for with two queries within the same method.
I'm assuming the comments table has a foreign key to the users table through a user_id field.
public function get_comments() {
/* Get all the comments */
$query = $this->db->get('comments');
$comments = $query->result_array();
/* Loop through each comment, pulling the associated user from the db */
foreach $comments as &$comment {
$query = $this->db->get_where('users', array('id' => $comment['user_id']));
$user = $query->result_array();
/* Put the user's data in a key called 'user' within the comment array */
$comment['user'] = $user;
/* Remove the unnecessary user_id and $user variable */
unset($comment['user_id']);
unset($user);
}
return $comments;
}

Symfony2 + Doctrine - Filtering

I've got a OneToMany relationship where one football team has many players. I want to list all football teams and display the name of the captain for each team.
Each player entity has a foreign key (team_id) and a field 'captain' which is set to 0 or 1. I'm currently running the following query:
$teams = $this
->getDoctrine()
->getRepository('FootballWebsiteBundle:Team')
->createQueryBuilder('t')
->setFirstResult(($pageNumber * $resultPerPage) - $resultPerPage)
->setMaxResults($resultPerPage)
->add('where','t.deleted = 0')
->add('orderBy', 't.name DESC')
->getQuery()->getResult();
Then when I loop through each team in twig I run team.getTeamCaptain().getName() which is a filter within my Team entity:
public function getTeamCaptain() {
$them = $this->players->filter(function($p) {
return $p->getCaptain() == 1;
});
return $them->first();
}
Is there a better way to run this query?
First of all, you may want to fetch-join the players of each retrieved team to avoid having them lazy loaded during rendering of the template. Here's the DQL:
SELECT
t, p
FROM
FootballWebsiteBundle:Team t
LEFT JOIN
t.players p
WHERE
t.deleted = 0
ORDER BY
t.name DESC
Which can be built with following query builder API calls:
$teamsQuery = $this
->getDoctrine()
->getRepository('FootballWebsiteBundle:Team')
->createQueryBuilder('t')
->addSelect('p')
->leftJoin('t.players', 'p')
->add('where','t.deleted = 0')
->add('orderBy', 't.name DESC')
->getQuery()
Then you wrap this query into a Paginator object (since setMaxResults and setFirstResult cannot be trusted when fetch-joining):
$paginator = new \Doctrine\ORM\Tools\Pagination\Paginator($teamsQuery, true);
$teamsQuery
->setFirstResult(($pageNumber * $resultPerPage) - $resultPerPage)
->setMaxResults($resultPerPage)
In your view you can then iterate on the teams like following pseudo-code:
foreach ($paginator as $team) {
echo $team->getTeamCaptain() . "\n";
}
You can also gain some extra performance in your getTeamCaptain method by using the Selectable API:
public function getTeamCaptain() {
$criteria = new \Doctrine\Common\Collections\Criteria();
$criteria->andWhere($criteria->expr()->eq('captain', 1));
return $this->players->matching($criteria)->first();
}
The advantage here is mainly relevant when the association players is not yet initialized, since this will avoid loading it entirely. This is not the case, but I consider it a good practice (instead of re-inventing collection filtering logic).