Retrieves the latest data from a foreign key in a relation - laravel

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');
}

Related

How do I serach in laravel Eloquent relationships?

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?

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'],
]);
}
}
}

Filter Data with Pivot Table Laravel Eloquent

I want to filter users based on their subscription_status which s stored in a pivot table.
I have Three tables users , subscription_packages , subscription_package_user
$user=User::with(['studentDetails','subscriptionsSatus.courses'])
->withPagination($offset,$perPage)
->get()
->sortBy('first_name')->values();
this code return the response is
[
{
"id": 44,
"first_name": "Abcd Test",
"last_name": "Test lastname",
"student_details": null,
"subscriptions_satus": [
{
"id": 1,
"name": "Gold",
"price": 3000,
"user_id": "2"
"pivot": {
"user_id": 44,
"subscription_package_id": 1,
"subscription_status": "on_free_trial",
"expires_on": null,
"id": 9
},
"courses": [
{
"id": 18,
"title": "English Grammar for Class 3",
"price": 400,
"strikethrough_price": null,
"status": "draft",
"user_id": 2,
"image": "http://127.0.0.1:8000/courses/1615702915.png",
"description": null,
"pivot": {
"subscription_package_id": 1,
"course_id": 18,
}
}
]
}
]
}]
i want to return only users who having subscription_status =$filter.
$filter='acive'or 'on_free_trail'
my model is
public function subscriptionsSatus()
{
return $this->belongsToMany(SubscriptionPackage::class)->withTimestamps()->withPivot('subscription_status','expires_on','id');
}
I havetried
$filter=$request->input('filter')??"active";
$user=User::with(['studentDetails','subscriptionsStatus.courses'])
->whereHas('subscriptionsStatus', function($query) use($filter){
$query->wherePivot('subscription_status','=',$filter);
})
->withPagination($offset,$perPage)
->get()
->sortBy('first_name')->values();
But Got error Column not found 'pivot'
You need to use wherePivot along with the orWhere like below:
public function subscriptionsStatus()
{
return $this->belongsToMany(SubscriptionPackage::class)
->withTimestamps()
->withPivot('subscription_status','expires_on','id')
->wherePivot(function($q){
return $q->where('subscription_status','=','active')
->orWhere('subscription_status','=','on_free_trail');
});
}
Update
Or in your controller:
$user=User::with(['studentDetails','subscriptionsStatus.courses'])
->whereHas('subscriptionsStatus', function($query) use($filter){
$query->withPivot('subscription_status')
->wherePivot('subscription_status','=',$filter);
})
->withPagination($offset,$perPage)
->get()
->sortBy('first_name')->values();

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

Laravel - way to sum total_balance of all children.balance columns with just one request?

I need to simplify my data structuring. I want to get sum of balances in children accounts of a parent account. Here is how my object is structured:
Account Types
Children Types
Account 1 ( has balance of 9000 )
Account 2 ( has balance of 5000 )
I want to get total balance of all children accounts:
Account Types
Children Types - total_balance = 14000
How to do this without looping through the object, but using only the query builder of Laravel?
This is the request in my controller:
$user = \Auth::user()->id;
$accounts = AccountType::where('parent_id', 0)
->where('virtual', '=', 0)
->with(['children', 'children.accounts' => function ($query) use ($user) {
$query->where('user_id', '=', $user);
}])
->get();
return $accounts;
And this is the object that I get:
{
"id": 1,
"name": "Savings",
"parent_id": 0,
"virtual": 0,
"created_at": "2016-10-27 10:28:59",
"updated_at": "2016-10-27 10:28:59",
"children": [
{
"id": 2,
"name": "General Savings",
"parent_id": 1,
"virtual": 0,
"created_at": "2016-10-27 10:28:59",
"updated_at": "2016-10-27 10:28:59",
"accounts": [
{
"id": 25,
"institution_id": 0,
"balance": 9000,
"account_nickname": "Money Laundering",
"is_primary": 1,
"account_type_id": 2,
"user_id": 2,
"created_at": "2016-10-31 16:47:23",
"updated_at": "2016-10-31 16:47:23"
},
{
"id": 26,
"institution_id": 0,
"balance": 5000,
"account_nickname": "Moneymarket Savings",
"is_primary": 0,
"account_type_id": 2,
"user_id": 2,
"created_at": "2016-10-31 16:48:30",
"updated_at": "2016-10-31 16:48:30"
}
]
}
]
Is there a way to do that?
This should give you a list of all account types a user has containing a the total_balance of all accounts under each account_type:
$userAccountTypes = DB::table('account_types AS at')
->select(DB::Raw('*, SUM(a.balance) AS total_balance'))
->join('account_types AS ct', 'ct.parent_id', '=', 'at.id')
->join('accounts AS a', 'a.account_type_id', '=', 'ct.id')
->where('at.parent_id', 0)
->where('a.user_id', $user)
->groupBy('ct.id')
->get();

Resources