$users = User::where('id', 'parent_id')->get();
The id and the parent_id are in the same table. I want to get all of the data from the users table where the id and parent_id are equal. How can I do that in Laravel?
The issue you are facing is that you want to know how to check if the user has no referrals. You can do it like this:
Add referrer Relation in your user model.
public function referrer()
{
return $this->hasOne(self::class, 'parent_id');
}
You can then query it like this:
User::doesntHave('referrer')->get();
You should try this:
$users = User::whereColumn('id', 'parent_id')->get();
Related
I have a table like this now what i want to do is count the records for each ID where STATUS is COMPLETED
.
Something like SELECT COUNT(*) FROM TABLE WHERE ID= foreach(ID)
AND STATUS=1
select id, count(id) as count from table where status='COMPLETED' group by id;
Basically you need to use group by clause in MySQL.
You can do it using Active Record as this:
I assuming you have you table model named like Job, then you can get a needed value as this:
$number = Job::find()->where(['STATUS' => 'Completed'])->count();
or it is always better to store constant properties in the model like this:
class Job extends ActiveRecord {
const STATUS_COMPLETED = 'Completed';
then your ActiveQuery will look like this:
$number = Job::find()->where(['STATUS' => Job::STATUS_COMPLETED])->count();
Also here is the full description: Querying Data
$any_var = Your_Table::find()->where(['status' => 'Cimpleted'])->select('id')->orderBy('id')->groupBy('id')->count ();
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
I built up a pivot table containing ids of tables I want to associate. When I have the id of a specific item, I now want to get the latest entry of this item saved in the pivot table. For example:
Table 1: Tickets
Table 2: Status
Table 3: Ticket_Status (Pivot)
If I add a new entry to the pivot table, I would have something like this:
Pivot
ticketId, statusId
1, 2
1, 3
2, 1
Now I want to receive the latest status in the pivot for Ticket Id 1 for example, so I expect to receive statusId 3 for ticket 1. But how do I do this in Laravel?
Creating the entries for the pivot table works:
public function attachDispatchStatus($id) {
$this->status()->attach($id);
$this->touch();
}
// set fields on the eloquent object and save to database
// raise event that the incident was created.
public function createDispatch($command) {
// Get BodyContent from POST Request
$this->dispatchReference = $command->dispatchReference;
$this->incidentReference = $command->incidentReference;
// Create new Dispatch
$dispatch = Dispatch::create(array(
'dispatch_reference' => $this->dispatchReference,
'incident_reference' => $this->incidentReference
));
$dispatchStatus = DispatchStatus::where('status', '=', 'processing')->first();
$dispatch->attachDispatchStatus($dispatchStatus->id);
return $this;
}
Why don't you use the updateExistingPivot($roleId, $attributes); available in Laravel 5 when editing your tickets ?
This will solve your problem and make your database lighter :)
Check Larvel Doc for some examples on pivot table.
If you don't want to make it like that (because you want to keep an historic of your input), I think you will have to add an dateTime field in your pivot table... Then, just order by date, and you will be fine.
This query gives a pagination of all 'albums' with a picture and description for each. Now I am trying to get always the latest picture of each album.
I have tried to add a second orderBy('pics.created_at') , but that did not work. I think I need some kind of subquery but don't know how.
$query = AlbumPic::select(DB::raw('COUNT(pics.id) as picscount,
pics.url,
pics.user_id,
pics.created_at,
albums.id as album_id,
albums.title,
albums.text,
users.username'))
->join('albums','albums.id','=','album_pic.album_id')
->join('pics','pics.id','=','album_pic.pic_id')
->join('users','users.id','=','pics.user_id');
if(!is_null($user_id))
$query->where('album_pic.user_id',$user_id);
$albums = $query->groupBy('albums.id')
->orderBy('albums.created_at','desc')
->paginate(20);
edit
I made a mistake. I don't have created_at and updated_at in the album_pic table .
So my 'Album' - model/relations are now like this:
public function pics()
{
return $this->belongsToMany('Pic');
}
public function latestPic()
{
return $this->belongsToMany('Pic')->latest('pics.created_at');
}
And the query now looks like this:
$q = Album::with('pics')->with('latestPic.users');
if(!is_null($user_id))
$q->where('albums.user_id',$user_id);
$albums = $q->orderBy('albums.created_at','desc')
->paginate(20);
This works. Only thing I would like to improve is the way, the pictures per album are counted. Now I get all with with('pics') and then do a count($album->pics) in the view. If there is a way to not load everything, but only count the pictures, it would be nice.
You need to get the MAX(created_at) inside a subquery; see MySQL select MAX(datetime) not returning max value for example.
Really, though, if you're doing this in Laravel, it would be better to set these all up as relations and leverage the power of Eloquent. Then, you can define a relationship for pictures that uses ->latest() to return the most recent. See laravel eloquent query group by last id for an example (which uses one table, but the principle is the same for multiple tables).
Here's how you could set this up using Eloquent relations:
User model (User.php)
class User extends Eloquent {
public function albums()
{
return $this->hasMany('Album');
}
}
Album model (Album.php)
class Album extends Eloquent {
public function pics()
{
return $this->belongsToMany('Pic');
}
public function latestPic()
{
return $this->belongsToMany('Pic')->latest('album_pic.created_at');
}
}
Because you have a many-to-many relationship between albums and pics, in the latestPic() relation, you must specify the album_pic.created_at field for latest()—since we are actually interested in the order of entries in the pivot table, rather than in the pics table.
Finally, link this all together. For example, for a user with id of 1:
$albums = User::find(1)->albums()->with('pics')->with('latestPic')->paginate(20);
foreach($albums as $album) {
echo('<br>Album:');
var_dump($album->title);
echo('All pics:');
foreach($album->pics as $pic) {
var_dump($pic->url);
}
echo('Latest pic:');
$latestPic = $album->latestPic->first();
if ($latestPic) {
var_dump($latestPic->url);
}
}
Note that we are eager loading the pics and latestPic to reduce the number on calls to the database. Also note that accessing the $latestPic->url is wrapped in an if statement, otherwise albums that do not have any photos will throw an error since $album->latestPic would return null.
As #cedie correctly noted, Laravel doesn't handle pagination all that efficiently when using a groupBy statement, but that shouldn't be a problem in this case. The underlying queries do not use groupBy, so you should be save to use ->paginate(20).
Try using this in your select query:
max(pics.created_at) as created_at
instead of this:
pics.created_at
So your code should look like this:
AlbumPic::select(DB::raw('COUNT(pics.id) as picscount,
pics.url,
pics.user_id,
max(pics.created_at) as created_at,
albums.id as album_id,
albums.title,
albums.text,
users.username'))
Perhaps ypu can figure out how to adapt this for your purposes...
SELECT ap.*
, p.*
FROM album_pic ap
JOIN pics p
ON p.id = ap.pic_id
JOIN
( SELECT ap.*
, MAX(p.created_at) max_created_at
FROM album_pics ap
JOIN p.*
ON p.id = ap.pic_id
) x
ON x.album_id = ap.album_id
AND x.max_created_at = p.created_at;
I have two tables: Users and Groups
In my table "Users", there is a column called "ID" for all the user ids.
In my table "Groups" there is a column called "Participants", fields in this column are filled with all the user ids like this "PID_134,PID_489,PID_4784," - And there is a column "ID" that identifies a specific group.
Now what i want to do, i want to create a menu that shows all the users that are not yet in this particular group.
So i need to get all the user ids, that are not yet in the Participants column of a group with a particular ID.
It would be cool if there was a single mysql query for that - But any PHP + MySQL solutions are okay, too.
How does that work? Any guesses?
UPDATE:
i know, that's not code, but is there a way I could do something like this that would return me a list of all the users?
SELECT *
FROM users, groups
WHERE groups.participants NOT LIKE '%PID_'users.id'%' AND groups.id = 1;
Something like this. You just get rid of "PID_" part of ID.
SELECT * FROM [users] WHERE [id] NOT IN
(SELECT replace(id,'PID_','') FROM groups WHERE group_name='group1')
Group1 would be your variable - group id/name of menu that you've opened.
You can select from multiple tables as shown below:
SELECT * from users, groups WHERE users.id != groups.participants AND groups.id = 1;
This will list all users who are not in group id 1; A more elegant solution can be found by using joins, but this is simple and will do the trick.
I believe something like that should help:
SELECT * FROM users WHERE users.id NOT IN (SELECT groups.participants FROM groups)
But this works only if your DB is normalized. So for your case I see only PHP + MySQL solution. Not very elegant, but it does the job.
<?php
$participants_array = mysql_query("SELECT participants FROM groups");
$ids = array();
while ($participant = mysql_fetch_assoc($participants_array))
{
$id = explode(',', $participant['participant']);
foreach ($id as $instance)
{
if (!in_array($instance, $ids)) $ids[] = $instance;
}
}
$participants = implode(',', $ids);
$result = mysql_query("SELECT * FROM users WHERE id NOT IN ( $participants )");
But I highly recommend normalizing the database.