Update data to mongoBD failed at updatedAt in laravel - laravel

I am doing update function to mongoDB in laravel. And I get some errors like this.
For example I have 1 table in mongoBD which is products:
{
"_id" : ObjectId("5e3a80d6d50c7d6f1a15b582"),
"status" : 1,
"name" : "Product 1",
"slug" : "product-1",
"description": 'test product 1',
"createdAt" : 1658905822,
"updatedAt" : 1659407411
}
In controller :
use App\Models\Product;
public function update(Request $request)
{
$reqProduct = $request->data;
// dd($reqProduct) result :
// array(65) {
// ["_id"]=>
// string(24) "5e3a80d6d50c7d6f1a15b582"
// ["status"]=>
// int(1) 1
// ["name"]=>
// string(11) "Product 1"
// ["slug"]=>
// string(11) "product-1"
// ["description"]=>
// string(5) "sss"
// ["createdAt"]=>
// string(10) "1658905822"
// ["updatedAt"]=>
// string(10) "1678537691"
// }
$product = Product::where('_id', '=', $reqProduct['_id'])->first();
$product->update($reqProduct);
}
So the update was successful. But my database sometimes come up with a case, updatedAt when saving in int type, but sometimes it is stored in date type (ISODate).
Example :
{
"_id" : ObjectId("5e3a80d6d50c7d6f1a15b582"),
"status" : 1,
"name" : "Product 1",
"slug" : "product-1",
"description": 'test product 1',
"createdAt" : 1658905822,
"updatedAt" : ISODate("2013-10-01T00:00:00.000Z")
}
And when I click update the error message: Object of class Carbon\\Carbon could not be converted to int.
I tried :
$product = Product::where('_id', '=', $reqProduct['_id'])->first();
$product->unset('updatedAt', $product->updatedAt);
$product->update($reqProduct);
But can't. Everyone please give me the solution so I can fix it, Thanks.

Simply convert it to datetime string before updating.
$updated_at = Carbon::createFromTimestamp(1678537691)->toDateTimeString();
["updatedAt"] => $updated_at,

Related

MongoDB: How to update an item in an array using laravel

In mongoDB, I have a table product :
{
"_id" : ObjectId("61e93a99667ad949974948fb"),
"listProduct" : [
{
"_id" : "61e93aceebadb38d243fa321",
"name" : "Product 1",
"order" : 1,
"childProduct" : [
{
"_id" : "61e93aceebadb38d243fa322",
"name" : "Samsung",
"description" : "New Samsung",
"productOn" : 1676351448
},
{
"_id" : "61ee808140451a00b4eee93c",
"name" : "Iphone",
"description" : "New Iphone",
"productOn" : 1676605213
},
],
}
],
}
In Models:
<?php
namespace App\Models\Backend\Mongo;
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
class Product extends Eloquent
{
protected $connection = 'mongodb';
protected $collection = 'product';
protected $guarded = ['_id'];
protected $dateFormat = 'U';
protected $fillable = [
'listProduct',
];
}
And in the laravel controller, I update the productOn field for it:
use App\Repositories\MongoDB\ProductRepository;
protected $productRepository;
public function __construct(
ProductRepository $productRepository,
) {
$this->productRepository = $productRepository;
}
public function updateProductOn()
{
$product = $this->productRepository->getModel()::where('_id', '=', '61e93a99667ad949974948fb')->first();
if ($product) {
$product->listProduct[0]['childProduct'][0]['productOn'] = strtotime('now');
$product->save();
}
}
And when I run that function, and save it, it gets the following error:
"message": "Indirect modification of overloaded property App\\Models\\Mongo\\Product::$listProduct has no effect",
"exception": "ErrorException",
I have researched and learned how to product->push and I have followed it, but it still doesn't work.And I also know push to save an array.
$product->push("listProduct[0].childProduct[0].productOn", strtotime('now'));
or
$product->push("listProduct[0]['childProduct'][0]['productOn']", strtotime('now'));
Is there any way to update productOn, please give me any suggestions. Thanks.

Laravel. How to insert nested data into database

It's very easy to insert a register when I have a JSON to insert an Article like this:
--JSON to insert--
{
"title" : "a title",
"content" : "some content",
"user_id" : 3
}
To put it short, I create the route aiming to the store method of the controller and go for something simple like:
--ArticleController--
public function store(Request $request)
{
$article = Article::create($request->all());
return response()->json($article, 201);
}
But, what is the correct way to insert the data to store if I have something JSON:API complying like this?:
{
"data":
{
"type": "articles",
"attributes": {
"title": "a title",
"content" : "some content",
"user_id" : 3
}
}
}
What is the correct approach?
I can't believe it was so easy,
I just changed this:
$article = Article::create($request->all());
return response()->json($article, 201);
for this:
$article = Article::create($request->data['attributes']);
return response()->json($article, 201);
And that's it

Validating json data for unique fields in laravel

I have a json request with household_data. I have tried to use validator on family_no which is a unique field. the json I'm working on is :
[
{
"BasicInfo": {
"ward": "12",
"tole_name": "Sahayogi Nagar",
"house_no": "21",
"family_no": "420",
"district": "Lalitpur",
},
"Family": [
{
"caste": "bahun",
"religion": "hindu",
}
]
}]
But the validator fails always, even if the family_no is unique or not and returns:
{
"family_no": [
"The family no field is required."
]
}
here is my controller code:
$items = json_decode($request->household_data);
// return json_decode($request->household_data);
if($request->household_data){
$validator = Validator::make($items, [
'family_no' => 'required|unique:households|max:255',
]);
if ($validator->fails()) {
return response()->json($validator->errors(), 404);
}
else{
foreach($items as $key=>$item){
$householdId = $this->saveHousehold($item);
return $householdId;
}
}
}
Anyone could please help me validate the unique field family_no?
checkout array validator of laravel on the doc webiste https://laravel.com/docs/7.x/validation#validating-arrays. But for your validation you have to write it like this :
{
"BasicInfo.family_no": [
"The family no field is required."
]
}

LARAVEL framework and Eloquent ORM model

{ "_id" : 8751, "title" : "The Banquet", "author" : "Dante", "copies" : 2 }
{ "_id" : 8752, "title" : "Divine Comedy", "author" : "Dante", "copies" : 1 }
{ "_id" : 8645, "title" : "Eclogues", "author" : "Dante", "copies" : 2 }
{ "_id" : 7000, "title" : "The Odyssey", "author" : "Homer", "copies" : 10 }
{ "_id" : 7020, "title" : "Iliad", "author" : "Homer", "copies" : 10 }
Above is a 'books' table
Using LARAVEL framework and Eloquent ORM model, how to return the following result:
{ "author" : "Homer", "books" : [ "The Odyssey", "Iliad" ] }
{ "author" : "Dante", "books" : [ "The Banquet", "Divine Comedy", "Eclogues" ] }
I am learning Laravel.
You could use GROUP_CONCAT.
Book::groupBy('author')
->select(DB::raw('GROUP_CONCAT(title) as books'), 'author')
->get()
->map(function ($author) {
$author->books = preg_split('/,/', $author->books);
return $author;
});
This will get you:
{ "author" : "Homer", "books" : [ "The Odyssey", "Iliad" ] }
{ "author" : "Dante", "books" : [ "The Banquet", "Divine Comedy", "Eclogues" ] }
If the table structure is within your control, then the better solution would be to place the data into two tables books and authors, to avoid data duplication as is the case now with a single table.
Then define two Eloquent Models and setup a one-to-many relationship. As in one author can have many books written.
So the Book model might look like this:
class Book extends Model
{
public function author()
{
return $this->belongsTo(Author::class);
}
}
And the Author model might look like this:
class Author extends Model
{
public function books()
{
return $this->hasMany(Book::class);
}
}
Now you can use the relationship, eager loading and a little collection processing to fetch the data in your preferred format:
$authors = Author::with('books')->get()->map(function ($author) {
return [
'author' => $author->name,
'books' => $author->books->pluck('title')
];
});
You might also want to read up on Database Normalization, and in your case more specifically The 1st Normal Form.

Laravel API : how to get only some fields and sort the response

I would like to know if I do the things correctly.
Let's say I have a table "countries". To get only some fields of this table, in a certain order, I have this url :
/countries?fields=id,country_name&desc=country_name
And the result is clear:
[
{
"id": "SP",
"country_name": "Spain"
},
{
"id": "IT",
"country_name": "Italy"
},
{
"id": "FR",
"country_name": "France"
},
{
"id": "CN",
"country_name": "China"
} ]
To do that I have this route :
Route::get('/countries', 'CountryController#index');
And the method index is :
public function index(Request $request)
{
$query = Country::query();
if ($request->has('fields')){
$fields = explode(',', $request->input('fields') );
foreach ($fields as $field) {
$query->addSelect($field);
}
}
if ($request->has('sort')){
$query->orderBy($request->input('sort'));
}
if ($request->has('desc')){
$query->orderBy($request->input('desc'), 'desc');
}
$countries = $query->get();
return response()->json($countries, 200);
}
It works fine.
My question is am I doing the things correctly ? Is there any other methods ?
To prevent unknown column exception try this:
import Schema class use Illuminate\Support\Facades\Schema;
add this:
$table = "countries";
if ($request->has('fields')){
$fields = explode(',', $request->input('fields') );
foreach ($fields as $field) {
if(!Schema::hasColumn($table,$field)){
return response("Unknown field", 422);
}
$query->addSelect($field);
}
}
What you are doing to me has no vulnerability in it and is very optimized too.
You can try using this:
$countries = $query->pluck('id', 'country_name');
Please check and let me know.

Resources