Laravel store JSON data API to database - laravel

I got the data json from API and I want to store them to my database.
data json sample :
{
"success": true,
"data": [
{
"status_employee_id": "1",
"name": "Manager"
},
{
"status_employee_id": "2",
"name": "Staff"
},
{
"status_employee_id": "3",
"name": "OB"
},
{
"status_employee_id": "4",
"name": "Fired"
},
{
"status_employee_id": "5",
"name": "Retired"
}
]
}
My model
class StatusEmployee extends Model
{
use HasFactory;
protected $table = 'status_employee';
protected $fillable = [
'status_employee_id','name'
];
public $timestamps = false;
}
I have tried use this in my controller
public function store()
{
$client = new \GuzzleHttp\Client();
$res = $client->request('GET', 'http://xx.xx.xx.xx/tools/public/get_status_employee');
$datas = json_decode($res->getBody(), true);
foreach($datas as $data){
StatusEmployee::create([
'status_employee_id' => $data->status_employee_id,
'name' => $data->name,
]);
}
}
And I want to store the data json sample to my table status_employee. How to make it?

It's easy, Laravel Eloquent will do everything for you.
// If json is in string decode first
$data = json_decode($res->getBody(), true); // to array
// Eloquent approach
StatusEmployee::insert(#$data['data']);

I assume you use Laravel since you have mentioned Laravel in your tags.
DB::table('status_employee')->insert(json_decode($res->getBody(),true)['data']);

Related

spatie/laravel-medialibrary, filters on getMedia() function not working

I am trying to get media for certain modal as follows:
public function show(Gallery $gallery)
{
$images = $gallery->getMedia('default'); //returns images
// $images = $gallery->getMedia('default', ['name', 'original_url']); //returns empty
return response()->json(['data' => $images]);
}
when not adding filters I get the correct data as follows:
{
"data": {
"686cc1b1-cfdc-425d-9b93-c99290f0d35e": {
"name": "Screenshot from 2022-06-27 23-29-29",
"file_name": "Screenshot-from-2022-06-27-23-29-29.png",
"uuid": "686cc1b1-cfdc-425d-9b93-c99290f0d35e",
"preview_url": "",
"original_url": "http://app.test/storage/media/25/Screenshot-from-2022-06-27-23-29-29.png",
"order": 1,
"custom_properties": [],
"extension": "png",
"size": 10546
}
}
}
but when I use filters I get empty array.
You have to retrieve single media, then you can chain property name
$gallery->getMedia('default')[0]->name;
or
$gallery->getFirstMedia('default')->name;
If you want to return json with name and original_url field for every media, that can be achieved by using API resource, something like this:
$images = $gallery->getMedia('default');
return MediaResource::collection($images);
and in MediaResource class you have:
public function toArray($request)
{
return [
'name' => $this->name,
'original_url' => $this->original_url
];
}

Laravel - How to consume and refresh external api into db using Guzzle

I am having this model in my Laravel-5.8 project:
Employee
class Employee extends Model
{
protected $table = 'employees';
protected $primaryKey = 'id';
protected $fillable = [
'staff_code',
'first_name',
'last_name',
'department_id',
];
public function department()
{
return $this->belongsTo('App\Department','department_id');
}
}
That is,:
App\Employee
Also I have an external api that comes in form of JSON get request.
https://api.employees.net/allemployees
I have viewed it with postman get request and I have something like this:
{
"ID": "1",
"StaffCode": "STC001",
"FirstName": "Japheth",
"LastName": "Shalom",
"DepartmentCode": "dep2",
},
{
"ID": "2",
"StaffCode": "STC002",
"FirstName": "Ahitophel",
"last_name": "Nedum",
"DepartmentCode": "dep1",
},
{
"ID": "3",
"StaffCode": "STC003",
"FirstName": "Joash",
"FirstName": "Nathan",
"DepartmentCode": "dep2",
},
and so on... this continues
Already I have created this function:
use App\Employee;
use App\Department;
public function index()
{
$client = new GuzzleHttp\Client();
$res = $client->request('GET','https://api.employees.net/allemployees');
$clientdatas = json_decode($res, true);
...
}
Apart from the id and staff_code that are UNIQUE, any of the others fields too can change from the source.
Since any of the fields can change at any time. How do I refresh the entire db, save new data and update changes?
Thank you
I could do something like this:
use App\Employee;
use App\Department;
public function index()
{
$client = new GuzzleHttp\Client();
$res = $client->request('GET','https://api.employees.net/allemployees');
$clientdatas = json_decode($res->getBody()->getContents(), true);
foreach($clientdatas as $clientdata)
{
$employee = Employee::firstOrNew(['id' => $clientdata['ID']]);
$employee->staff_code = $clientdata['StaffCode'];
$employee->first_name = $clientdata['FirstName'];
$employee->last_name = $clientdata['LastName'];
$employee->save();
}
}
Every time you will make an API call, create an instance of the employee model, or get the associated model if the ID exists. Then assign the new values and save your model. This way, you will be able to either create or update the models in a single loop without any complexities.
Don't know will it work or not but the logic you can keep.. In the other answer he is querying under a loop which is bad!
Hope It will Help you a little bit
public function index() {
$client = new GuzzleHttp\Client();
$res = $client->request('GET','https://api.employees.net/allemployees');
$clientdatas = json_decode($res->getBody()->getContents(), true);
// create a blank array for insert
$insert_arr = [];
foreach($clientdatas as $clientdata) {
$make_array = [
'id' => $clientdata['ID'],
'staff_code' => $clientdata['StaffCode'],
'first_name' => $clientdata['FirstName'],
.
.
];
array_push($insert_arr, $make_array);
// Now the the $insert_arr will ready for insert
}
// Here you have to check its duplicate or not
$exist_in_db = Employee::all('id')->toArray(); // get the id array from db
// do the stuff for unset the duplicate
$final_id = array_map(function($value) {
return $value['id'];
}, $team_id);
unset($exist_in_db);
if(count($final_id) > 0){
foreach ($insert_arr as $key => $value) {
if (in_array($value['id'], $final_id)) {
unset($insert_arr[$key]);
} else {
array_push($final_id, $value['id']);
}
}
}
// finally insert it here
if (count($insert_arr) > 0) {
Employee::insert($insert_arr);
}
}
Let me know its helpful or not!

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.

Laravel, remove null Eloquent object attributes from JSON

Is there an elegant way to remove NULL values from an Eloquent Object? My object is nested with relationships. This particular call can be 1000s of lines long, so my main reason for trying this is to save bandwidth for the user, but server performance is also a consideration.
My code:
$data['locations'] = Location::with('address')->where('user_id', '1')->get();
return Response::json($data);
I experimented with Mutators, but unless I'm mistaken Mutators don't have power over the object key, just the value.
I also tried and failed to use array_filter like these:
Any PHP function that will strip properties of an object that are null?
How to remove empty associative array entries
EDIT As requested,
{
"status": "ok",
"locations": [
{
"id": "1",
"latitude": "12.239107980271",
"longitude": "109.19479025725",
"user_time": "",
"transport": "Bus",
"title1": "",
"title2": "",
"address": {
"town": "Nha Trang",
"country": "Vietnam",
"address": "36-44 Hùng Vương, Lộc Thọ, Nha Trang, Khanh Hoa Province, Vietnam"
},
"altitude": {
"altitude": "10.006237983704"
},
"timezone": {
"offset": "25200"
},
"forecast": {
"icon": "",
"high_temp": "",
"low_temp": ""
}
},
{
"id": "2",
Desired response:
{
"status": "ok",
"locations": [
{
"id": "1",
"latitude": "12.239107980271",
"longitude": "109.19479025725",
"transport": "Bus",
"address": {
"town": "Nha Trang",
"country": "Vietnam",
"address": "36-44 Hùng Vương, Lộc Thọ, Nha Trang, Khanh Hoa Province, Vietnam"
},
"altitude": {
"altitude": "10.006237983704"
},
"timezone": {
"offset": "25200"
}
},
{
"id": "2",
As you can see, I could simply loop through the whole lot and remove any keys - or keys of keys - without values. I was hoping Laravel might provide a neat/fast way of doing the same.
I should add that technically only the latitude and longitude are required fields!
3 possibilities:
Write a response macro which cleans up your json data:
http://laravel.com/docs/responses#response-macros
Extend the Response class and implement your cleanup routine there. See this great tutorial for details how to do this: http://fideloper.com/extend-request-response-laravel
Implement the jsonSerialize method in your model which will be automatically called when your model is converted to json and place your cleanup routines there. You can even go a step further and write your own Collection for your Location model. Depending on your data structure this can make things a little bit easier. A nice tutorial for this purpose can be found here: http://heera.it/extend-laravel-eloquent-collection-object
I personally would prefer option 3.) because the data modifications happens where it should happen - in your model.
But bottom line it really depends which solutions fits best to your project.
First make a trait and add your custom validation then use in your each resource where you need
trait ResourceHelpers
{
/**
* Remove null values from Eloquent api resource
* #param array $data
* #return array
*/
public function removeNullValues(array $data)
{
$filtered_data = [];
foreach ($data as $key => $value) {
// if resource is empty
if ($value instanceof JsonResource and $value->resource === null) {
continue;
}
$filtered_data[$key] = $this->when($value !== null, $value);
}
return $filtered_data;
}
}
Then use it in your resource
class UserResource extends JsonResource
{
use ResourceHelpers;
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return $this->removeNullValues([
"id" => $this->id,
"first_name" => $this->first_name,
"last_name" => $this->last_name,
"phone" => $this->phone,
"email" => $this->email,
"balance" => $this->balance,
'address' => $this->address,
'city' => $this->city,
'state' => $this->state,
'zip_code' => $this->zip_code,
'country' => CountryResource::make($this->whenLoaded('country')),
"joined_at" => $this->created_at,
"updated_at" => $this->updated_at,
]);
}
}
I enhanced the removeNullValues to also ignore empty arrays and be recursive to handle nested arrays. Please check this one.
function removeNullValues(array $data)
{
$filtered_data = [];
foreach ($data as $key => $value) {
if (is_array($value))
{
if (sizeof($value) > 0)
$filtered_data[$key] = $this->removeNullValues($value);
}
else if ($value != null){
$filtered_data[$key] = $value;
}
}
return $filtered_data;
}

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