Laravel eloquent does not update JSON column : Array to string conversion - php

I want to update a JSON column in my database but I get this error :
Array to string conversion
I have declared the column name as array in the model :
protected $casts = [
'destinations' => 'array'
];
this is the code that I use :
$data[] = [
'from' => $fromArray,
'to' => $toArray
];
Flight::where('id', $id)->update(['destinations' => $data]);
What should I do ?

You can access your json keys using the arrow so you can update your column like so:
Flight::where('id', $id)->update([
'destinations->from' => $data['from'],
'destinations->to' => $data['to']
]);
As #fubar mentioned you have to have mysql
5.7 in order to have my solution to work.
check the docs

This code did the work for me.
$user = User::where('id', $request->user_id)
->first();
$array_data = ["json_key3"=>"value"];
$user->forceFill([
'db_column->json_key1->json_key2' => $array_data
])->save();

According to this conversation on Github : Make json attributes fillable if Model field is fillable Taylor Otwell recommande the use of save method :
$model->options = ['foo' => 'bar'];
$model->save();
So in you case you can do it like this :
$flight = Flight::find($id);
$flight->destinations = $data;
$flight->save();

You're getting that error because you're trying to update your model using the Query Builder, which basically just creates raw SQL queries. It isn't aware of any data casting, etc defined within your model. You therefore have three choices:
1) Find your model, and run the update on your model instance.
$flight = Flight::findOrFail($id);
$flight->update(['destinations' => $data]);
2) Convert the data to a string before updating.
$data = json_encode($data);
Flight::where('id', $id)->update(['destinations' => $data]);
3) Use a database that supports JSON column queries, per #AmrAly's suggestion. Beware of this option, as not all databases support JSON columns.

Related

How to Use WhereIn Query in Laravel 8

Controller
public function detail(Peserta $peserta)
{
// get konfirmasi_id
$konfirmasi = KonfirmasiPembayaran::where('email',$peserta->email)->select('id')->get();
$payments = BankSettlement::whereIn('konfirmasi_id',array($konfirmasi->id))->get();
// dd($payments);
$tagihan = Tagihan::where([['peserta_id', $peserta->id],['type', 3]])->first();
return view('data.peserta.detail', ['data' => $peserta, 'payments' => $payments,'tagihan' => $tagihan]);
}
I want to display data from BankSettlement based on konfirmasi_id. Here I try to use WhereIn Query like this, but still error "Property [id] does not exist on this collection instance.".
$konfirmasi has data like the image above.
What is the correct way to display data from BankSettlement based on konfirmasi_id ? Thankyou
Try this changes:
$konfirmasi = KonfirmasiPembayaran::where('email',$peserta->email)->pluck('id')->toArray();
$payments = BankSettlement::whereIn('konfirmasi_id',$konfirmasi)->get();
This is the wrong way to change a collection to array.
$payments=BankSettlement::whereIn('konfirmasi_id',array($konfirmasi->id))->get();
You should do this
public function detail(Peserta $peserta)
{
// get konfirmasi_id
$konfirmasi = KonfirmasiPembayaran::where('email',$peserta->email)
->select('id')
->get()
->pluck('id')
->toArray(); //This will return an array of ids
$payments = BankSettlement::whereIn('konfirmasi_id',$konfirmasi)->get();
// dd($payments);
$tagihan = Tagihan::where([['peserta_id', $peserta->id],['type', 3]])->first();
return view('data.peserta.detail', ['data' => $peserta, 'payments' => $payments,'tagihan' => $tagihan]);
}
Edit:
Read Laravel Collections|Pluck
If you do not have to reuse the result of $konfirmasi then it would be better to use subquery. Writing a subquery is optimized way. if you write two different query then there will be two seperate database connection request.
Laravel subquery
$konfirmasi = KonfirmasiPembayaran::where('email',$peserta->email)->select('id');
$payments = BankSettlement::whereIn('konfirmasi_id', $konfirmasi )->get();

How to optimize multiple value query from database in laravel

I am new to laravel and using simple command to query from database.
I am trying to get multiple value from database with same id.
$id = 'P01';
//Get value from database
$fruitname = DB::table('fruits')->where('id', $id)->value('fruitname');
$fruitcolour = DB::table('fruits')->where('id', $id)->value('fruitcolour');
$fruitshape = DB::table('fruits')->where('id', $id)->value('fruitshape');
$updatedat = DB::table('fruits')->where('id', $id)->value('updated_at');
$data = array(
'fruitname' => $fruitname,
'fruitcolour' => $fruitcolour,
'fruitshape' => $fruitshape,
'updated_at' => $updatedat
);
As result, $data can store the value.
But i found out that it takes time to complete the process.
Is there any ways i can optimize the process?
I'm not sure why you're making it more hard than it is, but you can just simply use eloquent in this case:
Provided you already have created the necessary model and adding it in your controller:
use App\Fruits;
Just simply use it in the find method:
public function someMethodName()
{
$id = 'P01';
$fruit = Fruits::find($id);
echo $fruit->fruitname; // and others
}
$fruit = DB::table('fruits')->where('id', $id)->first();
$data = array(
'fruitname' => $fruit->fruitname,
'fruitcolour' => $fruit->fruitcolour,
'fruitshape' => $fruit->fruitshape,
'updated_at' => $fruit->updatedat
);
Or if you have a view, you could just do
$fruit = DB::table('fruits')->where('id', $id)->first();
return view('yourview', compact('fruit'));
And in the view, you can access each of the values like so:
{{ $fruit->fruitname }}
{{ $fruit->fruitcolor }}
In your controller add function
public function function_name(Fruit $fruit)
{
return view('your_view_name', compact('fruit'));
}
In web file set your route as
Route::get('/fruit/{fruit}','YourControllername#methodName')->name('show');
At the time of setting route
Show
in View file get data as
{{ $fruit->fruitname }}
{{ $fruit->fruitcolor }}
To make it with a single query with QueryBuilder since QueryBuilder can have better performance than Eloquent:
DB::table('fruits')->where('id', $id)
->select(['fruitname', 'fruitcolour', 'fruitshape', 'updated_at'])
->first();
This returns a associative array with the selected column names.

Laravel boolean returns "1"/"0" instead of true/false in query

I have a query that returns a boolean field (by the way, I'm on an SQL Server) on my REST API developed with Laravel and a few days ago it was returning the value as true/false, but now it returns that boolean value as String: "1"/"0".
Any idea on what could it be?
I tried using casting on my Model like this:
protected $casts = [
'status' => 'boolean',
];
This is my query:
return DB::table('dbo.visits as V')
->leftJoin('dbo.reports AS R', 'R.id_visit', '=', 'V.id')
->select('R.id','R.status'); // status is the boolean
Thanks in advance.
When you're defining the following:
protected $casts = [
'status' => 'boolean',
];
You're defining it on the model. However, when you initiate your query using DB::table(), you're not using the model, so the binding doesn't actually apply. Initiate your query using your model:
return Visit::leftJoin('dbo.reports AS R', 'R.id_visit', '=', 'dbo.visits.id')
->select('R.id','R.status'); // status is the boolean
Note: Had to adjust query to dbo.visits.id from V.id due to aliasing not being available at that point.
Defining casts is working when you are using Eloquent models. In code you provided you use query builder and then Eloquent models are not used at all, so no casts are done.
You could use Eloquent: API Resources
/*Controller*/
$sel_visit= Visit::leftJoin('dbo.reports AS R', 'R.id_visit', '=', 'dbo.visits.id')->select('R.id','R.status')->get(); // status is the boolean
VisitResource::collection($sel_visit);
Then using a API Resources
public function toArray($request)
{
if($this->status==1) { $status=true;} else {$status=false;}
return [
'id' => $this->id,
'status' => $status
];
}
What you would like to do is add this function to your model. Every time you use your model to retrieve data, this function matching the attribute name will be called to convert your raw data from the database to your desired format.
public function getStatusAttribute($value)
{
return $value ? 'Yes' : 'No';
}

Is there a way to retrieve single row from database as key value only in laravel

can i retrieve single row from database like this in Laravel
["name"=>"jhon",
"age"=>"18"
]
Use the first() method:
User::where('name', 'John Smith')->first();
Or the find() method:
User::find($id);
It will return an object. If you need an array, use the toArray() method to convert an object to an array:
User::find($id)->toArray();
You can also use Eloquent Collection methods to transform it however you want.
$people = User::where('name', 'John Smith')->get()->map(function ($person) {
return [
'id' => $person->id,
'name' => $person->name
];
});
Use first() method along with id because id is unique key for every row
User::whereId($id)->first();

How can I use array_where in Laravel?

I have an array ($payments) returned by an Eloquent query with the following JSON encoded output:
[{"id":1, "user_id":"34","amount":"1000","status":"0","created_at":"2016-08-18 14:24:59","updated_at":"2016-08-18 14:24:59"},
{"id":3, "user_id":"33","amount":"300","status":"1","created_at":"2016-08-18 14:31:04","updated_at":"2016-08-18 14:33:20"},
{"id":4, "user_id":"33","amount":"1000","status":"0","created_at":"2016-08-18 14:31:27","updated_at":"2016-08-18 14:31:27"},
{"id":5, "user_id":"34","amount":"400","status":"1","created_at":"2016-08-18 14:42:02","updated_at":"2016-08-18 14:42:02"}]
I want to use the array_where() method in Laravel and filter $payments according this condition : status == 1, could anyone tell me how to do that?
If this is the result of an Eloquent query, it's not an array, it's a Collection. From the documentation:
All multi-result sets returned by Eloquent are an instance of the Illuminate\Database\Eloquent\Collection object
You can use the Collection's filter method, which takes a closure, and return the condition you want ('status' == 1) in the closure.
$filtered = $your_query_result->filter(function($value, $key) {
return $value->status == 1;
});
You may be surprised to find out that there is a php function called array_filter that does exactly that. Here it is in action
$array = [ ['id' => 1, 'status' => 0], ['id' => 2, 'status' => 1], ['id' => 3, 'status' => 0] ];
$array = array_filter($array, function ($item) {
return $item['status'] == 1;
});
Eloquents result cannot be json by default unless You call toJson() method.
Why not just add to Your database query condition?
Example:
$payments = Payment::where('status', '=', 1)->get(); // Payment is model
return response()->json($payments);
p.s. it's not recommended to get a big list of json data from db, parse it and filter it.
make better use of database and don't make Your life hard (:

Categories