Laravel session has value - laravel

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.

Related

In laravel livewire, I want to get the user only if it's value changed from specific value to another specific value

Here is the code in which I get the user if it's g10_eng_unwh is equal to 1.
public function purchased(User $user)
{
if ($user->g10_eng_unwh == 1) {
$token = "g10_eng_unwh";
}
if ($user->g7_eng_unwh == 1) {
$token = "g7_eng_unwh";
}
$time = Carbon::now()->format('Y-m-d');
dd($user->email, $time, $token);
}
Instead, I want to get the user only when it's g10_eng_unwh value changes from 0 to 1.
Is there any way?
You need to get the past value at the beginning so that you can apply the condition, it will have to be stored somewhere. Most likely you will need to create g10_eng_unwh_old or something like that. I assume that g10_eng_unwh is a column in the database, in this case create g10_eng_unwh_old and store the old value in it.
In this case, you could get it even on request. For example
DB::query()
->where('g10_eng_unwh', 1)
->where('g10_eng_unwh_old', 0)
->get();

How can I cross join dynamically in Laravel?

I want to create product variations like this image:
I have tried with static data it works.
$collection = collect(["XL", "XXL"]);
return $collection->crossJoin(["1kg", "2kg"], ["Red", "Green"]);
But I want to create this dynamically. I have tried this way.
$collections = [];
foreach ($request->options as $key => $option) {
if($key == 0) continue;
array_push($collections, $option["option_values"]);
}
return $collection->crossJoin($collections);
Its return like this image.That is not exact I want. I figured out problem that is $collections is a new array and option values inside this array. So that it's return like this. But I can not solve this problem.
I have dd my request data.
You were on the right track. The way I see it you need something like:
// all of my options
$options = [];
// Just store all options in the array
// I am going to assume $option["option_values"] is always an array
foreach ($request->options as $key => $option) {
array_push($options, $option["option_values"]);
}
// Get the first element so we can use collections
// and the crossJoin function
$start = array_shift($options);
return collect($start)->crossJoin(...$options);
The (...$options) kind of explodes all elements in the array and sets them as paramenters.
Some people may tell you to use the function call_user_func_array which allows you to call a function with its arguments as an array, like so...
call_user_func_array('some_function', ['argument1', 'argument2']);
Unfortunately I have never used this function. If there is someone with more experience who can implement it, I would like to know how it would be done.

Laravel check if updateOrCreate performed an update

I have the following code in my controller:
for($i=0; $i<$number_of_tourists; $i++) {
$tourist = Tourist::updateOrCreate([
'doc_number' => $request['doc_number'][$I]
],
$tourist_to_update);
}
Each time updateOrCreate runs, it does 1 of 3 things:
Updates the model instance; OR
Creates and saves a new one; OR
Leaves everything unchanged (if model with such values already exists)
I need to check if updateOrCreate has done the first one (updated) and then execute some code.
How can I do it?
You can figure it out like this:
$tourist = Tourist::updateOrCreate([...]);
if(!$tourist->wasRecentlyCreated && $tourist->wasChanged()){
// updateOrCreate performed an update
}
if(!$tourist->wasRecentlyCreated && !$tourist->wasChanged()){
// updateOrCreate performed nothing, row did not change
}
if($tourist->wasRecentlyCreated){
// updateOrCreate performed create
}
Remarks
From Laravel 5.5 upwards you can check if updates have actually taken place with the wasChanged and isDirty method.
isDirty() is true if model attribute has been changed and not saved.
wasChanged() is true if model attribute has been changed and saved.
There is also a property (not method!) wasRecentlyCreated to check if user was created or not.
$user = factory(\App\User::class)->create();
$user->wasRecentlyCreated; // true
$user->wasChanged(); // false
$user->isDirty(); // false
$user = \App\User::find($user->id);
$user->wasRecentlyCreated; // false
$user->wasChanged(); // false
$user->isDirty(); // false
$user->firstname = 'Max';
$user->wasChanged(); // false
$user->isDirty(); // true
$user->save();
$user->wasChanged(); // true
$user->isDirty(); // false
//You can also check if a specific attribute was changed:
$user->wasChanged('firstname');
$user->isDirty('firstname');
You can checkout the link to the laravel's documentation for wasChanged and isDirty methods.
https://laravel.com/docs/8.x/eloquent#examining-attribute-changes or
https://laravel.com/docs/9.x/eloquent#examining-attribute-changes
It is pretty easy to determine if the function resulted in an update or an insert (check the wasRecentlyCreated property). However, when using that function, it is less easy to determine if the update actually happened (if the model exists but is not dirty, no update will be performed). I would suggest not using that function, and splitting out the functionality yourself.
This is the function definition:
public function updateOrCreate(array $attributes, array $values = [])
{
$instance = $this->firstOrNew($attributes);
$instance->fill($values)->save();
return $instance;
}
To integrate this into your code, I'd suggest something like:
for ($i=0; $i<$number_of_tourists; $i++) {
$tourist = Tourist::firstOrNew(['doc_number' => $request['doc_number'][$i]]);
$tourist->fill($tourist_to_update);
// if the record exists and the fill changed data, update will be performed
$updated = $tourist->exists && $tourist->isDirty();
// save the tourist (insert or update)
$tourist->save();
if ($updated) {
// extra code
}
}
Okay so I couldn't find a good answer for my scenario.
I was using: $this->created_at == $this->updated_at however I would sometimes update the record later in the request, which meant that 20% of the time the created_at and updated_at were about 1ms out.
To combat this I created something a little more relaxed which allows an extra second between creation and modification.
public function getRecentlyCreatedAttribute()
{
return $this->wasRecentlyCreated || $this->created_at == $this->updated_at || $this->created_at->diffInSeconds($this->updated_at) <= 1;
}
I can now call $this->recentlyCreated which will return true if there is a small difference in time (1 second).
Tbh this is the second time I've needed this in a project, I'm posting as I just ended up googling it and coming back to this thread looking for the same answer.
If someone has a more elegant solution, hmu.
#patricus below presented a working way to solve the problem.
though #TheFallen here gave a solution which uses Eloquent Events and seems more elegant:
Laravel Eloquent Events - implement to save model if Updated
The model attribute 'wasRecentlyCreated' would only be 'true' if it has just been created.
There is property named 'changes' in model (it is an array), that determines whether the model has been updated with new values or it has been saved as is without making any changes to its attribute.
Check the following code snippet:
// Case 1 : Model Created
if ($model->wasRecentlyCreated) {
} else { // Case 2 : Model Updated
if (count($model->changes)) { // model has been assigned new values to one of its attributes and saved successfully
} else { // model has NOT been assigned new values to one of its attributes and saved as is
}
}

How to increment a column using Eloquent Model in Laravel 4

I am not sure how to increment the value in a column using Eloquent Model in Laravel 4?
This is what I currently have and I am not sure how correct is this.
$visitor = Visitor::where('token','=','sometoken')->first();
if(isset($visitor)){
$visitor->increment('totalvisits');
}else{
Visitor::create(array(
'token'=>'sometoken',
'totalvisits'=>0
));
}
With Query Builder we could do it using
DB::table('visitors')->increment('totalvisits');
Looks like the code that I posted worked after all
$visitor = Visitor::where('token','=','sometoken')->first();
if(isset($visitor)){
$visitor->increment('totalvisits');
}else{
Visitor::create(array(
'token'=>'sometoken',
'totalvisits'=>0
));
}
Prior to a fix a few weeks ago the increment method actually fell through to the query builder and would be called on the entire table, which was undesirable.
Now calling increment or decrement on a model instance will perform the operation only on that model instance.
Laravel 5 now has atomic increment:
public function increment($column, $amount = 1, array $extra = [])
{
if (! is_numeric($amount)) {
throw new InvalidArgumentException('Non-numeric value passed to increment method.');
}
$wrapped = $this->grammar->wrap($column);
$columns = array_merge([$column => $this->raw("$wrapped + $amount")], $extra);
return $this->update($columns);
}
which essentially works like:
Customer::query()
->where('id', $customer_id)
->update([
'loyalty_points' => DB::raw('loyalty_points + 1')
]);
Below is old answer for Laravel 4 where the built-in increment was a seperate select and then update which of course leads to bugs with multiple users:
If you'd like to accurately count your visitors by ensuring the update is atomic then try putting this in your Visitor model:
public function incrementTotalVisits(){
// increment regardless of the current value in this model.
$this->where('id', $this->id)->update(['totalVisits' => DB::raw('last_insert_id(totalVisits + 1)')]);
//update this model incase we would like to use it.
$this->totalVisits = DB::getPdo()->lastInsertId();
//remove from dirty list to prevent any saves overwriting the newer database value.
$this->syncOriginalAttribute('totalVisits');
//return it because why not
return $this->totalVisits;
}
I'm using it for a change tag system but might work for your needs too.
Does anyone know what to replace the "$this->where('id',$this->id)" with because since dealing with $this Visitor it should be redundant.

Can't save filenames into the database with JInput

I have a form with input fields of type text and file. I have a problem of the filenames not saving in the database but everything else does. I vardumped $myForm and everything is there but the files, so I created another array with the filenames and merged it with $myForm. I then tried to set it to 'jform' but it doesn't seem to be working. Anyone have any ideas to why? Thanks!
controller.php
function save()
{
$jinput = JFactory::getApplication()->input;
$myForm = $jinput->get('jform', null, 'array');
//$files = $jinput->files->get('jform');
$file_array = ['image1' => 'test.png',
'image2' => 'test2.png'];
$merged_array = array_merge($myForm, $file_array);
$jinput->set('jform',$merged_array);
//or $jinput->post->set('jform',$merged_array); (this doesn't work either)
return parent::save();
}
Do not use $_POST unless you plan on writing extensive validation code to secure the user input.
Instead, use $jinput->get('jform', null, 'raw');
This will still apply some validation, but should keep your values in tact.

Resources