Laravel one to one relationships and query - laravel

I have customers who have been classified as (individual - company), I want to get all customer information from the main table and subtable into one query, I tried many times and I did not find a solution to that .. My attempts at the end of this topic
My tables:
customer_type
id
type
customers
id
address
customer_type_id
customer_individual
id
first_name
last_name
customer_id
customer_company
id
company_name
logo
customer_id
My RelationShips:
CustomerType.php
class CustomerType extends Model
{
public function customers()
{
return $this->hasMany('App\Customer');
}
}
Customer.php
class Customer extends Model
{
public function customer_type()
{
return $this->belongsTo('App\CustomerType');
}
public function more()
{
$related = ($this->customer_type_id == '1') ?
'App\CustomerIndividual' : 'App\CustomerCompany';
// 1 => individual
return $this->hasOne($related, 'customer_id');
}
}
CustomerIndividual.php
class CustomerIndividual extends Model
{
public function customer()
{
return $this->belongsTo('App\Customer');
}
}
CustomerCompany.php
class CustomerCompany extends Model
{
public function customer()
{
return $this->belongsTo('App\Customer');
}
}
I want the output as follows:
[
{
"id": 1,
"customer_type_id": 1,
"address": "New York",
"more": {
"id": 1,
"customer_id": 1,
"first_name": "John",
"last_name": "doe"
}
},
{
"id": 2,
"customer_type_id": 2,
"address": "london",
"more": {
"id": 2,
"customer_id": 2,
"name": "ANA IT Company",
"logo": "analogo.png"
}
}
]
These are my attempts:
return Customer::with(['person', 'company'])->get();
$customers = Customer::query();
$customers->when($customers->customer_type_id === 1, function($q){
return $q->with('person');
});
$customers->when($customers->customer_type_id === 2, function($q){
return $q->with('company');
});
$c = $customers->get();
return $c;
I hope to find a solution here.

What you could do is to create a new collection and add them to that.
Assuming that $q->with('person') is an object:
$collection = new \Illuminate\Database\Eloquent\Collection;
$customers->when($customers->customer_type_id === 1, function($q){
$collection->push($q->with('person'));
});
$customers->when($customers->customer_type_id === 2, function($q){
$collection->push($q->with('company'));
});
$c = $collection->flatten();
return $c;
Docs: Here

Related

Laravel Query Builder Return Results

I have below Laravel Query, which runs very fine and returns the desired results.
$email = (Auth::user()->email);
$UerType = DB::table('tbl_schools')->where('email', $email)->pluck('type');
$parent_ids = DB::table('tbl_schools')->where('email', $email)->pluck('id');
// return $parent_ids;
if ($UerType == 'sub_admin') {
$children = DB::table('tbl_schools')->whereIn('id', $parent_ids)->get();
return $children;
} elseif ($UerType == 'school') {
$children = DB::table('tbl_schools')->where('email', $email)->get();
return $children;
} elseif ($UerType = 'admin') {
$children = DB::table('tbl_schools')->where('email', $email)->get();
return $children;
}
Out from Above is as expected
{
"id": 15,
"type": "sub_admin",
"parent_id": "12",
"username": "",
"access_role_type": "SCH2486518",
"school_code": "SCH2486518",
"school_name": "Test School",
"school_ad_name": "Support",
"address": "",
"email": "someemail#mail.com",
"mobile": "+2332123123123",
"school_logo": "",
"profile_image": "",
"status": "active",
"created": "2020-09-28 16:41:44",
"updated": "0000-00-00 00:00:00",
"token": ""
}
Now I need to Pick specific fields and save them to session for future use, but when I run the below code, strangely I still get the entire Query Result which is strange.
$email = (Auth::user()->email);
$UerType = DB::table('tbl_schools')->where('email', $email)->pluck('type');
$parent_ids = DB::table('tbl_schools')->where('email', $email)->pluck('id');
// return $parent_ids;
if ($UerType == 'sub_admin') {
$children = DB::table('tbl_schools')
->select('id','type','parent_id','school_name')
->whereIn('id', $parent_ids)
->get();
return $children;
} elseif ($UerType == 'school') {
$children = DB::table('tbl_schools')
->Select('id','type','parent_id','school_name')
->where('email', $email)
->get();
return $children;
} else {
$children = DB::table('tbl_schools')
->Select('id','type','parent_id','school_name')
->where('email', $email)
->get();
return $children;
}
I need help
First of all, you don't need to call the same query two times. Next, you are returning an array and compare it with a string. Do the following way. Hope this will give you the exact result.
$email = (Auth::user()->email);
$user = DB::table('tbl_schools')->where('email', $email)->first();
if ($uerType->type == 'sub_admin') {
$children = DB::table('tbl_schools')->whereIn('id', $user->id)->get();
return $children;
} elseif ($user->type == 'school') {
$children = DB::table('tbl_schools')->where('email', $email)->get();
return $children;
} elseif ($user->type = 'admin') {
$children = DB::table('tbl_schools')->where('email', $email)->get();
return $children;
}

Trying to get property 'point' of non-object

I have a problem with get value of object ,I tried many posts here in stackoverflow like this : Trying to get property of non-object - Laravel 5 but it isn't solved.
I have this controller method :
public function user_team($id)
{
$week = Week::where('status','active')->first();
$week_id = $week->id;
$team = Team::where('user_id',$id)->with('userteams')->get();
foreach ($team[0]->userteams as $userteam) {
$userteam->surname = $userteam->Club->surname;
$userteam->price = $userteam->Club->price;
$points = Userpoint::where('club_id',$userteam->club_id)->where('week_id',$week_id)->where('user_id',$id)->first();
$point = $points->point;
$userteam->point = $point;
unset($userteam->Club);
}
return $team;
}
teams return this in post man :
[
{
"id": 40,
"team_name": "",
"season_id": 1,
"week_id": 2,
"user_id": 223269719,
"created_at": "2021-07-30T13:34:44.000000Z",
"updated_at": "2021-07-30T13:34:44.000000Z",
"userteams": [
{
"id": 277,
"team_id": 40,
"club_id": 1,
"created_at": "2021-07-30T13:34:44.000000Z",
"updated_at": "2021-07-30T13:34:44.000000Z"
},
{
"id": 278,
"team_id": 40,
"club_id": 21,
"created_at": "2021-07-30T13:34:44.000000Z",
"updated_at": "2021-08-01T10:37:03.000000Z"
},
and $points->point is return a value : 9
but when I try
$point = $points->point
it give me error : Trying to get property 'point' of non-object
foreach ($team[0]->userteams as $key => $userteam) {
$userteam->surname = $userteam->Club->surname;
$userteam->price = $userteam->Club->price;
$points = Userpoint::where('club_id',$userteam->club_id)->where('week_id',$week_id)->where('user_id',$id)->first();
$team[0]->userteams[$key]['point'] = $points->point;
unset($userteam->Club);
}
There i updated it, can you try again with this code
I solved it :
public function user_team($id)
{
$week = Week::where('status','active')->first();
$week_id = $week->id;
$team = Team::where('user_id',$id)->with('userteams')->first();
foreach ($team->userteams as $userteam) {
$userteam->surname = $userteam->Club->surname;
$userteam->price = $userteam->Club->price;
$points = $userteam->Club->userpoints;
if(isset($oiints)){
foreach ($points as $point) {
if($point->user_id == $id){
$userteam->point = $point->point;
}
}
}else{
$userteam->point = 0;
}
unset($userteam->Club->userpoints);
unset($userteam->Club);
}
return $team;
}

insert path URL into values an array

i want to add the url image in value to array
public function show(){
$halls = DB::table('halls')
->join('imagas','halls.id','=','imagas.id_Halls')
->select('halls.id','halls.hall_name','halls.hall_adress','halls.hall_details','price_hours','price_int','halls.hall_name','imagas.image_path')->where('halls.id',157)
->get();
$results=[];
foreach ($halls as $hall) {
$array=json_decode($hall->image_path,true);
if (is_array($array))
{
$hall->image_path = $array;
}
array_push($results, $hall);
}
return response()->json($results);
}
output like this
{
"id": 157,
"hall_name": "ali",
"hall_adress": "st-50",
"hall_details": null,
"price_hours": "3000",
"price_int": "500",
"image_path": [
"1579635535.jpg",
"1579635536.jpg",
"1579635537.png",
"1579635538.png"
]
}
but i need pass string path url to array and show output like this
{
"id": 157,
"hall_name": "ali",
"hall_adress": "st-50",
"hall_details": null,
"price_hours": "3000",
"price_int": "500",
"image_path": [
"http://127.0.0.1:8000/images_ravs/1579635535.jpg",
"http://127.0.0.1:8000/images_ravs/1579635536.jpg",
"http://127.0.0.1:8000/images_ravs/1579635537.png",
"http://127.0.0.1:8000/images_ravs/1579635538.png"
]
}
Iterate through the image array and add the rest of the URL.
foreach ($halls as $hall) {
$array = json_decode($hall->image_path, true);
if (is_array($array)) {
foreach($array as $index => $image) {
$array[$index] = "http://127.0.0.1:8000/images_ravs/" . $image;
}
$hall->image_path = $array;
}
}
Hope this helps you.

get first value from array column database

I need to get the fist item an array from select database using loop for but when i do't my outfit display all the value for array
public function index() {
$hall=DB::table('halls')
->join('imagas','halls.id','=','imagas.id_Halls')
->select('halls.id','halls.hall_name','imagas.image_path')
->get();
$results =[];
foreach ($hall as $halls ) {
$array=$halls->image_path ;
for ($i=0; $i<$array; $i++) {
$halls=$array[0];
}
array_push($results, $halls);
}
return response()->json($results);
}
JSON Output
[
{ "id": 159,
"hall_name": "asdad",
"image_path": "[\"1579635948.jpg\",\"1579635948.jpg\",\"1579635948.png\",\"1579635948.png\"]"
},
{
"id": 160,
"hall_name": "dsfdsf",
"image_path": "[\"1579636069.jpg\",\"1579636069.png\",\"1579636069.png\",\"1579636069.png\"]"
},
]
I want to display the first value from all image_pathlike this
[ {
"id": 160,
"hall_name": "dsfdsf",
"image_path": "["1579636069.jpg"]"
},
]
You may use decode your $hall->image_path string before loop through it
public function index() {
$halls = DB::table('halls')
->join('imagas','halls.id','=','imagas.id_Halls')
->select('halls.id','halls.hall_name','imagas.image_path')
->get();
$results =[];
foreach ($halls as $hall) {
$array = json_decode($hall->image_path, true);
if (is_array($array)) {
$hall->image_path = reset($array) ?? NULL;
array_push($results, $hall);
}
}
return response()->json($results);
}
If I understand you correctly, you want the whole collection data but with modified image_path column, so it contains only the first path, right?
Here is the code using map helper function to output the collection as you desire:
public function index() {
$hall=DB::table('halls')
->join('imagas','halls.id','=','imagas.id_Halls')
->select('halls.id','halls.hall_name','imagas.image_path')
->get();
$results = $hall->map(function ($item, $key) {
is_array($item->image_path) ? [head($item->image_path)] : [$item->image_path];
return $item;
});
return response()->json($results);
// [ { "id": 159, "hall_name": "asdad", "image_path": "["1579635948.jpg"]" },
// { "id": 160, "hall_name": "dsfdsf", "image_path": "["1579636069.png"]" }]
}

How to fix issue with group join in linq / lambda expression?

I have the following Linq/Lambda expression to associate COMMENTS and ATTACHMENTS to RECORDS (these are the names of tables in database).
var comments = repositoryBase.Query<Comments>()
.Select(x => x);
var attachments = repositoryBase.Query<Attachment>()
.Where(x => x.DeletedFlag == false)
.Select(x => x);
var recordItems = repositoryBase.Query<Record>()
.Where(x => x.DepartmentId == departmentIdId && x.DeletedFlag == false);
recordItems = recordItems
.Where(x => x.Featured == true && (x.PhaseTypeId == 2 || x.PhaseTypeId == 3)); // filtering
var recordComments = recordItems
.GroupJoin(comments,
itm => new { a = 1, b = itm.RecordId },
c => new { a = c.TypeId, b = c.Id },
(itm, c) => new { c, itm })
.SelectMany(x => x.c.DefaultIfEmpty(), (x, y) => new
{
Comments = (y != null) ? true : false,
CommentsCount = x.c.Count(),
RecordId = x.itm.RecordId,
Featured = x.itm.Featured,
Id = x.itm.RecordId,
PhaseName = x.itm.PhaseType.PhaseName,
x.itm.ProductionDate,
x.itm.PublishedDate,
Title = x.itm.RecordTitle,
x.itm.UpdatedDate
}).Distinct();
where TypeId and Id in c => new { a = c.TypeId, b = c.Id } are fields in comments on which the group join(left outer join) is done.
var recordAttachments = recordComments
.GroupJoin(attachments,
itm => new { a = 1, b = itm.RecordId },
at => new { a = at.ContentType, b = at.ContentId },
(itm, at) => new { at, itm})
.SelectMany(x => x.at.DefaultIfEmpty(), (x, y) => new
{
Attachments = (y != null) ? true : false,
AttachmentsCount = x.at.Count(),
AttachmentTitle = y.FileName,
AttachmentId = (y != null) ? y.AttachmentId : 0,
TypeId = (y != null) ? y.ContentType : 0,
ItemId = (y != null) ? y.ContentId : 0,
Comments = x.itm.Comments,
CommentsCount = x.itm.CommentsCount,
Featured = x.itm.Featured,
Id = x.itm.RecordId,
PhaseName = x.itm.PhaseName,
x.itm.ProductionDate,
x.itm.PublishedDate,
Title = x.itm.Title,
x.itm.UpdatedDate
}).Distinct().ToList();
But with the last lambda expression there is an issue that if there are two attachment for the same record, the record with attachment gets duplicated (not in database but in view).
As shown here
"Data": [
{
"typeid": 1,
"typename": "Record Scan",
"id": 3071,
"title": "Late Outcomes",
"publishdate": "3/4/2013",
"featured": true,
"productiondate": "",
"phasename": "Board",
"updateddate": "4/29/2013",
"updateddateforsorting": "2013-04-29T19:44:29.47",
"comments": true,
"numofcomments": 4,
"attachment": true,
"numofattachments": 2,
"attachments": [
{
"attachmentid": 371,
"typeid": 1,
"id": 0,
"title": "Cardio_David.docx",
"name": null,
"createddate": "0001-01-01T00:00:00"
},
{
"attachmentid": 434,
"typeid": 1,
"id": 0,
"title": "blanks in password field.docx",
"name": null,
"createddate": "0001-01-01T00:00:00"
}
]
},
{
"typeid": 1,
"typename": "Record Scan",
"id": 3071,
"title": "Late Outcomes",
"publishdate": "3/4/2013",
"featured": true,
"productiondate": "",
"phasename": "Board",
"updateddate": "4/29/2013",
"updateddateforsorting": "2013-04-29T19:44:29.47",
"comments": true,
"numofcomments": 4,
"attachment": true,
"numofattachments": 2,
"attachments": [
{
"attachmentid": 371,
"typeid": 1,
"id": 0,
"title": "Cardio_David.docx",
"name": null,
"createddate": "0001-01-01T00:00:00"
},
{
"attachmentid": 434,
"typeid": 1,
"id": 0,
"title": "blanks in password field.docx",
"name": null,
"createddate": "0001-01-01T00:00:00"
}
]
}
]
NB- this is a sample data ignore the field names and values
I 've editted the last code recordAttachment as
var recordAttachment= from rc in recordComments
join at in attachments on rc.RecordId equals at.ContentId into ra
select new { Comments = rc.Comments, CommentsCount = rc.CommentsCount Featured = rc.Featured, Id = rc.RecordId, PhaseName = rc.PhaseName, rc.ProductionDate, jac.PublishedDate, Source = jac.Source, Title = rc.Title, rc.UpdatedDate, AttachmentCount = ra.Count(), Attachments = ra, IsAttachment = (ra.Count() != null) ? true : false };
This returns record and associated attachments. Now i need to Map this data to a view model..
public class FlaggedItemModel
{
public int typeid { get; set; }
public string typename { get; set; }
public int id { get; set; }
public string title { get; set; }
public string publishdate { get; set; }
public bool featured { get; set; }
public string productiondate { get; set; }
public string phasename { get; set; }
public string updateddate { get; set; }
public DateTime updateddateforsorting { get; set; }
public bool comments { get; set; }
public int numofcomments { get; set; }
public bool attachment { get; set; }
public int numofattachments { get; set; }
public IList<AttachmentModel> attachments { get; set; }
}
I tried this code but not working
var recordlist = journalArticleAttachments.Select(x => new FlaggedItemModel() { attachments = x.Attachments.Where(z => z.ContentId == x.Id).Select(jaa => new AttachmentModel() { attachmentid = jaa.AttachmentId, typeid = jaa.ContentType, title = jaa.FileName }).ToList(), numofcomments = x.CommentsCount, comments = x.Comments, featured = x.Featured, id = x.Id, phasename = x.PhaseName, productiondate = (x.ProductionDate.HasValue) ? x.ProductionDate.Value.ToShortDateString() : string.Empty, publishdate = (x.PublishedDate.HasValue) ? x.PublishedDate.Value.ToShortDateString() : string.Empty, title = x.Title, typeid = 1, typename = "Journal Scan", updateddate = x.UpdatedDate.ToShortDateString(), updateddateforsorting = x.UpdatedDate });
How to fix this issue?
You are getting this error because you are trying to get the database to convert a datetime to a formatted short date string, which it doesn't know how to do. I would recommend changing your model to have a production date be a datetime field, and formatting it appropriately in your view. Changing the datetime to a string in the controller (or DAL) isn't the appropriate place to do it.
Alternatively, if you insist on having the shortdate in your viewmodel, have the query initally return the field as date time, then call .ToList() on the query, and then project that result into your final view so that the result will be returned from the database as datetime, and then you can have it convert it to shortdate in C#. Something like this:
var recordlist = journalArticleAttachments.Select(x=>new { ..., publishdate, ...}).ToList().Select(x=>new { ..., publishdate = (publishdate==null) ? publishdate.ToShortDateString() : string.Empty, ...});

Resources