Laravel - Json object showing empty ParameterBag - laravel

I have this JSON data sent in HTTP body in a post request.
{
"id" : 238,
"title": "Its a title",
"description": "Its a description",
"target_price": 3000,
"date_of_availability": "16-02-2023",
"condition": "abc",
"latitude": "-31.953030",
"longitude": "115.853600",
"attributes": {
"list" : [
{
"title" : "Color",
"value" : "Red"
},
{
"title" : "Frame",
"value" : "Metal Frame"
}
]
}
}
I want attributes to be stored in json data type field. I can get value of all other fields in my controller but when i dd($request->attributes); it show me empty Parameter Bag.
How can i get $request->attributes and store it in my json data type field of mysql.
This is my migration
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->id('post_id')->generatedAs();
$table->string('title');
$table->text('description');
$table->integer('target_price')->nullable();
$table->date('date_of_availability')->nullable();
$table->string('condition')->nullable();
$table->decimal('latitude', 11, 8);
$table->decimal('longitude', 11, 8);
$table->json('attributes')->nullable();
$table->timestamps();
});
}
Here i am saving
$post = new Post();
$post->title = $data->title;
$post->description = $data->description;
$post->target_price = $data->target_price;
$post->date_of_availability = date("Y-m-d", strtotime($data->date_of_availability));;
$post->condition = $data->condition;
$post->latitude = $data->latitude;
$post->longitude = $data->longitude;
$post->attributes = $data->attributes;
$post->save();
This is the error i am getting for line $post->attributes = $data->attributes;
"message": "Object of class Symfony\Component\HttpFoundation\ParameterBag could not be converted to string",

The Laravel request object uses magic methods to access the parameters that are passed in the body of the request. This only works if the Request class doesn't already have a property of the same name.
The Illuminate\Http\Request class extends the Symfony\Component\HttpFoundation\Request class which has an explicit property called $attributes:
/**
* Custom parameters.
*
* #var ParameterBag
*/
public $attributes;
If you want to explicitly get a property from the request body without using the magic method you can use the input or json methods:
$post->attributes = $request->json('attributes');

Related

Model hide mutators and nested fields

Here is my JSON return
{
"product": {
"id": 1,
"name": "Glory Cookware",
"barcode": "1234567891234",
"local_code_id": 1,
"category_id": 1,
"description": null
},
"calculations": {
"product_quantity_in_warehouses": 1580,
"avgSellingPriceBeforeTax": 901.7085714285713,
"avgSellingPriceAfterTax": 1027.9477714285713,
"creditPriceInWarehousesBeforeTax": 1530828,
"creditPriceInWarehousesAfterTax": 1745143.92
}
}
What I am trying to do:
In the Product.php model I am trying to hide calculations.creditPriceInWarehousesBeforeTax.
What I have tried:
I have tried to use toArray() method in the Product.php mode.
public function toArray()
{
$hidden = ['calculations.creditPriceInWarehousesBeforeTax'];
// Also tried ['creditPriceInWarehousesBeforeTax']
$this -> hidden = $hidden;
return parent::toArray();
}
Expected behavior VS what happened
The JSON result should not return the calculations.creditPriceInWarehousesBeforeTax but what happened is that it return with the JSON.
NOTE
calculations are a mutator that I have created to append it as an attribute.

Join pivot has one array

I guys, i have 2 relations tables, and when listing all my messages, is shown the pivot columns relation, but i need to show the data has one array, is there a method in eloquent cant make this happen?
I searched and i no that is possible manipulate with collection methods but i wonder if there is another way.
My Model query is:
public function messages()
{
return $this->belongsToMany(Message::class,'message_users')->withPivot('is_read','sent_at');
}
This is how it is:
{
"data": [
{
"id": 4,
"title": "test",
"body": "<p>test</p>",
"pivot": {
"user_id": 1,
"message_id": 4,
"is_read": 0,
"sent_at": "2019-06-05 12:59:11"
}
}
]
}
This is how i want:
{
"data": [
{
"id": 4,
"title": "test",
"body": "<p>test</p>",
"user_id": 1,
"message_id": 4,
"is_read": 0,
"sent_at": "2019-06-05 12:59:11"
}
]
}
You can do next: in User model write toArray() method as
/**
* Convert the model instance to an array.
*
* #return array
*/
public function toArray(): array
{
$attributes = $this->attributesToArray();
$attributes = array_merge($attributes, $this->relationsToArray());
// Detect if there is a pivot value and return that as the default value
if (isset($attributes['pivot'] && isset($attributes['pivot']['user_id']))) {
$attributes['user_id'] = $attributes['pivot']['user_id'];
$attributes['message_id'] = $attributes['pivot']['message_id'];
$attributes['is_read'] = $attributes['pivot']['is_read'];
$attributes['sent_at'] = $attributes['pivot']['sent_at'];
unset($attributes['pivot']);
}
return $attributes;
}

How to Mock a Guzzle Request for PHPUnit

I have a class like this:
class CategoryClient
{
private $categories;
/**
* Constructor
* Retrieves JSON File
*/
public function __construct(Client $client)
{
$response = $client->request('GET', config('services.url'));
$this->categories = collect(json_decode($response->getBody(), true));
}
}
How would I mock the json response for testing purposes in PHPUnit? and set the $this->categories variable?
You can use the Mock Handler of the Guzzle testing strategy and instantiate your Client class. As example:
$mock = new MockHandler([
new Response(200, [], '{
"categories": [
{ "id" : 1,
"name": "category name 1"},
{ "id" : 2,
"name": "category name 3"},
]
}');
$handler = HandlerStack::create($mock);
$guzzleClient= new Client(['handler' => $handler]);
$categoryClient = new CategoryClient($guzzleClient);
Hope this help

Laravel datatable nested row-details on nested relationships

I am trying to view laravel datatable with nested row details on nested relationships. Here are the details of what I have done
Database relationships
I want the datatable to view all products on page load, then first level of row detail will show all components of a product. Second level of row detail will show all sub-components from a component.
This is the current result of my datatable view
As shown in the illustration, the datatable fails to show the rawmaterial name of a sub-component.
Here are my Eloquent models and relationships.
Product Model
protected $table = 'products';
public function components() {
return $this->hasMany('App\Component', 'product_id', 'id');
}
Component Model
protected $table = 'components';
public function comp_subcomps() {
/*The syntax ->with('subcomponents') seems WORKING fine in resulting
the second level row detail ( viewing the subcomponents of a component )*/
return $this->hasMany('App\CompToSubComp', 'component_id', 'id')->with('subcomponents');
}
CompToSubComp Model
protected $table = 'comp_subcomp';
public function subcomponents() {
/* This syntax ->with('rawmaterials') seems NOT WORKING to
get the material name in the second level row detail */
return $this->belongsTo('App\SubComponent', 'subcomponent_id', 'id')->with('rawmaterials');
}
SubComponent Model
protected $table = 'subcomponents';
public function rawmaterials() {
return $this->belongsTo('App\Rawmaterial', 'rawmaterial_id', 'id');
}
CONTROLLER
/* On page load */
public function viewTable() {
$products = Product::select();
return Datatables::of($products)
->addColumn('details_url', function($product) {
return url('/product/getdetaildata/' . $product->id);
})->make(true);
}
/* First level row detail ( showing components of a product ) */
public function getDetailsData($id)
{
$components = Product::find($id)->components();
return Datatables::of($components)
->addColumn('moredetails_url', function($component) {
return url('/product/getmoredetail/' . $component->id);
})->make(true);
}
/* Second level row detail ( showing sub-components of a component ) */
public function getMoreDetailsData($id) {
$compsubcomp = Component::find($id)->comp_subcomps();
return Datatables::of($compsubcomp )->make(true);
}
JS DATATABLE
/* On load: Its working */
var dt = $('#example').DataTable({
...
"columns": [
{ "data": "id", "name": "id" },
{ "data": "name", "name": "name"}
]
});
/* First level row detail: Its working */
var tabComponent = $('#' + tableId).DataTable({
...
"columns": [
{ "data": "id", "name": "id" },
{ "data": "name", "name": "name" }
]
});
/* Second level: This PROBLEM exists where RAWMATERIAL NAME is not showing */
$('#' + tableId).DataTable({
...
"columns": [
{ "data": "id", "name": "subcomponents.id" },
{ "data": "name", "name": "subcomponents.name" },
{ "data": "rawmaterial_id", "name": "subcomponents.rawmaterial_id" },
{ "data": "subcomponents.rawmaterials.name", "name": "subcomponents.rawmaterials.name" }
]
});
How to correctly view the relationship between 'rawmaterials' and 'subcomponents' inside my datatable?
Any help to identify my errors would be appreciated. Thanks in advance.

Laravel 4.1 remove pivot attributes from response

I am using laravel 4.1 to build an api. I have pivot a table which is working fine. But the response comes with pivot attributes which i don't want. as you will see in my example i have to two tables name: trips and users. I don't want to see pivot table attributes in my response. Here is the example:
[
{
"id": 140,
"name_first": "hasan",
"name_last": "hasibul",
"profile_image": "/assets/images/default-profile-img.png",
"created_at": "2013-09-18 08:19:50",
"last_login": "2013-12-26 11:28:44",
"status": "active",
"last_update": "2013-10-15 13:40:47",
"google_refresh_token": null,
"is_admin": 1,
"updated_at": null,
"pivot": {
"trip_id": 200,
"user_id": 140
}
}
This is my User Model:
public function trips(){
return $this->belongsToMany('Trip');
}
This is my trip model:
public function users(){
return $this->belongsToMany('User');
}
This is my controller:
public function index($tripId)
{
$userCollection = Trip::find($tripId)->users;
return $userCollection;
}
This is my route:
//get all the users belongs to the trip
Route::get('trips/{tripId}/users', array(
'as' => 'trips/users/index',
'uses' => 'TripUserController#index'
));
is there any way i can remove pivot attributes using laravel or i have to use php ?
Use the $hidden property of the model, you can add attributes or relations to it and the pivot is basicly acts as a relation.
class Foo extends Eloquent
{
protected $hidden = array('pivot');
public function bars()
{
return $this->belongsToMany('Bar');
}
}
If you want to remove just any one column from the response, then you can try something like this:
In you Model:
public function toArray()
{
$attributes = $this->attributesToArray();
$attributes = array_merge($attributes, $this->relationsToArray());
unset($attributes['pivot']['user_id']);
return $attributes;
}
This way you will get only attribute required.
You can add it to your "hidden" array. At Model page
protected $hidden = [
'pivot'
];
As mentioned above you can remove the pivot attribute from the response, by adding the following to the related model.
protected $hidden = [
'pivot'
];
Moreover, in case you want to select specific fields from the pivot to be displayed in the related user object you can add this to your controller using Laravel 5.8. This works also when you hide the pivot information with the above code snippet.
public function index(Trip $trip)
{
return $trip->users()->select(['trip_id'])->paginate();
}
and you will receive something objects where the trip_id is added to the user object.
{
"data": [
{
"id": 140,
"trip_id": 200,
"name_first": "hasan",
"name_last": "hasibul",
"profile_image": "/assets/images/default-profile-img.png",
"created_at": "2013-09-18 08:19:50",
"last_login": "2013-12-26 11:28:44",
"status": "active",
"last_update": "2013-10-15 13:40:47",
"google_refresh_token": null,
"is_admin": 1,
"updated_at": null,
"pivot": {
"trip_id": 200,
"user_id": 140
}
}
]
}

Resources