How to update alias column in Laravel - laravel

I want to update records in Postgresql DB and Laravel.
The problem is that alias columns are not in relation with the table, but I made them in first place:
message: "SQLSTATE[42703]: Undefined column: 7 ERROR: column "nivo600" of relation "meas_kanal" does not exist↵LINE 1: update "meas_kanal" set "recordtime" = $1, "nivo600" = $2, "...↵
The function in controller:
$student = Stamboliiski::where('recordtime', $request->get('kanal_id'))
->selectRaw('recordtime')
->selectRaw('max(formattedvalue) filter (where fullname = \'text 1\') as nivo600')
->selectRaw('max(formattedvalue) filter (where fullname = \'text 2\') as razhod600')
->update([
'recordtime' => $request->input('recordtime'),
'nivo600' => $request->input('formattedvalueN'),
'razhod600' => $request->input('formattedvalueR'),
])
->where(function ($query) {
$query->where('fullname', 'like', "text 1")
->orWhere('fullname', 'like', "text 2");
})
->groupBy('recordtime')
->orderBy('recordtime')
->first();
$success_output = '<div class="alert alert-success">The record is updated!</div>';
Model:
class Stamboliiski extends Model
{
protected $connection = 'stamboliiski';
protected $table = 'meas_kanal';
protected $fillable = ['fullname','formattedvalue','recordtime','qualitydesc','statedesc','author','id'];
}
Why?
EDIT 1 after comment of #Dimitri Mostrey:
$student = Stamboliiski::where('recordtime', $request->get('kanal_id'))
->selectRaw('recordtime')
->selectRaw('max(formattedvalue) filter (where fullname = \'text 1\') as nivo600')
->selectRaw('max(formattedvalue) filter (where fullname = \'text 2\') as razhod600')
->where(function ($query) {
$query->where('fullname', 'like', "text 1")
->orWhere('fullname', 'like', "text 2");
})
->groupBy('recordtime')
->orderBy('recordtime')
->first();
$student->recordtime = $request->get('recordtime');
$student->nivo600 = $request->get('formattedvalueN');
$student->razhod600 = $request->get('formattedvalueR');
$student->author = Auth::user()->name;
$student->save();
The error now is this:
message: "SQLSTATE[42703]: Undefined column: 7 ERROR: column "nivo600" of relation "meas_kanal" does not exist↵LINE 1: update "meas_kanal" set "nivo600" = $1, "razhod600" = $2, "a...↵ ^ (SQL: update "meas_kanal" set "nivo600" = 1.86, "razhod600" = 9.76, "author" = John Doe, "updated_at" = 2020-04-30 10:22:28 where "id" is null)"
In this method it uses id column that I don't want, and even I don't know why it used instead using the timestamp.
EDIT 2 on reply of #Uzair Riaz
Unforchantly the problem is still here. After change the controller and model is getting success message, but nothing changes. For example if I want to change value of nivo600 to 1 in recordtime 2020-04-17 00:00:00. After I echo $student in dd:
App\StamboliiskiMeasCanal {#530
#connection: "stamboliiski"
#table: "meas_kanal"
#fillable: array:8 [
0 => "fullname"
1 => "formattedvalue"
2 => "recordtime"
3 => "qualitydesc"
4 => "statedesc"
5 => "author"
6 => "id"
7 => "updated_at"
]
#mapping: array:2 [
"nivo600" => "formattedvalue"
"razhod600" => "formattedvalue"
]
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:6 [
"recordtime" => "2020-04-17 00:00:00"
"nivo600" => "1.86"
"razhod600" => "9.76"
"author" => "Христиан Йорданов"
"formattedvalue" => "9.76"
"updated_at" => "2020-05-05 06:47:26"
]
#original: array:6 [
"recordtime" => "2020-04-17 00:00:00"
"nivo600" => "1.86"
"razhod600" => "9.76"
"author" => "Христиан Йорданов"
"formattedvalue" => "9.76"
"updated_at" => "2020-05-05 06:47:26"
]
#changes: array:4 [
"recordtime" => "2020-04-17 00:00:00"
"author" => "Христиан Йорданов"
"formattedvalue" => "9.76"
"updated_at" => "2020-05-05 06:47:26"
]
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [
0 => "*"
]
}
It seems that no update is maded...

If those are the only two aliases you are going to use, I suggest overriding the ->fill() method in your model. Map your aliases to the $fillable like so:
class Stamboliiski extends Model
{
protected $fillable = ['fullname', 'formattedvalue', 'recordtime', 'qualitydesc', 'statedesc', 'author', 'id'];
protected $mapping = [
'nivo600' => 'formattedvalue',
'razhod600' => 'formattedvalue'
];
public function fill(array $attributes)
{
foreach ($attributes as $key => $value) {
if (isset($this->mapping[$key])) {
$attributes[$this->mapping[$key]] = $value;
unset($attributes[$key]);
}
}
return parent::fill($attributes);
}
}
Then you can update like so:
$student->update([
'recordtime' => $request->get('recordtime'),
'nivo600' => $request->get('formattedvalueN'),
'razhod600' => $request->get('formattedvalueR'),
'author' => Auth::user()->name
]);

Related

Laravel: test response is different from real response

In a Laravel9 project:
Controller.php
// /api/auth/user
public function show (Request $request) {
$user = $request->user();
$user->makeVisible(['email', 'email_verified_at', 'social']);
return $user;
}
The social is a nullable json column
$table->json('social')->nullable();
// 'social' => '{"facebook": "1234567890", "twitter": "1234567890"}
the actual HTTP response is (which I've verified in PostMan)
{
"id": 11,
"name": "Test User",
"email": "test#example.com",
"social": null,
"email_verified_at": "2022-12-27T02:50:58.000000Z",
"created_at": "2022-12-27T02:50:58.000000Z",
"updated_at": "2022-12-27T02:50:58.000000Z"
}
But in the Feature Test
tests/Feature/Auth/User/ShowTest.php
public function test_show_current_user () {
$user = User::factory()->create();
$response = $this->actingAs($user)->get($this->api);
$response
->assertStatus(200)
->assertJson([
'id' => $user->id,
'name' => $user->name,
'email' => $user->email,
'email_verified_at' => $user->email_verified_at->jsonSerialize(),
'social' => $user->social,
]);
}
This test will always fail since it can't find social in the $response
Once I dd() the $response, there is no social attribute at all:
update:
My User model (since so doesn't support <details>, I use code snippet to create a foldable code)
// the User model in Feature Test
App\Models\User^ {#4147 // tests/Feature/Auth/User/ShowTest.php
#connection: "sqlite"
#table: null
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
+preventsLazyLoading: false
#perPage: 15
+exists: true
+wasRecentlyCreated: true
#escapeWhenCastingToString: false
#attributes: array:8 [
"name" => "Bettie Von"
"email" => "lhermiston#example.net"
"email_verified_at" => "2022-12-27 08:51:06"
"password" => "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi"
"remember_token" => "eMBMnyRei4"
"updated_at" => "2022-12-27 08:51:06"
"created_at" => "2022-12-27 08:51:06"
"id" => 1
]
#original: array:8 [
"name" => "Bettie Von"
"email" => "lhermiston#example.net"
"email_verified_at" => "2022-12-27 08:51:06"
"password" => "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi"
"remember_token" => "eMBMnyRei4"
"updated_at" => "2022-12-27 08:51:06"
"created_at" => "2022-12-27 08:51:06"
"id" => 1
]
#changes: []
#casts: array:2 [
"email_verified_at" => "datetime"
"social" => "array"
]
#classCastCache: []
#attributeCastCache: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#hidden: array:2 [
0 => "password"
1 => "remember_token"
]
#visible: []
#fillable: array:4 [
0 => "name"
1 => "email"
2 => "password"
3 => "social"
]
#guarded: array:1 [
0 => "*"
]
#rememberTokenName: "remember_token"
#accessToken: null
}
Why is the $response in the feature test different from the actual HTTP response?
And how can I pass the feature test?
I figured it out by adding a simple $user->refresh();
$user = User::factory()
->create();
$user->refresh(); // add this
$response = $this
->actingAs($user)
->get($this->api);
Thanks a lot to #KGG, #apokryfos, and #Abdel-aziz hassan for their help.

Laravel mass assignment ignore guarded

I have a simple Laravel Eloquest Model with some fileable attributes and relations. This model is connected to DB, and worked good two months ago. After updating a table and adding a new column status, something become broken. Here is my model:
class Good extends Model
{
protected $table = 'product_goods';
public $incrementing = false;
protected $fillable = ['sku', 'status'];
/**
* #return BelongsTo
* #noinspection PhpUnused
*/
public function product() {
return $this->belongsTo(Product::class);
}
/**
* #return BelongsTo
* #noinspection PhpUnused
*/
public function color() {
return $this->belongsTo(Color::class);
}
/**
* #return BelongsToMany
*/
public function sizes() {
return $this->belongsToMany(Size::class, 'product_good_size');
}
/**
* #return BelongsTo
* #noinspection PhpUnused
*/
public function sizeStandard() {
return $this->belongsTo(SizeStandard::class);
}
/**
* #return MorphMany
* #noinspection PhpUnused
*/
public function files() {
return $this->morphMany(File::class, 'fileable')
->orderBy('show_priority');
}
/**
* #return HasMany
* #noinspection PhpUnused
*/
public function prices() {
return $this->hasMany(Price::class);
}
}
Then i'm trying to make() this model like this:
$goodData = [
'prices' => [
'RUB' => 788,
'UAH' => 499,
],
'color_id' => Color::first()->id,
'size_standard_id' => $sizeStandard->id,
'sizes' => $sizeIds,
'sku' => $faker->uuid,
'files' => [
['file' => UploadedFile::fake(),],
['file' => UploadedFile::fake(),],
['file' => UploadedFile::fake(),],
['file' => UploadedFile::fake(),],
],
];
$good = Good::make($goodData);
Then i got illegal attributes, which I dont want to see. I need only fillable attributes, but i see whole data, which is wrong.
App\Models\Product\Good^ {#1207
#table: "product_goods"
+incrementing: false
#fillable: array:2 [
0 => "sku"
1 => "status"
]
#connection: "mysql"
#primaryKey: "id"
#keyType: "int"
#with: []
#withCount: []
#perPage: 15
+exists: false
+wasRecentlyCreated: false
#attributes: array:7 [
"prices" => array:2 [
"RUB" => 788
"UAH" => 499
]
"color_id" => "6922c4e9-462f-4ce8-8028-36116845f0ea"
"size_standard_id" => "5f367199-c28a-4dc7-a979-d46f019eb2ac"
"sizes" => array:6 [
0 => array:1 [
"id" => "275c9efd-f5b6-437c-b0f1-a05c278404bd"
]
1 => array:1 [
"id" => "3090beb1-7fd3-4f79-9977-1d78abf83d09"
]
2 => array:1 [
"id" => "3121d205-101e-4cf1-8130-1bd94a2c255d"
]
3 => array:1 [
"id" => "b903d4c0-d33d-4191-8fb5-9b625b06ef7f"
]
4 => array:1 [
"id" => "deddbd28-4e72-46bc-b317-8ab8a68c2ed7"
]
5 => array:1 [
"id" => "f4139b5a-b703-4cd0-a29a-44f66aae18fc"
]
]
"sku" => "62471d6b-04c6-3b88-a9af-2960f96b78a9"
"files" => array:4 [
0 => array:1 [
"file" => Illuminate\Http\Testing\FileFactory^ {#1162}
]
1 => array:1 [
"file" => Illuminate\Http\Testing\FileFactory^ {#1187}
]
2 => array:1 [
"file" => Illuminate\Http\Testing\FileFactory^ {#1164}
]
3 => array:1 [
"file" => Illuminate\Http\Testing\FileFactory^ {#1157}
]
]
"status" => "active"
]
#original: []
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [
0 => "*"
]
}
What do I do wrong?
Since you are using $faker->uuid I am assuming you are trying to call make() while seeding.
Mass Assignment restrictions are turned off during seeding. If you would like your model to respect Mass Assignment restrictions, you can use:
Good::reguard();
Good::make($goodData);

Model binding doesn't retrieve model data

I have this route:
Route::delete('product/{product}/attachments/{attachment}', 'AttachmentsController#destroy');
public function destroy(Product $product, Attachment $attachment)
{
dd($product);
}
and dd shows:
App\Models\Product^ {#1059
#fillable: array:3 [
0 => "title"
1 => "section_id"
2 => "sortOrder"
]
#attributes: []
#original: []
... etc
}
I can't access model data such as $product->title it will return null, so I tried to change destory method to:
public function destroy($product, Attachment $attachment)
{
$product = Product::whereId($product)->firstOrFail();
dd($product);
}
and now I can access/see the model data:
"section_id" => 18
"title" => "test product"
"sortOrder" => 217645360
"created_at" => "2020-05-05 13:34:54"
"updated_at" => "2020-05-05 13:34:54"
]
#original: array:8 [
"id" => 18
"section_id" => 18
"title" => "test product"
"sortOrder" => 217645360
"created_at" => "2020-05-05 13:34:54"
"updated_at" => "2020-05-05 13:34:54"
]
Why doesn't the model binding work? I even tried to add
public function boot()
{
parent::boot();
Route::model('product', App\Models\Product::class);
}
I tried also to do: cache:clear route:clearand composer dumpautoload I cant find why the model binding doesn't work?

Laravel model not filling 1 specific column

In my model, i have the following fillable array:
protected $fillable = [
'first_name',
'last_name',
'email',
'street',
'house_number',
'province',
'phone',
'country',
'date_of_birth',
'postcode',
'account_id',
'user_id'
];
user_id is nullable and account_id is not.
When i try to create a new entity, user_id stays null in my database.
This is my code for saving the entity:
#in controller
$this->dispatch(new Job($user = $request->user(), $client = new Client(),
$request->only($client->getFillable())
));
#in job class
$client = $this->client->create(array_merge([
'user_id ' => $this->user->id,
'account_id' => $this->user->account->id
],$this->variables));
This is all of the data going into the create method:
"user_id " => 3
"account_id" => 3
"first_name" => "patrick"
"last_name" => "vd pols"
"email" => "patrickvanderpolssad22dxsxs#live.nl"
"street" => "Dijkgraaf 2"
"house_number" => "asdasd"
"province" => "Drenthe"
"country" => "asdasdsad"
"date_of_birth" => "14-12-2019"
"postcode" => "3155GA"
Both user with ID 3 and account with ID 3 exist in my database.
After saving the entity, the user_id is null:
App\Client {#384 ▼
#fillable: array:12 [▶]
#connection: "mysql"
#table: "clients"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: true
#attributes: array:13 [▼
"account_id" => 3
"first_name" => "patrick"
"last_name" => "vd pols"
"email" => "patrickvanderpolssad22dxsxs#live.nl"
"street" => "Dijkgraaf 2"
"house_number" => "asdasd"
"province" => "Drenthe"
"country" => "asdasdsad"
"date_of_birth" => Carbon\Carbon #1576281600 {#385 ▶}
"postcode" => "3155GA"
"updated_at" => "2019-12-14 00:10:03"
"created_at" => "2019-12-14 00:10:03"
"id" => 8
]
#original: array:13 [▶]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [▶]
}
What am i not seeing?
Thanks!
Edit:
I am an idiot.
There was an extra space after user_id:
'user_id ' => $this->user->id
Solved.
You did find the catch!
But since you want me to write the answer, I gladly do it.
You had an extra space on your key 'user_id ' => $this->user->id

laravel Property [address] does not exist on this collection instance

I have a business table which is linked using eloquent with table addresses, location and gallery.
Output looks like this:
Collection {#266 ▼
#items: array:1 [▼
0 => Business {#260 ▼
#table: "businesses"
+timestamps: true
#connection: "mysql"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:14 [▶]
#original: array:14 [▶]
#casts: []
#dates: []
#dateFormat: null
#appends: []
#events: []
#observables: []
#relations: array:3 [▼
"addresses" => Collection {#261 ▼
#items: array:1 [▼
0 => Address {#263 ▼
#table: "addresses"
+timestamps: true
#connection: "mysql"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:9 [▼
"id" => 10
"firstline_address" => "96"
"secondline_address" => "Cambridge Street"
"town" => "p.wojtas26#gmail.com"
"city" => "p.wojtas26#gmail.com"
"postcode" => "SK15 1AU"
"telephone" => "7815522481"
"created_at" => "2017-06-26 08:05:32"
"updated_at" => "2017-06-26 08:05:32"
]
#original: array:11 [▶]
#casts: []
#dates: []
#dateFormat: null
#appends: []
#events: []
#observables: []
#relations: array:1 [▼
"pivot" => Pivot {#262 ▶}
]
#touches: []
#hidden: []
#visible: []
#fillable: []
#guarded: array:1 [▶]
}
]
}
"location" => Location {#279 ▶}
"gallery" => null
]
However the problem is that is says:
Property [addresses] does not exist on this collection instance. (View: C:\xampp\htdocs\laravel\resources\views\displayBusiness.blade.php)
here's my view:
#foreach($business->addresses as $address)
<p>{{$address->firstline_address}}</p>
<p>{{$address->secondline_address}}</p>
<p>{{$address->town}}</p>
<p>{{$address->city}}</p>
<p>{{$address->postcode}}</p>
<p>{{$address->telephone}}</p>
#endforeach
</div>
Model:
class Business extends Model
{
protected $table = 'businesses';
public $timestamps = true;
use Searchable;
public function addresses()
{
return $this->belongsToMany('App\Address', 'business_address', 'business_id', 'address_id');
}
public function gallery()
{
return $this->hasOne('App\Gallery', 'business_id');
}
public function film()
{
return $this->hasOne('App\Film', 'business_id');
}
public function location()
{
return $this->hasOne('App\Location', 'business_id');
}
public function user()
{
return $this->hasMany('App\User', 'user_business', 'business_id', 'user_id');
}
Another problem is that sometimes a field is empty so let's say sometimes $address->city = null how would I tell to ignore that field and carry on?
I can do #if($address->city == NULL) but I don't want to do it for each one as I cannot predict what will be empty.
//edit
Controller:
public function displayBusiness($id) {
$business = Business::where('id', $id)
->with('addresses')
->with('location')
->with('gallery')
->get();
//dd($business);
/*
$instagram = $business->instagram_business;
$twitter = $business->twitter_business;
$instagramItems=[];
$twitterItems=[];
if(!empty ($instagram)){
$client = new \GuzzleHttp\Client();
$url = sprintf('https://www.instagram.com/'.$instagram.'/media');
$response = $client->get($url);
$instagramItems = json_decode((string) $response->getBody(), true)['items'];
$twitterItems = Twitter::getUserTimeline(['screen_name' => $twitter, 'count' => 10, 'format' => 'array']);
*/
//$session = session()->put('key', $id);
//$gallery = Gallery::where('business_id', $id)->get();
//$location = Location::where('business_id', $id)->get();
//$review = Review::where('business_id', $id)->get();
return view('business.displayBusiness', compact('business', 'address', 'gallery', 'location', 'review', 'instagramItems', 'twitterItems'));
/*}
//edit2
It now says
Trying to get property of non-object (View: C:\xampp\htdocs\laravel\resources\views\business\displayBusiness.blade.php)
Which is:
#foreach ($business->location as $marker)
<script>
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 19,
center: {lat: {{$marker->latitude}}, lng: {{$marker->longitude}}}
});
It looks like you need to change
$business = Business::where('id', $id)
->with('addresses')
->with('location')
->with('gallery')
->get();
to
$business = Business::where('id', $id)
->with('addresses')
->with('location')
->with('gallery')
->first();
Your problem is that your query is returning a Collection rather than a single instance of Business, this is because your query is searching for multiple businesses and will generate a Collection of any businesses it finds, even if there is just one.
Better to use has()
$business = Business::where('id', $id)
->has('addresses')
->has('location')
->has('gallery')
->get();
Querying Relationship Existence
https://laravel.com/docs/5.7/eloquent-relationships#querying-relations

Resources