Join 3 tables based on column values - Laravel - mysql

LEADS TABLE
id
title
owner_id
from_table
EMPLOYEE TABLE
id
first_name
last_name
role
ADMIN TABLE
id
first_name
last_name
role
$users = Leads::query();
return Datatables::make($users)
->editColumn('owner_id', function ($user) {
if($user->from_table == 'employee'){
$emp = Employee::where('id',$user->owner_id)->first();
return $emp->first_name.' '.$emp->last_name.' ('.$emp->role.')';
}
if($user->from_table == 'admin'){
$admin = Admin::where('id',$user->owner_id)->first();
return $admin->first_name.' '.$admin->last_name.' ('.$admin->role.')';
}
})
the above solutions is working fine but we are unable to search column wise induvidual searching in datatables.
what i want is join query something like:
if(leads.from_table == employee)
// fetch data from EMPLOYEE TABLE i.e. LEADS TABLE + EMPLOYEE TABLE
id
title
owner_id
from_table
first_name
last_name
role
if(leads.from_table == admin)
// fetch data from ADMIN TABLE i.e. LEADS TABLE + ADMIN TABLE
id
title
owner_id
from_table
first_name
last_name
role

I think you should change your database structure to use polymorphic relations, they fully comply with your needs - https://laravel.com/docs/5.8/eloquent-relationships#polymorphic-relationships

from_table column should contain the class name of the parent model.
Add in Leads model
public function fetchOwner()
{
return $this->morphTo();
}
Add In Employee Model
public function employee()
{
return $this->morphOne('App\Employee', 'fetchOwner');
}
Add In Admin Model
public function employee()
{
return $this->morphOne('App\Admin', 'fetchOwner');
}
$users = Leads::with('fetchOwner');
return Datatables::make($users)
->editColumn('owner_id', function ($user) {
return $user->fetchOwner->name;
})

thanks to all who tried to help..
I'm answering my own question as i found the answer after 9 days digging everywhere..
so here is the answer:
you may want to replace owner_code by owner_id in your business table.
so i changed the from_table to owner_type & owner_type now should contain the class name as value ex: changed admin to App\Admin & employee to App\Employee in Database
App\Admin.php
public function employee()
{
return $this->morphOne('App\Leads', 'owner');
}
App\Employee.php
public function employee()
{
return $this->morphOne('App\Leads', 'owner');
}
App\Leads.php
public function owner()
{
return $this->morphTo();
}
Thanks to: laravel morphTo how to use custom columns? (EddyTheDove) for pointing out the exact problem..

Related

query in table pivot laravel

I have two tables and one pivot table which has
FK_idStore
FK_idEmployee
dateChange
My model store:
public function employee(){
return $this->belongsToMany(empleado::class,'employee_store', 'fk_idStore','fk_idEmployee')
->withPivot('dateChange');
}
the result:
I need to show the last store where an employee was.
Try:
$store = Store::findOrFail($id)->employee->latest();
Or:
$store = Store::findOrFail($id)->employee->->sortBy('dateChange', 'desc')->first();
Assuming the pivot table is the Store, and that you need the last record of each employee in each store, use:
public function employee(){
return Employe_Store::all()->groupBy('fk_idEmployee')->max('dateChange');
}

Laravel sql select users email who listed rooms where status = listed

I have these 2 tables:
**users**
id | name | email | ...
-----------
**rooms**
user_id | title | status | ...
---------------------------
How can i select all users's email with rooms where rooms status is Listed in Laravel 5 ?
What you have to do, you have to use "with" and "has"
$user = User::with(['room'])->whereHas('room,function($query){
$q->where('status',1);
})->get();
create model of User and Room & a relation in user name room.
May be the above one solve your problem
If you have already define a relation between App\User and App\Room Models like this.
class User {
/* other codes in your model goes here */
public function rooms(){
return $this->hasMany(App\Room::class);
}
}
class Room {
/* other codes in your model goes here */
public function user(){
return $this->belongsTo(App\User::class);
}
}
You can retrieve all users's email with rooms where rooms status is Listed like this
$users= \App\User::with(['rooms' => function($query){
$query->where('status', 'listed');
}])->pluck('email');

Grails - [1:N] Relationship issue

I have 2 different domain classes, one for Employee and one for Departments. The relationship between them is [1:N],which means that many employees can work at one Department but not vice versa. The issue is that, after Grails creates the tables from the domain classes when the project runs, for one employee, the department Id of that table references the id on Department Table. For example, for a user named "Peter", department id would be 1.
The department table also has names for the departments, along with the department id's.
How can I reference the department_id in employee table to point at department.name instead of department.id ?
Department Domain Class :
class Department {
String name
static hasMany = [
employees: Employee
]
static constraints = {
}
static mapping = {
version false
}
def String toString() {
name
}
}
Employee Domain Class :
class Employee {
String firstName
String lastName
String email
String country
int born
static belongsTo = [department: Department]
static constraints = {
firstName(blank: false)
lastName(blank: false)
born(blank: false)
email(blank: false, email: true)
country(blank: false)
}
static mapping = {
version false
}
}
What I need is, when in Employee table, the department_id column to reference at department.name instead of department.id.
I guess you need to configure that the Primary Key of the Department table is 'name' instead of the default 'id' column. Grails will then use the name as the Foreign Key.
i.e.:
class Department {
...
static mapping = {
id name: 'name'
}
...
}
ref (Grails 3.1) : http://docs.grails.org/3.1.x/ref/Database%20Mapping/id.html

Insert data into pivot table in Laravel5.4

I am working in Laravel5.4. I have created 3 table's.
User table :
tickets table :
ticket_cc_users table :
Now, I have create relation ship between users and tickets module like below.
User model :
public function tickets()
{
return $this->belongsToMany('App\User', 'ticket_cc_users', 'user_id', 'ticket_id');
}
Ticket model :
public function users()
{
return $this->belongsToMany('App\Models\Tickets\Ticket', 'ticket_cc_users', 'ticket_id', 'user_id');
}
TicketController controller save method :
public function store(Request $request)
{
return $request->all();
$ticket = new Ticket;
$ticket->requester_id = $this->user['id'];
//$ticket->assignee_id = $request->assignee_id;
//$ticket->cc_id = $request->cc_id;
$ticket->type = $request->type;
$ticket->priority = $request->priority;
$ticket->subject = $request->subject;
$ticket->description = $request->description;
$ticket->status = $request->status;
if($request->link)
{
$ticket->link = $request->link;
$ticket->due_date = null;
}
if($request->due_date && $request->due_date !="")
{
$ticket->due_date = date('Y-m-d',strtotime($request->due_date));
$ticket->link = "";
}
if($ticket->save())
{
$ticket->users()->sync($request->cc_id);
foreach($request->ticket_tags as $value){
$tag = new Tag;
$tag->tag_name = $value['text'];
$tag->save();
$ticketTag = new TicketTag;
$ticketTag->tickets_id = $ticket->id;
$ticketTag->tags_id = $tag->id;
$ticketTag->save();
}
$data = Ticket::find($ticket->id);
Mail::to('khyati#infirays.com')->send(new CreateTicket($data));
$response = array(
'success' => true
);
}
return $response;
}
Here, I am going to store data into ticket table. So I need to store cc user data into ticket_cc_user table. So how can I store ticket_id and user_id into this table. Here, I can get multiple user_id. And I am using Eloquent ORM.
Here, It gives an error like SQLSTATE[42S22]: Column not found: 1054 Unknown column '$$hashKey' in 'field list' (SQL: insert into ticket_cc_users ($$hashKey, address, city_id, country_id, created_at, deleted_at, email, firstname, id, introducer_id, is_verified, lastname, phone, signature, state_id, ticket_id, updated_at, user_id, username, userrole_id) values (object:109, , , , 2017-02-10 05:26:01, , nisarg.b#infirays.com, , 26, 1, , , 9999999999, , , 1, 2017-02-14 08:33:18, 0, nisarg, 2))
So,what code should I have to change in save function to store data into ticket_cc_users table?
It seems that belongsToMany() parameters order should be changed. The first and the last(4-th) parameters should be "about" same instance.
UPDATE Also the body of tickets() and users() functions should be exchanged
So try this:
User model :
public function tickets()
{
return $this->belongsToMany('App\Models\Tickets\Ticket', 'ticket_cc_users', 'user_id', 'ticket_id');
}
Ticket model :
public function users()
{
return $this->belongsToMany('App\User', 'ticket_cc_users', 'ticket_id', 'user_id');
}
From Laravel Many To Many Docs:
The third argument is the foreign key name of the model on which you are defining the relationship, while the fourth argument is the foreign key name of the model that you are joining to:
return $this->belongsToMany('App\Role', 'role_user', 'user_id', 'role_id');

Insert a duplicate record based on value of another column

I have a db table named Student, with columns as id, name, age.
id is the Primary Key, name is not null, and age can be null
I want to implement the following in php, Zend:
Only add a duplicate student name in db if the age value is different.
Inside the function/action addStudentAction, I am calling the Student model's function -findStudent to implement the requirement:
public function findStudent($name)
{
$result = null;
$select = $this->select(Zend_Db_Table::SELECT_WITH_FROM_PART)
->setIntegrityCheck(false)
->where('student.name = ?', $name);
//error_log($select->assemble());
$result = $this->getAdapter()->fetchRow($select);
return $result;
}
public function addStudentAction() {
$data = $_POST;
$studentModel = new Application_Model_Student;
$result = $studentModel->findStudent($data['name']);
if(!empty($result)) {
error_log("found student name in db, going to get age");
//Check for age
if( (!empty($result['age'] )) {
if( $result['age'] != $data['age']) {
error_log("going to add student as new record");
return $this->insert($data);
}
else {
error_log("not adding new student record ");
}
}
}
}
Now, there could be multiple records of Students with same name but different age values. Therefore, when adding a new student, I need to compare the ages of all records(if name matches) with the incoming value of age.
What could be best way to implement this requirement? Any help is greatly appreciated.
Thanks
The easiest way would be to create a compound UNIQUE index on the name, then age field. UNIQUE allows multiple NULL values, so that won't be an issue. Depending on your database size and usage, this might not be the most preferred option, in which case a simple SELECT of the student information before an INSERT to check if he/ she is already in there would be the best solution.
Let me know if I need to elaborate on this. I'd be happy to give you some examples.
How about you do a new SELECT with name and age:
public function findStudentWithAge($name, $age =null)
{
$result = null;
$select = $this->select(Zend_Db_Table::SELECT_WITH_FROM_PART)
->setIntegrityCheck(false)
->where('student.name = ?', $name);
if($age) $select->where('student.age = ?', $age);
//error_log($select->assemble());
$result = $this->getAdapter()->fetchRow($select);
return $result;
}
Now in the addStudentAction:
public function addStudentAction() {
$data = $_POST;
$studentModel = new Application_Model_Student;
$result = $studentModel->findStudent($data['name'], $data['age']);
if(!empty($result)) {
error_log("found student with this age, cannot add the record");
} else {
$this->insert($data);
}
}