Laravel Factory ->each() add iterator - laravel

I have a factory:
factory(Survey::class, 3)->create()->each(function ($survey)
{
factory(Question::class, 1)
->create()
->each(function ($question)
{
factory(Option::class, rand(2,3))->create();
});
});
The problem is - I need to add an index to every option. It should be 1,2,3...
How can I add iterator to ->each() function?
I've tried to add variables inside body of the loop, but in not works as for/foreach one.
ANy ideas?

If I get your question right.
The each method iterates over the items in the collection and passes each item to a callback. If you will add second argument to each it will be an index of current element, which you can use later inside.
$collection->each(function ($item, $key) {
//
});
https://laravel.com/docs/5.7/collections#method-each

Related

Dump within map function in Laravel

Within a map function i would like to use dd(); dump but i only get the first object.
When i use print_r(); within a map function i get all objects
$valeurCategorieCible = $CategoriesItineraires->map(function ($item) {
return $item->ciblesParCategorie->map(function ($ciblesParCategorie) {
return $ciblesParCategorie->cibles->map(function ($items) {
print_r($items); // Return all objects
dd($items); // Return only the first object then stop !
});
});
});
According to the documentation for dd() it "dumps the given variables and ends execution of the script" - the important part is "ends execution of the script"!
If you don't want to end execution use dump() instead of dd()

Laravel session has value

if(! session()->exists('disease', $val)){
$request->session()->push('disease', $val);
}
I want to add a value (text) for disease only if it is not in array. How to archive this in Laravel 8? I can assign the session array to a var and do a php array_unique. But is there a beautiful way in Laravel?
Thank you all.
->exists() only takes a single argument, $key:
https://github.com/laravel/framework/blob/8.x/src/Illuminate/Contracts/Session/Session.php#L64.
If you want to check that 'disease' is in the session and equals $val, then you can do:
if (session()->get('disease', null) !== $val) {
session()->push('disease', $val);
}
If 'disease' in the session is present and already equal to $val, then nothing will happen. Otherwise, it will add it to the session.
Edit: Since 'disease' is an array, not a single value, you'll need to adjust your code a bit:
$diseases = session()->get('disease', []);
if (!in_array($val, $diseases)) {
$diseases[] = $val;
session()->put('disease', $diseases);
}
You should be able to use ->push() as suggested in the comments, and as evidenced by your current 'disease' array, but the same idea applies; only append to the array if it's not already there.

Updating a collection and returning it

I want to update a collection before looping through it.
Is there a way to set the sent value of the emails collection to true and return the collection before actually looping through it.
$emails = Email::where('sent', false);
$emails->update(array("sent" => true));
foreach ($emails as $email) {
//send email
}
I want to be able to call ->get() somewhere but I cant do it on the update or the initial query
Don't forget to call get on the Email::where('sent', false) that is an Illuminate\Eloquent\Builder instance.
You can use something like this:
tap(Email::where('sent', false)->get(), function ($emails){
Email::whereIn('id', $emails->pluck('id')->all())->update(['sent' => true]);
})->each(function($email){
// Send email
});
The tap function accepts two arguments, first one is a value that you want to run the second argument(which is a callback) on it, then the tap function returns you that first passed value and here you can easily loop through.
See Here for tap

Laravel chunk returns null

I'm needing to chunk my query as it's making PHP run out of memory, however the below code just dumps null:
$chunked = $query->chunk(25, function ($events) {
//dd($events);
});
dd($chunked);
However, when I do the below, it dumps the first chunk of 25:
$chunked = $query->chunk(25, function ($events) {
dd($events);
});
//dd($chunked);
No combination of changing dd($events); to the likes of return $events, return true, iterating over each item in each chunk and returning that - works.
Am I stupid/doing something wrong or is this not working like it should?
chunk() is a helper method which you can use on an instance of Query Builder or Eloquent Builder. In both cases, the method returns void:
Query Builder
Eloquent Builder
This means that your $chunked variable will be always empty.
The syntax you need to employ is the following:
Query Builder
DB::table('users')->chunk(100, function($users) {
foreach ($users as $user) {
//
}
});
Eloquent
Flight::chunk(200, function ($flights) {
foreach ($flights as $flight) {
//
}
});
Basically, all you need to do is to use a loop within the callback function of chunk() to modify your results.

Route to two methods of controller with one row in Laravel 4

It is simple to route this way:
Route::get('user/profile', 'PaymentsController#profile');
Route::get('user/delete', 'PaymentsController#delete');
I want to do this with one row:
Route::get('user/{subsection}', 'PaymentsController#'.$subsection);
but my syntax seems to be wrong. Is it possible to be done with one row? It would be nice if it is possible.
No, you can't do that, but you can make proxy method
Route::get('user/{subsection}', 'PaymentsController#profileDelete');
And method will looks like
public function profileDelete($subsection) {
return $this->$subsection();
}
public function profile(){}
public function delete(){}
Also, you can bind {subsection}
Route::bind('subsection', function ($subsection) {
if (!in_array($subsection, ['profile', 'delete'])) {
throw new Exception;
}
return $subsection;
});
Not exactly one row, but you can do this:
Route::get('user/{subsection}', function($subsection){
if(!method_exists('PaymentsController', $subsection)){
App::abort(404);
}
return App::make('PaymentsController')->callAction($subsection);
});
Alternatively to the method_exists you could also use a route condition to only allow a predefined set of subsections:
Route::get('user/{subsection}', function($subsection){
return App::make('PaymentsController')->callAction($subsection);
})->where('subsection', '(profile|delete)');

Resources