Iterate through laravel result object - laravel

My Code is like below.
$prayers = Prayer_time::where('mosque_id', $request->mosque_id)
->where('month', $month)
->where('date', $date)
->first();
foreach ($prayers as $key => $prayer) {
if ($prayer != null) {
$payer_times[$key] = $prayer;
}
}
return response()->json(['prayer_times' => $payer_times], 200);
I am getting below output.
{
"prayer_times": {
"incrementing": true,
"exists": true,
"timestamps": true
}
}
How can I iterate through result?

Assuming that first one is an API Controller and you want to iterate over the prayer_times in a frontend
res.data.prayers_time.each({
DO WHATEVER
})

Related

How to foreach array in laravel + vue?

I need to foreach array from session. My controller code
return [
'buys' => request()->session()->get('userBuys')
];
Vue component
export default {
data() {
return {
buys: {}
}
},
methods: {
async getBuys() {
this.$axios.post('/products/mybuys')
.then(res => {
this.buys = res.data.buys
this.$root.hideLoading()
})
}
},
mounted() {
this.$root.showLoading()
this.getBuys()
}
}
So i'm getting array
How i need to foreach this array correctly? I tried a lot of...
You have a json in a array so your
buys = [113, 114,...]
So your loop have only the numbers not the propertys/attributes
Try without brackets:
return 'buys' => request()->session()->get('userBuys')

Laravel / OctoberCMS frontend filter

I am using OctoberCMS and I have created a custom component. I am trying to create a frontend filter to filter Packages by the Tour they are assigned to.
This is what I have so far. The issue is that the code is looking for a tour field within the packages table rather than using the tour relationship. Does anyone have any ideas?
<?php namespace Jakefeeley\Sghsportingevents\Components;
use Cms\Classes\ComponentBase;
use JakeFeeley\SghSportingEvents\Models\Package;
use Illuminate\Support\Facades\Input;
class FilterPackages extends ComponentBase
{
public function componentDetails()
{
return [
'name' => 'Filter Packages',
'description' => 'Displays filters for packages'
];
}
public function onRun() {
$this->packages = $this->filterPackages();
}
protected function filterPackages() {
$tour = Input::get('tour');
$query = Package::all();
if($tour){
$query = Package::where('tour', '=', $tour)->get();
}
return $query;
}
public $packages;
}
I really appreciate any help you can provide.
Try to query the relationship when the filter input is provided.
This is one way to do it;
public $packages;
protected $tourCode;
public function init()
{
$this->tourCode = trim(post('tour', '')); // or input()
$this->packages = $this->loadPackages();
}
private function loadPackages()
{
$query = PackagesModel::query();
// Run your query only when the input 'tour' is present.
// This assumes the 'tours' db table has a column named 'code'
$query->when(!empty($this->tourCode), function ($q){
return $q->whereHas('tour', function ($qq) {
$qq->whereCode($this->tourCode);
});
});
return $query->get();
}
If you need to support pagination, sorting and any additional filters you can just add their properties like above. e.g;
protected $sortOrder;
public function defineProperties(): array
{
return [
'sortOrder' => [
'title' => 'Sort by',
'type' => 'dropdown',
'default' => 'id asc',
'options' => [...], // allowed sorting options
],
];
}
public function init()
{
$filters = (array) post();
$this->tourCode = isset($filters['tour']) ? trim($filters['tour']) : '';
$this->sortOrder = isset($filters['sortOrder']) ? $filters['sortOrder'] : $this->property('sortOrder');
$this->packages = $this->loadPackages();
}
If you have a more complex situation like ajax filter forms or dynamic partials then you can organize it in a way to load the records on demand vs on every request.e.g;
public function onRun()
{
$this->packages = $this->loadPackages();
}
public function onFilter()
{
if (request()->ajax()) {
try {
return [
"#target-container" => $this->renderPartial("#packages",
[
'packages' => $this->loadPackages()
]
),
];
} catch (Exception $ex) {
throw $ex;
}
}
return false;
}
// call component-name::onFilter from your partials..
You are looking for the whereHas method. You can find about here in the docs. I am not sure what your input is getting. This will also return a collection and not singular record. Use ->first() instead of ->get() if you are only expecting one result.
$package = Package::whereHas('tour', function ($query) {
$query->where('id', $tour);
})->get();

want to update array values in vuejs using laravel

i have an array values in update form. i need to update specific values when user change in textareas. it looks like this
In my vuejs data objects looks like this.
data() {
return {
jobs: [],
details: {
basic_id: this.$route.params.id,
work: this.jobs
}
};
},
and my update method i wrote like this.
updateDetails() {
this.loading = true;
this.updateWorkedPlaces(this.details)
.then(() => {
console.log("success");
this.loading = false;
})
.catch(() => {
this.loading = false;
});
}
i pass these values it my vuex action methods.
async updateWorkedPlaces({ commit }, payload) {
let job = await Api().put("works/" + payload.basic_id, payload.work);
commit("UPDATE_WORK", job);
},
i pass these values to my laravel backend update function. it looks like this.
public function update(Request $request, $id)
{
$work = $request->work;
$basic = $request->basic_id;
foreach ($request->work as $i => $id) {
$job = Job::findOrFail($basic);
$job->fill(['position' => $id['position'], 'address' => $id['address']])->save();
}
return response()->json(['message' => 'success']);
}
but when i pass these values to this function it shows me this error.
Invalid argument supplied for foreach()
how can i fix this error. anyone can help me?
i figure out my problem with this function
public function update(Request $request, $id)
{
$collection = $request->all();
for ($i = 0; $i < count($collection); $i++) {
Job::where('id', $collection[$i]['id'])
->update([
'position' => $collection[$i]['position'],
'address' => $collection[$i]['address']
]);
}
return response()->json(['collection' => $collection]);
}

Auth::user() Returns Null in API Controller

I'm using Laravel 7 and my problem is to get null from Auth::user();
auth()->user and Auth::id() return null as well.
BTW, in balde template Auth::user() works.
It returns null when I try to use it in controller.
What I'm trying to do is to create a comment page in backend (Vuejs) and I want to build up a filter logic. In order to do that, I want to add a new property named repliedBy into each comment in controller. If a comment isn't replied by the current user, repliedBy will be notByMe. So I don't event try to return user id to Vuejs. I can't get id even in the controller. BTW, login, registration etc work normal way.
Here is my CommentsController:
public function index()
{
$comments = Comment::join("site_languages", "language_id", "=", "site_languages.id")
->select("content_comments.*", "site_languages.shorthand as lang_shorthand")
->with(["replies", "post", "user"])
->orderBy('id', 'desc')
->get()
->groupBy("commentable_type");
$grouppedComments = [];
foreach ($comments as $type => $typeSet) {
$newType = strtolower(explode("\\", $type)[1]);
$grouppedByLanguage = $typeSet->groupBy("lang_shorthand");
$langSet = [];
foreach ($grouppedByLanguage as $lang => $commentSet) {
$grouppedBycontent = [];
foreach ($commentSet as $comments) {
$content = $newType . "_" . $comments->commentable_id;
if (array_key_exists($content, $grouppedBycontent)) {
array_push($grouppedBycontent[$content], $comments);
} else {
$grouppedBycontent[$content] = [$comments];
}
}
$groupAfterOrganized = [];
foreach ($grouppedBycontent as $content => $comments) {
$order = 1;
$commentAndReplies = [];
foreach ($comments as $comment) {
if ($comment->parent_id === null) {
if (isset($comment->order) === false || $comment->order > $order) {
$comment->order = $order;
}
array_push($commentAndReplies, $comment);
} else {
foreach ($comments as $parentComment) {
if ($parentComment->id === $comment->parent_id) {
$parent = $parentComment;
break;
}
}
foreach ($parent->replies as $replyInParent) {
if ($replyInParent->id === $comment->id) {
$reply = $replyInParent;
break;
}
}
if (isset($comment->order) === false) {
$comment->order = $order;
$order++;
}
if (isset($parent->order) === false || $parent->order > $comment->order) {
$parent->order = $comment->order;
}
$reply->order = $comment->order;
$reply->replies = $comment->replies;
$reply[$newType] = $comment[$newType];
$basePower = 6;
if ($comment->user_id !== null) {
if ($comment->user_id === Auth::id()) {
$reply->replyFrom = "me";
} else if ($comment->user->role->power >= $basePower) {
$reply->replyFrom = "staff";
} else {
$reply->replyFrom = "user";
}
} else {
$reply->replyFrom = "visitor";
}
$iReplied = false;
$staffReplied = false;
foreach ($reply->replies as $replyOfReply) {
if ($replyOfReply->user_id !== null) {
$power = $replyOfReply->user->role->power;
if ($power >= $basePower) {
$staffReplied = true;
}
}
if ($replyOfReply->user_id === Auth::id()) {
$iReplied = true;
}
}
if ($staffReplied === false) {
if ($reply->replyFrom === "user" && $reply->replyFrom === "visitor") {
$reply->replied = "notReplied";
} else {
$reply->replied = "lastWords";
}
} else if ($staffReplied && $iReplied === false) {
$reply->replied = "notByMe";
} else if ($staffReplied) {
$reply->replied = "replied";
}
}
}
$groupAfterOrganized[$content] = $commentAndReplies;
}
$langSet[$lang] = $groupAfterOrganized;
}
$grouppedComments[$newType] = $langSet;
}
return $grouppedComments;
}
api.php
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
Route::apiResources([
'languages' => 'API\LanguagesController',
'users' => 'API\UsersController',
'roles' => 'API\RolesController',
'tags' => 'API\TagsController',
'categories' => 'API\CategoryController',
'pictures' => 'API\PicturesController',
'posts' => 'API\PostsController',
'comments' => 'API\CommentsController'
]);
EDIT
I'm using the code down below in RedirectIfAuthenticated.php and when I try with
dd(Auth::user());
it returns null as well. BTW obviosly, redirect to backend doesn't work.
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
if (Auth::user()->role->power > 5) {
return redirect('backend');
}
return redirect(RouteServiceProvider::HOME);
}
return $next($request);
}
The solution to this problem is fairly simple . because you are using api request laravel default auth can not understand the user so here the passport comes :
https://laravel.com/docs/7.x/passport
as written in documenation you should go 3 steps :
composer require laravel/passport
php artisan migrate
php artisan passport:install
after that you can generate token for logged in users and use that token in api authentication to use for your api which is the only and more reliable way that laravel default auth .
this link can be helpful to you too :
https://laravel.io/forum/laravel-passport-vue-check-user-authentication
this way if you intent to use you api in mobile or any other application you can simply authenticate your user in that :)
hope this helps
EDIT
according To your comment now you must generate token for your vue api to use so this would be like below :
$token = $user->createToken(config('app.name'))->accessToken;
if ($this->isApiType()) {
$token = $user->createToken(config('app.name'))->accessToken;
} else {
Auth::login($user);
$redirect = $this->getRedirectTo($user);
}
this must be added in the end of your login method so if the request comes from api it generates a JWT token for you which can be used in vue for login
yes for getting the authencated user detail your API must under the auth:API middleware.
Route::group(['middleware' => 'auth:api'], function () {
}
As you are using Resource those are not under the Api middleware just put that into that and Auth::user will return the result set.
Route::group(['middleware' => 'auth:api'], function () {
Route::apiResources([
'comments' => 'API\CommentsController'
]);
}
will fix the issue.

Laravel Eloquent : Getting object instead of array

Trying to get a hotel in detail for hotel management API, in which for some hotels, getting
$hotel->rooms
as object and for some as array. The eloquent query in Hotel model as below.
public function detail($hotelid) {
return $this->with(['rooms','roomType'])->find($hotelid);
}
public function rooms() {
return $this->hasMany(HotelRooms::class, 'hotels_id')->where('status','active');
}
HotelRoom Model
public function roomType(){
return $this->hasOne(RoomType::class,'id','room_type_id')->where('status','active');
}
Controller
public function __construct(){
$this->model = new Hotel();
}
public function hotelDetail(Request $request){
$data = $this->model->detail($request->input('hotel_id'));
foreach($data->rooms as $key=>$room){
if(!$room->roomType){
unset($data->rooms[$key]);
continue;
}
}
return response()->json([
'status' => true,
'status_message' => 'successful',
'data' => $data,
]);
}
response
{
"id":"id",
"name":"name",
"rooms":{
"1":{},
"2":{}
}
}
{
"id":"id",
"name":"name",
"rooms":[
{},
{},
]
}
When you use unset on array, your array indexes remain for each item. Same as for collection->filter() or for array_filter() that is actually used in collection->filter(). That is why you need to rebuild the indexes:
$data->rooms = array_values($data->rooms->toArray());
to reindex the array.
Or use the foreach, but push values to new array:
$filteredRooms = [];
foreach($data->rooms as $key=>$room){
if(!$room->roomType){
continue;
}
$filteredRooms[] = $room;
}
$data->rooms = $filteredRooms;
Or instead of foreach loop, use filter for collection in combination with values() :
$filteredRooms = $data->rooms->filter(function ($room, $key) {
return (!$room->roomType)? false : true;
})->values();
After filtering array you have to re-index your array.
foreach($data->rooms as $key=>$room){
if(!$room->roomType){
unset($data->rooms[$key]);
continue;
}
}
$data->rooms = $data->rooms->values();

Resources