Laravel eloquent DB seeder and array casting - laravel-5

can someone help me to understand how can I use attribute casting if I am inserting data with DB seeder (and retrieve it)
this is part of the seeder
DB::table('events')->insert([
[
'title' => 'prizes',
'description' => serialize([
"text" => "General description..."
]),
'language' => 'en',
'time_start' => null,
'time_end' => null,
'lat' => null,
'lng' => null,
]
]);
this way I do have serialized data in my database, but when I do
$events = Event::with('user')->where('child','=',null)->get();
I get description is null
(don't worry about user its null by default)
this is my Event model
class Event extends Model
{
protected $table = 'events';
//
public function user()
{
return $this->hasOne('App\User','id');
}
protected $casts = [
'description' => 'array',
];
}
what am I missing here?

According to the doc, Eloquent array casting serializes array into JSON:
The array cast type is particularly useful when working with columns that are stored as serialized JSON
So you should insert it like this:
DB::table('events')->insert([[
'title' => 'prizes',
'description' => json_encode(["text" => "General description..."]),
'language' => 'en',
'time_start' => null,
'time_end' => null,
'lat' => null,
'lng' => null,
]]);
As a side note, serialize belongs to PHP core and it does not produce JSON.

Related

Laravel cast model values when using Resource

When returning a model using resource created_at and updated_at casting is working fine,
but when i modify the toArray() function the casting is not working !
in my model :
protected $casts = [
'created_at' => 'datetime:Y-m-d:h',
'updated_at' => 'datetime:Y-m-d:h',
];
in resource :
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'value' => $this->value,
'box' => new BoxResource($this->box),
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
in controller :
public function index(Request $request)
{
return CurrencyResource::collection(
Currency::where("user_id", "=", $request->user()->id)
->paginate($per_page)
);
}
How to make the casting work ?
By it not working, you mean the timestamps revert to carbon instances? You could just use the format method then.
'created_at' => $this->created_at->format('Y-m-d:h'),
'updated_at' => $this->updated_at->format('Y-m-d:h'),

How to insert all json file data in database?

I have JSON file and have data in it. I want to import all data in the database through DB seeders. I am getting an error Trying to get property name of non-object. I have multiple data how I can insert in the database?
public function run()
{
$json = File::get("public/kmz/WASASubdivisions.geojson");
$data = json_decode($json);
// dd($data);
foreach ($data as $obj){
Regions::create(array(
'name' => $obj[0]->Name,
'description' => $obj[0]->description,
'altitudeMode' => $obj[0]->altitudeMode,
'Town' => $obj[0]->Town,
'AC' => $obj[0]->AC,
'No_of_TW' => $obj[0]->No_of_TW,
'No' => $obj[0]->No,
'DC'=> $obj[0]->DC,
'HH_2017' => $obj[0]->HH_2017,
'FID' => $obj[0]->FID,
'Area_ha' => $obj[0]->Area_ha,
'Field_1' => $obj[0]->Field_1,
'Pop_Dens' => $obj[0]->Pop_Dens,
'Id' => $obj[0]->Id,
'Pop_2017' => $obj[0]->Pop_2017,
'Area_Sq'=> $obj[0]->Area_Sq,
));
}
}
Sample Json Format
31 => {#837
+"type": "Feature"
+"properties": {#838
+"Name": "Gujjar Pura"
+"description": null
+"altitudeMode": "clampToGround"
+"Town": "Shalimar Town"
+"AC": "31"
+"No_of_TW": "11"
+"No": "13"
+"DC": "38"
+"HH_2017": "30478"
+"FID": "31"
+"Area_ha": "648.327"
+"Field_1": "Gujjar Pura"
+"Pop_Dens": "54063.141167"
+"Id": "0"
+"Pop_2017": "196619"
+"Area_Sq": "3.63684"
}
+"geometry": {#839
+"type": "MultiPolygon"
+"coordinates": array:1 [
0 => array:1 [
0 => array:169 [ …169]
]
]
}
}
Let's support I have a model Post and I want to save additional data in JSON format in the posts table. In that case, we can use property $casts in Laravel. Which will cast our field value to whatever we gave.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $table='posts';
protected $fillable = ['user_id', 'title', 'short_description', 'description', 'status', 'json_data'];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'json_data' => 'array',
];
}
Now we want to save data something like this
$data = [
'user_id' => 1,
'title' => 'abc',
'short_description' => 'test',
'description' => 'test',
'status' => true,
'json_data' => [
'additional_info' => '',
'post_image' => '',
...
],
];
$item = new Post;
$item->fill($data)->save();
This will save your json_data array values to JSON in the database. But when you will get data from the database it will convert that to array automatically.
For reference read this
since i am not a big fan of processing the json as a object
So the json_decode will accept the second arg so
$json = File::get("public/kmz/WASASubdivisions.geojson");
$data = json_decode($json,true);
dd($data);
foreach ($data as $obj)
{
Regions::create(array(
'name' => $obj['Name'],
'description' => $obj['description'],
'altitudeMode' => $obj['altitudeMode'],
'Town' => $obj['Town'],
'AC' => $obj['AC'],
'No_of_TW' => $obj['No_of_TW'],
'No' => $obj['No'],
'DC'=> $obj['DC'],
'HH_2017' => $obj['HH_2017'],
'FID' => $obj['FID'],
'Area_ha' => $obj['Area_ha'],
'Field_1' => $obj['Field_1'],
'Pop_Dens' => $obj['Pop_Dens'],
'Id' => $obj['Id'],
'Pop_2017' => $obj['Pop_2017'],
'Area_Sq'=> $obj['Area_Sq'],
));
}
Can You Post the dd() result and fileds sets of the table
public function run()
{
$json = File::get("public/kmz/WASASubdivisions.geojson");
$data = json_decode($json);
dd($data);
foreach ($data as $obj){
Regions::create(array(
'name' => $obj->Name,
'description' => $obj->description,
'altitudeMode' => $obj->altitudeMode,
'Town' => $obj->Town,
'AC' => $obj->AC,
'No_of_TW' => $obj->No_of_TW,
'No' => $obj->No,
'DC'=> $obj->DC,
'HH_2017' => $obj->HH_2017,
'FID' => $obj->FID,
'Area_ha' => $obj->Area_ha,
'Field_1' => $obj->Field_1,
'Pop_Dens' => $obj->Pop_Dens,
'Id' => $obj->Id,
'Pop_2017' => $obj->Pop_2017,
'Area_Sq'=> $obj->Area_Sq,
));
}
}
The attributes are under the properties key, but you're referencing them from the root of the object. e.g. $obj[0]->Name should be $obj[0]->properties->Name, etc.

Laravel forgen key not passing tests

I am working through TDD in Laravel. I have a Location factory that looks like this:
LocationFactory
$factory->define(Location::class, function (Faker $faker) {
return [
'owner_id' => function () {
return factory(User::class)->create()->id;
},
'name' => $faker->company,
...
];
});
My test looks like this:
LocationTest
// Allow Laravel to handle the exception.
$this->withExceptionHandling();
// Create an authenticated user instance.
$user = factory(User::class)->create();
// Create the location instances via a factory.
$location = factory(Location::class)->create();
// An authenticated user can send a POST request to /locations to create a new location.
$response = $this->actingAs($user)->post('/locations', $location->toArray());
// Assert the system should persist the data to the database.
$this->assertDatabaseHas('locations', [
'id' => $location->id,
'owner_id' => $location->owner_id,
'name' => $location->name,
'description' => $location->description,
'address' => $location->address,
'address2' => $location->address2,
'city' => $location->city,
'state' => $location->state,
'zip' => $location->zip,
'created_at' => $location->created_at,
'updated_at' => $location->updated_at,
'deleted_at' => null,
]);
// Assert the response.
$response->assertSessionHasNoErrors();
$response->assertStatus(200);
The error I am getting is pretty obvious:
[
"The owner id field is required."
]
Failed asserting that true is false.
However, I know I'm getting an owner_id in my tests:
dd($location);
#original: array:12 [
"owner_id" => 665
...
Here is a snippet of my controller - how I'm saving the location.
LocationController
$attributes = $request->validate([
'owner_id' => 'required',
'name' => 'required',
...
]);
$location = Location::create($attributes);
$location->owner_id = auth()->id();
$location->save();
My Location model looks like this:
protected $fillable = [
'name', 'description', 'address', 'address2', 'city', 'state', 'zip',
];
/**
* The attributes that aren't mass assignable.
*
* #var array
*/
protected $guarded = [
'owner_id',
];
Using telescope I can see that owner_id is not in the array. I am not sure what I am doing wrong.
Thank you for any suggestions!
Edit
Checking my migration to make sure the field is there:
$table->unsignedInteger('owner_id');
While looking right at the raw database, I can see the column exists and has data.

Laravel Auth::user() Assign Custom User Model

I'm using my own User model class that is not derived from Eloquent. I use a database driver for authentification, which works fine.
However, Auth::user() returns a class of type GenericUser. Is there a way to assign a custom user model to the Auth class?
I tried auth config...
'users' => [
'driver' => 'database',
'table' => 'users',
'model' => App\Models\User::class
],
But it doesn't work. Perhaps this functionality doesn't exist.
Edit:
I don't want to use Active record, I have a Data Mapper package for that. My user model looks like this...
<?php
class User extends Model
{
use Notifiable, HasApiTokens, CanResetPassword;
use Authenticatable, Authorizable;
protected $attributes = [
'id' => null, 'roleId' => null,
'email' => null, 'phone' => null,
'firstName' => null, 'lastName' => null,
'password' => null, 'rememberToken' => null,
'registrationLocation' => null,
'data' => null,
'verified' => 0,
'createdAt' => null, 'updatedAt' => null,
];
public function __construct(array $attributes = [])
{
$this->fill($attributes);
}
}
Model is extended from the data mapper package's class Entity.

Attach extra attributes to Laravel pivot table

I have 4 extra attributes ('product_id', 'quantity', 'discount_percent', 'discount_amount') in my pivot table, but my values for these are always 0 when I store, while the rest is populated properly. Any ideas?
Invoice model
public function productversion()
{
return $this->belongsToMany('App\Productversion')->withPivot('product_id', 'quantity', 'discount_percent', 'discount_amount')->withTimestamps();
}
Productversion model
public function invoice()
{
return $this->belongsToMany('App\Invoice')->withPivot('product_id', 'quantity', 'discount_percent', 'discount_amount')->withTimestamps();
}
Controller (store)
$invoice->productversion()->attach($productversionid, ['product_id' => $productid], ['quantity' => $qty], ['discount_percent' => $discountprc], ['discount_amount' => $discountamt]);
Just one array will do:
$invoice->productversion()->attach($productversionid, [
'product_id' => $productid,
'quantity' => $qty,
'discount_percent' => $discountprc,
'discount_amount' => $discountamt
]);
In addition to #jeff's method, you can attach or sync multiple elements with pivot attributes providing a multidimensional array that has ids as keys.
$attach_data[$productversionid] = [
'product_id' => $productid,
'quantity' => $qty,
'discount_percent' => $discountprc,
'discount_amount' => $discountamt
];
Then you can $invoice->productversion()->attach($attach_data).
Substantially you can pass an array like
[
'relation_id' => [
// pivot data
],
'relation_id' => [
// pivot data
],
// ...
]

Resources