Laravel get updated request value after merge - php

I am attempting to modify a Laravel Request object using merge to update the key trial_end.
I am doing this using the following code...
if ($this->request->get('trial_end', '')) {
$this->request->merge(array('trial_end' => 'test'));
}
dd($this->request->all(), $this->request->get('trial_end'));
I expect $this->request->get('trial_end') to be test, but it is not. $this->request->all() returns what I expected.
Result of die dump
array:1 [
"trial_end" => "test"
]
"12/4/2018"
How come it is not returning the updated value?

Figured it out. The solution was to change
$this->request->get('trial_end');
to
$this->request->input('trial_end');
This works because input() adds the data in all() to getInputSource()->all() before doing a data_get on that, whereas get() just performs a data_get on the input parameters (pre-modifications).
New code (with a change suggested by Alex)
if ($this->request->has('trial_end')) {
$this->request->merge(['trial_end' => 'test']);
}
dd($this->request->all(), $this->request->input('trial_end'));
New results
array:1 [
"trial_end" => "test"
]
"test"
Hope this helps any others that come across this issue.

the problem it's not with the assignment, but with the comparison, here's my personally best way to check if a value in the request has been set.
public function test(Request $request){
if (!$request->has('trial_end')) { //this is what you have wrong
$request->merge(array('trial_end' => 'test'));
}
return $request->get('trial_end');
}
greetings

Related

How do i resolve Call to a member function only() on array error

I want to use laravels FormRequest to validate before updating some fields. This works fine if i just use:
User::find($application->userid)->fill($request->only('first_name'...
but the request also contains sub array ($request->programmeData).
array:2 [▼
"programme_id" => 5
"programme_title" => "some programme title"
]
if i try access that the same way i get 'Call to a member function only() on array':
Course::find($application->userid)->fill($request->programmeData->only('programme_id...
I've tried a handful of things, but not sure best way to go with this?
Update
I'm now using a foreach loop to save two items in the array. the example below saves the second value for both user_ids. any reason this isn't saving the first value for the first user_id?
foreach ($request->programmeData['userProgrammes'] as $key=>$userProgrammes) {
Course::where('application_id', $application->id)->get()[$key]->fill(Arr::only($request->programmeData['userProgrammes'][$key], ['programme_id']))->save();
}
but nothing updates. Any ideas on this one?
You can use Array::only() helper for this:
foreach ($request->programmeData['userProgrammes'] as $key=>$userProgrammes) {
Course::where('application_id', $application->id)->first()->fill([
$key => Arr::only($request->programmeData['userProgrammes'][$key], ['programme_id'])
])->save();
// or
$course = Course::where('application_id', $application->id)->first()
$course->$key = Arr::only($request->programmeData['userProgrammes'][$key], ['programme_id']);
$course->save();
}
//Arr::only($request->programmeData, ['programme_id', ...]);

Laravel Collection Transform/Map Method Inconsistent Behaviour

In my HTML frontend, I have a jQuery DataTable displaying all records fetched via AJAX from the database - a rather pretty straight forward thing. I use the Laravel Collection's ->transform(function($o){ . . . }) to iterate through the collection and return it in an array-esque manner. Just think of the following piece of code in a controller:
$cAllRecords = DatabaseRecord::all();
if(!empty($aData['sFilterIds']))
{
$cAllRecords = $cAllRecords->whereIn('creator', explode(',', $aData['sFilterIds']));
}
return response()->json(['data' => $cAllRecords->transform(function ($oDatabaseRecord) {
/** #var $oDatabaseRecord DatabaseRecord */
$sActionsHtml = 'edit';
$sUrl = route('some.route', ['iDatabaseRecordId' => $oDatabaseRecord->getAttribute('od')]);
return [
$oDatabaseRecord->getAttribute('id'),
$oDatabaseRecord->getAttribute('updated_at')->toDateTimeString(),
$oDatabaseRecord->getAttribute('created_at')->toDateTimeString(),
$sActionsHtml
];
})]);
I'm actually just filtering for records created by certain user IDs (the whereIn() call in line 4. However, the response sent back to the client looks different for different users filtered leading the jQuery table to show 'no records available', as it had received an malformed answer from the server. For one user, the response looks like this:
{
"data":[
[
1,
"2019-05-29 16:44:53",
"2019-05-29 16:44:53",
"<a href=\"#\">edit<\/a>"
]
]
}
This is a correctly formed server response and will show up in the table regularly. Great! Now something that drives me insane - the same code for another user (ID 1, while the first request was for user ID 2) returns this:
{
"data":{
"1":[
3,
"2019-05-29 17:08:49",
"2019-05-29 17:08:49",
"<a href=\"#\">edit<\/a>"
]
}
}
which, pretty obviously, is malformed and is not correctly parsed by the datatable. OK, now combing them two filters and filtering for user ID 1 and 2 will, again, return the response correctly formatted:
{
"data":[
[
1,
"2019-05-29 16:44:53",
"2019-05-29 16:44:53",
"<a href=\"#\">edit<\/a>"
],
[
3,
"2019-05-29 17:08:49",
"2019-05-29 17:08:49",
"<a href=\"#\">edit<\/a>"
]
]
}
I tried a number of things, none of which had worked since it's merely guessing why it could work with one user and not with another. (Things like reversing the order of IDs to be filtered, etc., but I found out that the filtering is not the problem. It MUST be the transform, which behaves inconsistent.)
Any ideas on why this happens and how to tackle it? I mean, it's not the only way to achieve what I'm after, I was using ->each() and array_push for all the time before but wanted to get rid of it for the sake of making use of Laravel's helpers (or possibilites) - the manual iteration and array pushing process worked out seamlessly before, and even other parts of the app work well with the Collection transform over array iteration and pushing. Why doesn't it here?
Update: The ->map() collection method behaves exactly same. Map, as opposed by transform, does not alter the collection itself. However, this should not be a relevant part within this application any way. I really can't understand what's going wrong. Is this possibly Laravel's fault?
Please note that transform method returns a Illuminate\Support\Collection.
It's better that you call all() after the transform to get an array result.
Like this:
...
return response()->json(['data' => $cAllRecords->transform(function ($oDatabaseRecord) {
/** #var $oDatabaseRecord DatabaseRecord */
$sActionsHtml = 'edit';
$sUrl = route('some.route', ['iDatabaseRecordId' => $oDatabaseRecord->getAttribute('od')]);
return [
$oDatabaseRecord->getAttribute('id'),
$oDatabaseRecord->getAttribute('updated_at')->toDateTimeString(),
$oDatabaseRecord->getAttribute('created_at')->toDateTimeString(),
$sActionsHtml
];
})->all()]);
#Cvetan Mihaylov's answer made me look at all the available collection methods (https://laravel.com/docs/5.8/collections#available-methods) and I found ->values() to return the values reindexed. And - that did the trick! :-)
return response()->json(['data' => $cAllRecords->transform(function ($oDatabaseRecord) {
/** #var $oDatabaseRecord DatabaseRecord */
$sActionsHtml = 'edit';
$sUrl = route('some.route', ['iDatabaseRecordId' => $oDatabaseRecord->getAttribute('od')]);
return [
$oDatabaseRecord->getAttribute('id'),
$oDatabaseRecord->getAttribute('updated_at')->toDateTimeString(),
$oDatabaseRecord->getAttribute('created_at')->toDateTimeString(),
$sActionsHtml
];
})->values()]);

Update Value of Session of only a single key in laravel

I have an input like below.
array:4 [
"_token" => "evktHCfCNZVQMNYXzntfHZkdNLZFqvOoYgU3yPKy"
"name" => "Name"
"orderId" => "5cb5943a6733a1555403834"
"amount" => null
]
which I stored to a session like this:
public function store(Request $request)
{
request()->session()->put('bookingInfo', $request->input());
return redirect()->route('book.checkout');
}
Now I want to change the amount value in the session. How I am going to achieve that?
To update the value, you need to retrieve the values from session and update it again.
To do that, you need to do
$booking_info = $request->session()->get('bookingInfo');
Then you will got an array back. Update it like a normal array
$booking_info["amount"] = 10; // anything you wanted
If you need to put it back into session again you can do this
$request->session()->put('bookingInfo', $booking_info);
EDIT
If you want the ability to update partially, you would need to store it separately like this.
$input = $request->all();
$request->session()->put('bookingInfo.name', $input['name']);
$request->session()->put('bookingInfo.orderId', $input['orderId']);
$request->session()->put('bookingInfo.amount', $input['amount']);
Laravel 5+
// Via a request instance...
$request->session()->put('amount', 'value');
// Via the global helper...
session(['amount' => 'value']);
// For retrieve
session('amount');

Laravel - pluck with specified keys

I have a line of code similar to the following:
Sport::pluck('id', 'name)
I am dealing with frontend JavaScript that expects a list in this format:
var list = [
{ text: 'Football', value: 1 },
{ text: 'Basketball', value: 2 },
{ text: 'Volleyball', value: 3 }
...
]
I am trying to figure out how I can somehow transform the id and name values that I pluck from my model to a format similar to the Javascript list.
If that's unclear, I am looking to end up with an associative array that contains two keys: text and value, where text represents the name field on my model, and where value represents the id of the model - I hope this makes sense.
How would I approach this?
I initially tried something like this (without checking the documentation)
Sport::pluck(["id" => "value", "name" => "text]);
But that isn't how you do it, which is quite clear now. I've also tried some map-related snippet, which I cannot seem to Ctrl-z to.
Any suggestions?
Another method is to use map->only():
Sport::all()->map->only('id', 'name');
The purpose of pluck is not what you intend to do,
Please have a look at below examples,
Sport::selectRaw("id as value, name as text")->pluck("text","value");
// ['1' => 'Football', '2'=>'BasketBall','3'=>'Volleyball',...]
Syntax
$plucked = $collection->pluck('name', 'product_id');
// ['prod-100' => 'Desk', 'prod-200' => 'Chair']
Please see the documentation.
Your output is possible using simple code.
Sport::selectRaw('id as value, name as text')->get();
You could use map.(https://laravel.com/docs/5.8/collections#method-map)
$mapped = Sport::all()->map(function($item, $index) {
return [
"id" => $item["id"],
"name" => $item["text"]
];
});
This is the easiest way. Actually Laravel offers a better way for it. You can use api resources to transform your data from eloquent for the frontend:
https://laravel.com/docs/5.8/eloquent-resources
Try with toArray function:
Sport::pluck('id', 'name)->toArray();
Then you can return your result with json_encode php function;

Yii2: get value of attribute that has a behavior

I'm using the TimestampBehaviour like this:
public function behaviors() {
return [
[
'class' => \yii\behaviors\TimestampBehavior::className(),
'createdAtAttribute' => 'usr_date_added',
'updatedAtAttribute' => 'usr_date_modified',
'value' => new \yii\db\Expression('UTC_TIMESTAMP()'),
],
];
}
Then if access it through the authenticated user like this...
Yii::$app->user->identity->usr_date_modified;
...I get the expression instead of the actual value:
object(yii\db\Expression)#38 (2) {
["expression"]=>
string(15) "UTC_TIMESTAMP()"
["params"]=>
array(0) {
}
}
If I do it like this I correctly get the actual value:
$user = app\models\User::findOne(51);
echo $user->usr_date_modified;
Why is that? And how can I get the actual value through the identity property?
The value while not saved in the database holds the information about how this actual value should be created - in your case it uses UTC_TIMESTAMP() MySQL function that will be called at the moment of saving this object into DB.
When you are retrieving object already saved in the database it takes whatever has been saved there (in your case the result of this MySQL function), so it gives you actual timestamp.
Before saving the object there is no point of checking this value.
I realized that I have modified an attribute and then called the save() method. You would think it should then hold the actual value after calling save() but it doesn't - I guess because doing the UPDATE query the database doesn't return the value. You need to call the refresh() method (see documentation) to make another SELECT query to get the new value. So you would need to do it like this:
Yii::$app->user->identity->usr_last_access = gmdate('Y-m-d H:i:s');
Yii::$app->user->identity->save();
Yii::$app->user->identity->refresh();

Categories