Laravel Collection Loop to another Collection - php

How to loop the eloquent collection from one to another? I'm just getting first line of array. I have more than 4 array in the collection.
$queries = Students::where('year',"=", 1)->get();
$students = new Students();
foreach ($queries as $query) {
$students->name = $query->name;
$students->faculty = $query->faculty ."Add something";
$students->year = $query->year;
}
dd($students);

I want to change the collection a bit before I print to json. For example, I want add something behind the faculty
Use the transform() method to modify collection:
$students = Students::where('year', 1)->get();
$students->transform(function($i) {
$i->faculty = $i->faculty . 'add something';
return $i;
});
You also can use resource classes to transform the data before returning JSON response.

You could use map() to modify collection-
$queries = $queries->map(function($query){
$query->faculty = $query->faculty."kfjhgli";
return $query;
});
return $queries;

Related

can't orderBy accessor in Laravel

I cant orderBy points. Points is accessor.
Controller:
$volunteers = $this->volunteerFilter();
$volunteers = $volunteers->orderBy('points')->paginate(10);
Volunteers Model:
public function siteActivities()
{
return $this->belongsToMany(VolunteerEvent::class, 'volunteer_event_user', 'volunteer_id', 'volunteer_event_id')
->withPivot('data', 'point', 'point_reason');
}
public function getPointsAttribute(){
$totalPoint = 0;
$volunteerPoints = $this->siteActivities->pluck('pivot.point', 'id')->toArray() ?? [];
foreach ($volunteerPoints as $item) {
$totalPoint += $item;
}
return $totalPoint;
}
But I try to sortyByDesc('points') in view it works but doesn't work true. Because paginate(10) is limit(10). So it doesn't sort for all data, sort only 10 data.
Then I try to use datatable/yajra. It works very well but I have much data. so the problem came out
Error code: Out of Memory
You could aggregate the column directly in the query
$volunteers = $this->volunteerFilter();
$volunteers = $volunteers->selectRaw('SUM(pivot.points) AS points)')->orderByDesc('points')->paginate(10);

How to use query result and query again using LIKE statement in Laravel

I am trying to use questions result and get question again if title has some char in it.
If I query in condition_question table, I get results as expected.
public function showQuestions($category)
{
$myArray = array($category);
$questions = Question::whereIn('question_id', function ($query) use ($myArray) {
$query->select('question_id')
->from('condition_question')
->whereIn('condition_id', $myArray);
})->orderBy('question_id', 'desc')->paginate(20);
return QuestionLiteResource::collection($questions);
}
Question: How can I use now $questions result and query again with LIKE statement. So far I tried many thing, for example like this, but something is missing as I am getting errors:
public function showQuestions($category, $queryQuestion)
{
$myArray = array($category);
$chary = $queryQuestion;
$questions = Question::whereIn('question_id', function ($query) use ($myArray) {
$query->select('question_id')
->from('condition_question')
->whereIn('condition_id', $myArray);
})->get();
$results = $questions->where('question_title', 'LIKE', "%{$chary}%")->get();
return QuestionLiteResource::collection($results->values());
}
I know it is not my best, but need some help...It would be also cool to have paginated result at the end.
So, how to get collection of questions from questions table where title has char. Any help would be most welcomed!
You might know that once you call get() function, you got the results and not able to query any further. Maybe this is gonna work:
public function showQuestions($category, $queryQuestion)
{
$myArray = array($category);
$chary = $queryQuestion;
$questions = Question::whereIn('question_id', function ($query) use ($myArray) {
$query->select('question_id')
->from('condition_question')
->whereIn('condition_id', $myArray);
})
->where('question_title', 'LIKE', "%{$chary}%")
->get();
return QuestionLiteResource::collection($questions);
}
Since you have called get() on question query, you get the result as an Laravel Collection.
To filter through collection you can use filter() function.
Example Code
$results = $questions->filter(function($question) use ($chary) {
return Str::contains($question->question_title, $chary);
});
i think you can use join():
public function showQuestions($category, $queryQuestion)
{
$myArray = array($category);
$chary = $queryQuestion;
$query = Question::getModel()->newQuery();
$questions = $query
->join('condition_question', function (Builder $join) use ($myArray) {
$join->on('questions.question_id', '=', 'condition_question.question_id');
$join->whereIn('condition_question.condition_id', $myArray);
})
->where('questions.question_title', 'like', $chary)
->orderBy('questions.question_id', 'desc')
->paginate(20)
return QuestionLiteResource::collection($questions);
}

Laravel query whereIn - show results from which search

I have an array that comes to controller's action.
$arrOfTags = $request['position'];
That array looks like :
['manager', 'consultant'];
Next, I am querying the DB for CV's where position is one of these.
$query = Cv::query();
$query->whereIn('position', $arrOfTags);
...
->get();
Now the question :
If $request['position'] = ['manager','consultant']; and whereIn clause finds result just for position = 'consultant' and none for 'manager', how can I programmatically discover that results are found for 'consultant' and/or didn't found for 'manager' ?
EDIT
All my query's code :
$arrOfTags = explode(',', $request['position']);
$query = Cv::query();
$query->whereIn('position', $arrOfTags)
if($request['salary']) {
$query->whereIn('salary', $request['salary']);
}
if($request['skill']) {
$query->join('skills', 'cvs.id', '=', 'skills.cv_id')
->join('allskills', 'skills.allskills_id', '=', 'allskills.id')
->select('cvs.*', 'allskills.name AS skillName')
->whereIn('skills.allskills_id', $request['skill']);
}
if($request['language']) {
$query->join('languages', 'cvs.id', '=', 'languages.cv_id')
->join('alllanguages', 'languages.alllanguages_id', '=', 'alllanguages.id')
->select('cvs.*', 'alllanguages.name as languageName')
->whereIn('languages.alllanguages_id', $request['language']);
}
$cvs = $query->distinct()->get();
Imagine that $arrOfTags values are ['manager', 'consultant', 'sales']
I want somehow to discover that results was found for position =
manager and consultant, and didn't found for position = 'sales'
You can load the data from DB:
$cvs = CV::....;
And then use the partition() method:
list($manager, $consultant) = $cvs->partition(function ($i) {
return $i['position'] === 'manager';
});
Or the where() method:
$manager = $cvs->where('position', 'manager');
$consultant = $cvs->where('position', 'consultant');
Both partition() and where() will not execute any additional queries to DB.
You can do this way too:
$managers = $collection->search(function ($item, $key) {
return $item['position'] === "manager";
});
$consultants = $collection->search(function ($item, $key) {
return $$item['position'] === "consultant";
});
You could use count().
if(($query->count)==($query->where('position','consultant')->count())){
///all are coming for position=consultants
}
Or you could use groupBY-
$query = $query->groupBy('position')->toArray();
And retrieve by-
$consultants = $query['consultant'];

Laravel modify Collection data

I wonder if Laravel have any helper to modify a collection.
What I need to do is to make a query with paginate() then check if the logged in users ID match the sender or receiver and based on that add a new value to the output:
$userId = Auth::guard('api')->user()->user_id;
$allMessages = Conversation::join('users as sender', 'conversations.sender_id', '=', 'sender.user_id')
->join('users as reciver', 'conversations.recipient_id', '=', 'reciver.user_id')
->where('sender_id',$userId)->orWhere('recipient_id',$userId)
->orderBy('last_updated', 'desc')
->select('subject','sender_id','recipient_id', 'sender_unread', 'recipient_unread', 'last_updated', 'reciver.username as receivername', 'sender.username as sendername')
->paginate(20);
Now I want to do something like:
if ($allMessages->sender_id == $userId) {
// add new value to output
newField = $allMessages->sendername
} else {
// add new value to output
newField = $allMessages->receivername
}
Then send the data with the new value added
return response()->json(['messages' => $allMessages], 200);
Is this possible?
You're better off using the Collection class's built-in functions for this. For example, the map function would be perfect.
https://laravel.com/docs/5.3/collections#method-map
$allMessages = $allMessages->map(function ($message, $key) use($userId) {
if ($message->sender_id == $userId) {
$message->display_name = $message->receivername;
} else {
$message->display_name = $message->sendername;
}
return $message;
});
Solved by adding:
foreach ($allMessages as $message) {
if ($message->sender_id == $userId) {
$message->display_name = $message->receivername;
} else {
$message->display_name = $message->sendername;
}
}
You can surely use the laravel's LengthAwarePaginator.
Along with total count of collection you also need to pass the slice of collection's data that needs to be displayed on each page.
$total_count = $allMessages->count();
$per_page = 2;
$current_page = request()->get('page') ?? 1;
$options = [
'path' => request()->url(),
'query' => request()->query(),
];
Suppose you want 2 results per page then calculate the offset first
$offset = ($current_page - 1) * $per_page;
Now slice the collection to get per page data
$per_page_data = $collection->slice($offset, $per_page);
$paginated_data = new LengthAwarePaginator($per_page_data, $total_count, $per_page, $current_page, $options);
$paginated_data will have only limited number of items declared by $per_page variable.
If you want next two slice of data then pass api_request?page="2" as your url.
As I don't know which Laravel version you're using, taking Laravel 5.2 let me give you a smarter way to deal with this (if I get your problem correctly).
You can use Laravel's LengthAwarePaginatior(API Docs).
Don't use paginate method when you are bulding your query, instead of that use simple get method to get simple collection.
$userId = Auth::guard('api')->user()->user_id;
$allMessages = Conversation::join('users as sender', 'conversations.sender_id', '=', 'sender.user_id')
->join('users as reciver', 'conversations.recipient_id', '=', 'reciver.user_id')
->where('sender_id',$userId)->orWhere('recipient_id',$userId)
->orderBy('last_updated', 'desc')
->select('subject','sender_id','recipient_id','sender_unread','recipient_unread','last_updated','reciver.username as receivername','sender.username as sendername')
->get();
Now you can populate extra items into that collection based on your certain conditions like this.
if ($allMessages->sender_id == $userId ) {
// add new value to collection
} else {
// add new value to collection
}
Now use LengthAwarePaginator, to convert that populated collection into a paginated collection.
$total_count = $allMessages->count();
$limit = 20;
$current_page = request()->get('page');
$options = [
'path' => request()->url(),
'query' => request()->query(),
];
$paginated_collection = new LengthAwarePaginator($allMessages, $total_count, $limit, $current_page, $options);
The variable $paginated_collection now can be used to be sent in response. Hope this helps you to deal with your problem.

Laravel conditions in Controller where clause

I'm trying to build a query based on URL parameters. When the Controller is loaded I need to check which parameters have been provided and build a query from them. It's working with static values, but isn't working with conditional statements. Is my laravel syntax correct?
class OrdenesController extends BaseController {
public function showOrdenes($action)
{
$my_id = Auth::user()->id;
$my_cod = Auth::user()->codprov;
switch ($action)
{
case 'list':
$rows = DB::table('ordens')->count();
if(Input::get("jtSorting"))
{
$search = explode(" ", Input::get("jtSorting"));
$numorden= Input::get("nro_orden");
$filtros =explode(" ", $filtros);
$data = DB::table("ordens")
->select(array('*', DB::raw('SUM(cant_pend) as cant_pend'), DB::raw('SUM(importe) as importe')))
->where('cod_prov', '=', $my_cod)
->where('nro_orden', '=', $numorden)///work
---------- ////no work
if (Input::has('nro_orden')) {
->where('nro_orden', '=', $numorden)
}
---------- /// no work
->groupBy('nro_orden')
->skip(Input::get("jtStartIndex"))
->take(Input::get("jtPageSize"))
->orderBy($search[0], $search[1])
->get();
}
return Response::json(
array(
"Result" => "OK",
"TotalRecordCount" => $rows,
"Records" => $data
)
);
break;
};
}
}
You are missing the variables, no? You haven't told PHP what variable/object to do the where() to in your condition. The magic of Laravel's Eloquent (and a lot of other libraries) is that when you call its methods, it returns itself (the object) back so you can make another method call to it right away.
So when you do this:
$data = DB::table("ordens")
->select(...)
->where(...);
is the same as:
$data = DB::table("ordens");
$data = $data->select(...);
$data = $data->where(...);
But you are trying to do ->where(...) right away after if condition. You need to tell PHP which object/variable you are trying to call the method from. Like this:
$num = Input::get("nro_orden");
$data = DB::table("ordens")
->select(array('*', DB::raw('SUM(cant_pend) as cant_pend'), DB::raw('SUM(importe) as importe')))
->where('cod_prov', '=', $my_cod);
if (Input::has('nro_orden')) {
$data = $data->where('nro_orden', '=', $num);
}
$data = $data->groupBy('nro_orden')
->skip(Input::get("jtStartIndex"))
->take(Input::get("jtPageSize"))
->orderBy($search[0], $search[1])
->get();

Categories