How do I serach in laravel Eloquent relationships? - laravel

I have a function that returns data as required. When I add a search string so that I can filter the results, no filtering is done.
Function
public function getComboSubItemRequirements(Request $request, $comboId){
$search_string = $request->query('search_string');
$search_string = empty($search_string)
? null
: trim(urldecode($search_string));
$combo = ComboSellable::where('id', $comboId)
->with('sellable')
->with('items')
->first();
$sellable_id = $combo->sellable->sellable_id;
$sellables = Sellable::thisMerchant()
->with('sellable')
->where('sellable_type', '<>', Sellable::COMBO)
->when(!empty($sellable_id) && !is_numeric($sellable_id), function ($q) use($search_string){
$q->whereHasMorph(
'sellable',
[Sellable::SERVICE, Sellable::PRODUCT],
function ($qq) use ($search_string){
return $qq->where('sellable.name', 'like', "%{$search_string}%");
}
);
})
->whereNotIn('id', $combo->items->pluck('sellable_id')->toArray())
->limit(10)
->get();
return response()->json($sellables);
}
}
Result structure
[
{
"id": 3,
"merchant_id": 2,
"sellable_id": 3,
"sellable_type": "App\\Product",
"created_at": null,
"updated_at": null,
"deleted_at": null,
"sellable": {
"id": 3,
"merchant_id": "2",
"name": "Wash and set weave",
"description": "",
"cost": "1000",
"image": null,
"duration": "60",
"remainder_days": null,
"created_at": "2020-12-02T06:59:24.000000Z",
"updated_at": "2021-06-19T16:03:30.000000Z",
"commission": null,
"deleted_at": null,
"can_be_sold": 1,
"tax_id": null,
"tax_method": null
}
},
{
"id": 4,
"merchant_id": 2,
"sellable_id": 4,
"sellable_type": "App\\Product",
"created_at": null,
"updated_at": null,
"deleted_at": null,
"sellable": {
"id": 4,
"merchant_id": "2",
"name": "Wash andset tracks",
"description": "",
"cost": "800",
"image": null,
"duration": "75",
"remainder_days": null,
"created_at": "2020-12-02T06:59:53.000000Z",
"updated_at": "2021-08-21T02:47:18.000000Z",
"commission": null,
"deleted_at": null,
"can_be_sold": 1,
"tax_id": null,
"tax_method": null
}
}
]
I want to search items based on sellable->name. I have added the sellable table to the query but the results are still the same. No search or filtering is done.
How do I filter in such a case?

Related

How to loop read all the column from the spreadsheet using Laravel-Excel

I have a spreadsheet that contains quiz records where I save all the quiz_questions and choices in the database.
I have this code reading and saving the spreadsheet but it has some issues, I want to save the choice_1, choice_2, choice_3, and choice_4 inside the database with the column name of choices. When I run this code it only save the choice_4 columns but not all of the choices. How can I get all the choices and save it? can anyone help me? thanks in advance.
This is my QuizImport
public function collection(Collection $rows)
{
foreach($rows as $row){
$quizQuestions = quizQuestions::create([
'quiz_id' => $row['quiz_id'],
'question_num' => $row['question_num'],
'question_content' => $row['question_content'],
'tagalog_question'=> $row['tagalog_question'],
]);
$quizQuestions->choices()->create([
'option' => $row['option_1'] || $row['option_2'] || $row['option_3'] || $row['option_4'],
'remarks' => $row['remarks_1'] || $row['remarks_2'] || $row['remarks_3'] || $row['remarks_4'],
'tagalog_choices'=> $row['tagalog_choices'],
]);
}
}
This is my controller
public function store(Request $request){
$file = $request->file('file');
Excel::import(new QuizImport, $file);
return response(['message'=>"Quiz successfully imported",
'error'=>false,
'error code'=>200,
'line'=>"line".__LINE__."".basename(__LINE__),
'file'=>$file],200,[],JSON_NUMERIC_CHECK);
}
This is the sample structure of my excel
This is the expected output
"quizQuestions": [
{
"id": 2,
"quiz_id": 6,
"question_num": 1,
"question_content": "<p>Sample Question</p>",
"correct_answer": null,
"created_by": 7,
"updated_by": null,
"created_at": "2021-09-06T07:27:20.000000Z",
"updated_at": "2021-10-18T17:35:17.000000Z",
"question_image": null,
"tagalog_question": "<p><span style=\"color: black;\">Tagalog Translation of the question</span></p>",
"choices": [
{
"id": 2,
"quiz_questions_id": 2,
"option": "choices_1",
"remarks": 1,
"created_at": "2021-09-06T07:27:48.000000Z",
"updated_at": "2021-10-18T17:53:13.000000Z",
"choices_image": null,
"tagalog_choices": "Tagalog"
},
{
"id": 3,
"quiz_questions_id": 2,
"option": "choices_2",
"remarks": 0,
"created_at": "2021-09-06T07:28:01.000000Z",
"updated_at": "2021-10-18T17:53:25.000000Z",
"choices_image": null,
"tagalog_choices": "Tagalog"
},
{
"id": 4,
"quiz_questions_id": 2,
"option": "choices_3",
"remarks": 0,
"created_at": "2021-09-06T07:28:54.000000Z",
"updated_at": "2021-10-18T17:53:32.000000Z",
"choices_image": null,
"tagalog_choices": "Tagalog"
},
{
"id": 5,
"quiz_questions_id": 2,
"option": "choices_4",
"remarks": 0,
"created_at": "2021-09-06T07:29:07.000000Z",
"updated_at": "2021-10-18T17:53:37.000000Z",
"choices_image": null,
"tagalog_choices": "Tagalog"
}
]
},
But this is what I get
"quizQuestions": [
{
"id": 541,
"quiz_id": 33,
"question_num": 1,
"question_content": "Sample Question",
"correct_answer": null,
"created_by": null,
"updated_by": null,
"created_at": "2022-01-10T11:35:42.000000Z",
"updated_at": "2022-01-10T11:35:42.000000Z",
"question_image": null,
"tagalog_question": "Tagalog Translation of the Question",
"choices": [
{
"id": 1735,
"quiz_questions_id": 541,
"option": "choice4",
"remarks": 0,
"created_at": "2022-01-10T11:35:42.000000Z",
"updated_at": "2022-01-10T11:35:42.000000Z",
"choices_image": null,
"tagalog_choices": "Tagalog"
}
]
},
I believe you need a loop for creating multiple choices with the same parent. (not tested)
public function collection(Collection $rows)
{
foreach($rows as $row){
$quizQuestions = quizQuestions::create([
'quiz_id' => $row['quiz_id'],
'question_num' => $row['question_num'],
'question_content' => $row['question_content'],
'tagalog_question'=> $row['tagalog_question'],
]);
for($i = 1; $i < 5; $++) {
$quizQuestions->choices()->create([
'option' => $row['option_' .$i],
'remarks' => $row['remarks_' . $i],
'tagalog_choices'=> $row['tagalog_choices'],
]);
}
}
}

How to Users of a specific Room and filter these users with specific spatie tag?

I have a User model that have spatie tags (developer and consultant).
I have a Room model that have many to many relation with User.
I want to return users of a specific room with tag of "consultant".
Can you please help me to do that?
I can find my specific room by id and also I can use relation to get its users but I dont know how to filter them by tag.
I hope you understand my point.
this is what I tried so far but didnt worked!
$room->users->withAnyTags('consultant');
here is my relation:
public function users()
{
return $this->belongsToMany(User::class, 'skyroom_room_user', 'skyroom_room_id', 'user_id')->with('tags');
}
if I run this:
$room->users;
it will return this:
{
"id": "2c8fdf5a-fe94-4216-a3dc-8a49e76c6e34",
"first_name": null,
"last_name": null,
"email": null,
"slug": null,
"username": "+989353785968",
"gender": "male",
"birthday": null,
"national_code": null,
"sheba": null,
"country": null,
"city": null,
"bio": null,
"long_bio": null,
"education": null,
"language": null,
"type": "trainee",
"avatar": null,
"verified_at": null,
"certified_at": null,
"referred_by": null,
"referred_at": null,
"skyroom_user_id": 9379122,
"skyroom_username": "09353785968",
"skyroom_nickname": "مصطفی طاهری",
"skyroom_access": 1,
"created_at": "2021-04-08T13:22:42.000000Z",
"updated_at": "2021-04-08T13:22:42.000000Z",
"deleted_at": null,
"tags": []
},
{
"id": "33b1a31d-1aae-4c38-8c07-0793de5a4216",
"first_name": "حامد",
"last_name": "پوسانه",
"email": "h.pousaneh#gmail.com",
"slug": "hamed",
"username": "+989127426900",
"gender": "male",
"birthday": "1990-05-28 19:37:12",
"national_code": null,
"sheba": null,
"country": "Iran",
"city": "Tehran",
"bio": "مدیریت کسب و کار",
"long_bio": "مدیریت کسب و کار از دانشگاه صنعتی امیرکبیر",
"education": "کارشناسی ارشد",
"language": "فارسی، آذری و انگلیسی",
"type": "trainer",
"avatar": null,
"verified_at": null,
"certified_at": null,
"referred_by": "a9ca25bd-18fb-4271-8155-0a75d9dc31d9",
"referred_at": null,
"skyroom_user_id": 8025480,
"skyroom_username": "09127426900",
"skyroom_nickname": "حامد پوسانه",
"skyroom_access": 3,
"created_at": "2021-04-08T13:06:24.000000Z",
"updated_at": "2021-04-08T15:07:13.000000Z",
"deleted_at": null,
"tags": [
{
"id": "71de78b1-15ad-410d-9778-50cb9b3bd4ca",
"name": {
"en": "consultant"
},
"slug": {
"en": "consultant"
},
"type": "user-system-tag",
"order_column": 3,
"created_at": "2021-04-08T13:06:24.000000Z",
"updated_at": "2021-04-08T13:06:24.000000Z",
"pivot": {
"taggable_id": "33b1a31d-1aae-4c38-8c07-0793de5a4216",
"tag_id": "71de78b1-15ad-410d-9778-50cb9b3bd4ca",
"taggable_type": "App\\Models\\User"
}
},
Assuming you have created your relationships correctly, the syntax for retrieving tagged models would be:
$room->users()->withAnyTags('consultant')->get()
If you wanted to search for multiple tags, you would provide an array to withAnyTags:
$room->users()->withAnyTags(['consultant', 'developer'])->get()

Retrieves the latest data from a foreign key in a relation

I want to ask, can I retrieve the last foreign key data in the relation ?.
In this case I want to retrieve the last user transaction data.
for example in the transaction table between 3 months ago and now there are some transaction data as follows.
{
"current_page": 1,
"data": [
{
"id": 8,
"user_id": 1,
"type": "sell",
"created_at": "2019-12-11 11:55:31",
"updated_at": "2019-12-11 11:55:31",
"tax": null,
"invoice_number": null,
"name": "Fredy"
},
{
"id": 7,
"user_id": 1,
"type": "buy",
"created_at": "2019-11-20 17:14:55",
"updated_at": "2019-11-20 17:14:55",
"tax": null,
"tax_percent": "0.90",
"invoice_number": null,
"name": "Fredy"
},
{
"id": 6,
"user_id": 8,
"type": "buy",
"created_at": "2019-11-20 16:28:33",
"updated_at": "2019-11-20 16:28:33",
"tax": null,
"name": "Tommy"
},
{
"id": 5,
"user_id": 2,
"type": "buy",
"created_at": "2019-11-20 15:47:57",
"updated_at": "2019-11-20 15:47:57",
"tax": null,
"name": "Sarah"
},
{
"id": 4,
"user_id": 3,
"type": "buy",
"created_at": "2019-11-20 15:47:31",
"updated_at": "2019-11-20 15:47:31",
"tax": null,
"name": "John Doe"
},
],
}
This is the sample code that i made
public function index()
{
$start = Carbon::now()->subMonths(3)->format('Y-m-d') . ' 00:00:00';
$end = Carbon::now()->format('Y-m-d') . ' 23:59:59';
return $query = DB::table('transaction')
->join('users', 'users.id', '=', 'gold_transaction.user_id')
->select('transaction.id', 'user_id', 'users.*')
->whereBetween('transaction.created_at', [$start, $end])
->whereIn('transaction.id', [DB::raw("SELECT MAX(transaction.id) FROM transaction GROUP BY user_id")])->get();
}
What do i do if i only want to display users who did't make transaction more than 7 days from the last transaction for all users ?
Thank you.
Then you can do it like below,
Get user's transaction
$transaction = User::with(['transactions' => function ($q) use($start, $end){
$q->whereBetween('transactions.created_at', [$start, $end]);
])->find($user_id);
Get all users with their transactions
$transaction = User::with(['transactions' => function ($q) use($start, $end){
$q->whereBetween('transactions.created_at', [$start, $end]);
])->get();
assuming that you have transactions relation in your user model like below
public function transactions() {
return $this->hasMany('App\Transaction', 'user_id');
}

How to map Laravel API resources for Non-Related Models

Hi I'm creating non related model resources. Inventories and Categories. They have child relationship models but they are not connected directly.
Sample:
{
"data": {
"inventories": [
{
"id": 1,
"user_id": 1,
"sub_category_id": 6,
"created_at": "2019-03-08 03:00:00",
"updated_at": "2019-03-08 03:00:00",
"deleted_at": null,
"get_inventory_details": {
"id": 1,
"inventory_id": 1,
"image_path": "Pahiram-Drone1-1.png",
"name": "Drone i1",
"description": "Drone i1 The Best Drone yet!",
"quantity": 10,
"cost_per_day": 1000,
"cost_per_hour": 100,
"status": "0",
"created_at": "2019-03-08 03:00:00",
"updated_at": "2019-03-08 03:00:00",
"deleted_at": null
}
}
],"categories": [
{
"id": 1,
"category_id": 1,
"parent_id": null,
"created_at": "2019-03-08 03:00:00",
"updated_at": "2019-03-08 03:00:00",
"deleted_at": null,
"get_sub_category_details": {
"id": 1,
"sub_category_id": 1,
"category_type_id": 1,
"name": "Drone DJI 1",
"description": "Drone DJI 1",
"created_at": "2019-03-08 03:34:23",
"updated_at": "2019-03-08 03:34:23",
"deleted_at": null
}
}
]
}
}
This is my sample data
It works with:
public function toArray($request)
{
return parent::toArray($request);
}
But not:
public function toArray($request)
{
return [
'inventory_ids' => $this->inventories->id,
'category_ids' => $this->categories->id
];
}
My expected result is to be able to map my response.
You Don't access direct id from categories and inventories, because its an array not object.
This should be usefull for you.
$categoryIds = Collection::make($this->categories)->pluck('id')->toArray();
$inventoryIds = Collection::make($this->inventories)->pluck('id')->toArray();
return [
'category_ids' => $categoryIds,
'inventory_ids' => $inventoryIds
];

How to change the response in API

I want to change my response in an API. I get the user object in response but i want there the object of join like that here is the code of my Activity Profile Controller in which I get user object.
Currently i get this response.
"user": {
"id": 1,
"facebook_id": null,
"name": "umar",
"surname": "javed",
"email": "uj1#gmail.com",
"username": null,
"date_of_birth": "1993-01-18",
"profile_picture": null,
"occupation": null,
"gender": null,
"city": "lahore",
"country": null,
"course": null,
"university": null,
"discription": null,
"visible_on_feeds": 1,
"visible_on_guestlists": 1,
"created_at": "2018-05-02 10:35:03",
"updated_at": "2019-01-15 14:32:54"
}
public function joinActivity(Activity $activity)
{
$authUser = JWTAuth::parseToken()->toUser();
$userAge = Carbon::parse($authUser->date_of_birth)->age;
if($activity->age_from <= $userAge && $activity->age_to >= $userAge)
{
$authUser->joinActivity($activity, $authUser);
if ($activity->user_id != $authUser->id) {
$user = User::where('id', $activity->user_id)->first();
$user->notify(new JoinedTheActivity($authUser, $activity));
}
$userFriendIds = $authUser->friendslist()->pluck('id')->toArray();
$joinedIds = $activity->joins()->pluck('user_id')->toArray();
$joinedUsers = User::whereIn('id', $joinedIds)->whereIn('id', $userFriendIds)
->where('id', '!=', $authUser->id)->get();
foreach ($joinedUsers as $joinedUser) {
$joinedUser->notify(new FriendJoinedSameActivity($authUser, $activity));
}
return response()->json(['user'=> $authUser], 200);
} else {
return response()->json(['message'=> 'Your are not under the age limit of this Activity']);
}
}
And Here is the code of my ActivityInterest trait:
public function joinActivity(Activity $activity, User $user)
{
if ( $this->isJoiningActivity($activity, $user))
{
$activity->interests()->update(['status'=> Status::JOINED]);
} else {
$joining = $activity->interests()->create([
'user_id' => $user->id,
'activity_id' => $activity->id,
'status' => Status::JOINED,
]);
return $joining->save();
}
}
But I want this response How i can do that Please help Me. Thanks in advance.
"joins": [
{
"id": 71,
"user_id": 1,
"activity_id": 7,
"status": 1,
"created_at": "2018-12-21 07:05:30",
"updated_at": "2018-12-21 07:05:30",
"user": {
"id": 1,
"facebook_id": null,
"name": "umar",
"surname": "javed",
"email": "uj1#gmail.com",
"username": null,
"date_of_birth": "1993-01-18",
"profile_picture": null,
"occupation": null,
"gender": null,
"city": "lahore",
"country": null,
"course": null,
"university": null,
"discription": null,
"visible_on_feeds": 1,
"visible_on_guestlists": 1,
"created_at": "2018-05-02 10:35:03",
"updated_at": "2019-01-15 14:32:54"
},
"activity": {
"id": 7,
"activity_type": "event",
"user_id": 1,
"category_id": 2,
"subcategory_id": 3,
"activity_privacy": "open",
"activity_privacy_visible": 1,
"activity_datetime_from": "2018-07-28 13:35:00",
"activity_datetime_to": "2018-12-12 04:10:12",
"activity_address": "lahore",
"company_id": 3,
"latitude": null,
"longitude": null,
"age_from": 16,
"age_to": 30,
"people_limit": "4",
"activity_picture": null,
"activity_title": "party",
"activity_description": "party bla bla",
"created_at": "2018-05-03 10:49:48",
"updated_at": "2018-09-29 07:57:10",
"user": {
"id": 1,
"facebook_id": null,
"name": "umar",
"surname": "javed",
"email": "uj1#gmail.com",
"username": null,
"date_of_birth": "1993-01-18",
"profile_picture": null,
"occupation": null,
"gender": null,
"city": "lahore",
"country": null,
"course": null,
"university": null,
"discription": null,
"visible_on_feeds": 1,
"visible_on_guestlists": 1,
"created_at": "2018-05-02 10:35:03",
"updated_at": "2019-01-15 14:32:54"
},
"subcategory": {
"id": 3,
"category_id": 2,
"subcategory_name": "party",
"subcategory_picture": "dds",
"created_at": null,
"updated_at": null,
"category": {
"id": 2,
"category_name": "nightlife",
"category_picture": "knk",
"category_color": "#992233",
"created_at": null,
"updated_at": "2018-08-09 11:21:23"
}
}
}
}
]
When you need to change a response in your api, you can create a resource. this is the correct way, and will help you returning the information the way you need it.
In example, php artisan make:resource UserCollection
More info here:
https://laravel.com/docs/5.7/eloquent-resources

Resources