convert csv file to json object with Laravel - json

I am doing a project with Laravel 7. I have to read a csv file and through a controller passing the data in json format to a view.
Unfortunately I don't know how to do that.
These are my controller methods:
public function index($source)
{
$source = strtolower($source);
switch ($source) {
case "csv":
$file_csv = base_path('transactions.csv');
$transactions = $this->csvToJson($file_csv);
dd(gettype($transactions));
return view('transactions', ['source' => $source, 'transactions' => $transactions]);
break;
case "db":
$transactions = Transaction::all();
dd(gettype($transactions));
return view('transactions', ['source' => $source, 'transactions' => $transactions]);
break;
default:
abort(400, 'Bad sintax error.');
}
}
function csvToJson($filename = '', $delimiter = ',')
{
if (!file_exists($filename) || !is_readable($filename)) {
return false;
}
$header = null;
$data = array();
if (($handle = fopen($filename, 'r')) !== false)
{
while (($row = fgetcsv($handle, 1000, $delimiter)) !== false)
{
if (!$header)
$header = $row;
else
$data[] = array_combine($header, $row);
}
fclose($handle);
}
return $data;
}
As you can see, under the two cases I put a dd with a gettype function inside. In the first case I receive uncorrectly the response array, in the second one I receive correctly the response object.
The converted csv file should have this format:
[{"id":1,"code":"T_218_ljydmgebx","amount":"8617.19","user_id":375,"created_at":"2020-01-19T16:08:59.000000Z","updated_at":"2020-01-19T16:08:59.000000Z"},
{"id":2,"code":"T_335_wmhrbjxld","amount":"6502.72","user_id":1847,"created_at":"2020-01-19T16:08:59.000000Z","updated_at":"2020-01-19T16:08:59.000000Z"}]
Do you know how to convert the array transactions into a json object in the first case?

I don't know if there is any build-in solution on Laravel, but it can be done by PHP.
I didn't test my code. So it might not work, or contain some typos, but I'm sure it will give you some directions.
$cols = ["id","code","amount","user_id","created_at","updated_at"];
$csv = file('folder/name.csv');
$output = [];
foreach ($csv as $line_index => $line) {
if ($line_index > 0) { // I assume the the first line contains the column names.
$newLine = [];
$values = explode(',', $line);
foreach ($values as $col_index => $value) {
$newLine[$cols[$col_index]] = $value;
}
$output[] = $newLine;
}
}
$json_output = json_encode($output);

You can just do this :
$csv= file_get_contents($file);
$array = array_map('str_getcsv', explode(PHP_EOL, $csv));
$json json_encode($array);
If you want to return json object
return $json;
If you want to create a .json file
// Pure PHP
$file = fopen('results.json', 'w');
fwrite($file, $json);
fclose($file);
// Laravel using Storage
Storage::disk('local')->put('public/result.json', $json);
I hope this helps somone.

I have an email marketing application where I made bulk importers. So here is their CSV TO JSON code.
function convert_csv_to_json($csv_data){
// CSV to JSON process 1
$context = array(
'http'=>array(
'follow_location' => false,
'max_redirects' => 1000000
)
);
$context = stream_context_create($context);
if (($handle = fopen($csv_data, "r", false, $context)) !== FALSE) {
$csvs = [];
while(! feof($handle)) {
$csvs[] = fgetcsv($handle);
}
$datas = [];
$column_names = [];
foreach ($csvs[0] as $single_csv) {
$column_names[] = $single_csv;
}
foreach ($csvs as $key => $csv) {
if ($key === 0) {
continue;
}
foreach ($column_names as $column_key => $column_name) {
$datas[$key-1][$column_name] = $csv[$column_key];
}
}
return $json = json_encode($datas);
}
// OR
// CSV to JSON process 1
$cols = ['id',
'owner_id',
'name',
'email',
'country_code',
'phone',
'favourites',
'blocked',
'trashed',
'is_subscribed',
'deleted_at',
'created_at',
'updated_at.'];
$csv = file($csv_data);
$output = [];
foreach ($csv as $line_index => $line) {
if ($line_index > 0) { // I assume the the first line contains the column names.
$newLine = [];
$values = explode(',', $line);
foreach ($values as $col_index => $value) {
$newLine[$cols[$col_index]] = $value;
}
$output[] = $newLine;
}
}
return $json_output = json_encode($output);
}

Related

laravel foreach json response not working right

I'm having a problem with a soap response in laravel...
I'm calling the soap in the controller like this :
public function users()
{
$user = Auth::user();
$users = User::all();
// webservice X3
$soapclient = new SoapClient($this->WSDL, $this->params);
// method x3
$wsname = 'ZWSUSR01';
$xml='<?xml version="1.0" encoding="utf-8"?>';
$xml.='<PARAM>';
$xml.='</PARAM>';
$result = $soapclient->run($this->CContext, $wsname, $xml);
$status = $result->status;
$i=0;
if ($status == 1) {
$xml = simplexml_load_string($result->resultXml);
foreach ($xml->TAB->LIN as $line) {
$x3users[$i]= array();
foreach ($line->FLD as $name) {
$x3users[$i]["".$name['NAME'].""] = (string)$name;
}
$i++;
}
$x3users= json_encode($x3users, JSON_UNESCAPED_UNICODE );
} else {
$message = $result->resultXml;
$vars = array(
'xwebservice' => $wsname,
'xident' => $id,
'xmessage' => $message
);
$this->erroRotinas($vars);
$xml='';
}
return view('configs.users', compact(['users', 'x3users']));
}
When i call in the view the response using {{ $x3users }} it gives me the result in json and it looks fine [{...},{...},{...}]
But if I do #foreach($x3users as $x3user) it returns Invalid argument supplied for foreach() (View:
What can it be?

How to add picture to database with laravel

I am creating Laravel 7 project and I want to add/browse images into/from MySQL database.
The images column names are icon_lg and icon_sm
This is my create function in the Controller I tried it in two ways as I saw in some tutorials:
public function create(Request $request)
{
$object = $this->objectModel::create([
'name' => $request->name,
'icon_sm' => $request->icon_sm
]);
if($request->hasFile('icon_lg')) {
$images = explode(',', $request->hasFile('icon_lg'));
foreach($images as $image)
$filename = rand().'.'.$image->getClientOriginalExtension();
$filePath = public_path("images");
$image->move($filePath, $filename);
return Image::create([
'icon_lg' => $filename,
//'item_id' => $created->id,
]);
}
if ($request->save == 'browse')
return redirect()->route("{$this->objectName}");
elseif ($request->save == 'edit')
return redirect()->route("{$this->objectName}.edit", ['id' => $object]);
elseif ($request->save == 'add')
return redirect()->route("{$this->objectName}.add");
else
return redirect($request->previous_url);
}
It does nothing with icon_lg it inserts null value to it.
And it deals with icon_sm as String.
i think you must set the hasfile validation inside foreach loop like
$images = explode(',', $request->hasFile('icon_lg'));
foreach($images as $image)
if($request->hasFile('icon_lg')) {
$filename = rand().'.'.$image->getClientOriginalExtension();
$filePath = public_path("images");
$image->move($filePath, $filename);
return Image::create([
'icon_lg' => $filename,
//'item_id' => $created->id,
]);
}
just test it without validation first
it should work

Api Response and Json laravel format

I'm using Laravel 5.7. and GuzzleHttp 6.0 to get API response
from endpoint
I'm passing query data from Blade form to this function.
public static function prhmulti($multisearch, $start ,$end)
{ $city = $multisearch['city'];
$client = new Client([
'base_uri' => 'https://avoindata.prh.fi/tr/',
'query' => [
'totalResults' => 'true',
'maxResults' => '1000',
'registeredOffice'=> $city,
'companyForm'=>'OY',
'companyRegistrationFrom'=>$start,
'companyRegistrationTo'=>$end,
],
'defaults'=>[
'timeout' => 2.0,
'cookies' => true,
'headers' => [
'content-type' => 'application/json',
'User-Agent' =>"GuzzleHttp/Laravel-App-5.7, Copyright MikroMike"
]]]);
$res = $client->request('GET','v1');
$ResData = json_decode($res->getBody()->getContents());
dd ($ResData) gives all data from API response.
But I am not able to return JSON back to other function
return $this->multisave($ResData);
public static function multisave (data $ResData)
This will parse JSON and
{
foreach ($data->results as $company) {
$name = $company->name;
$Addr = $company->addresses;
$businessId = $company->businessId;
$companyForm = $company->companyForm;
$registrationDate = $company->registrationDate;
foreach ($company->addresses as $Addr) {
$city = $Addr->city;
$postcode = $Addr->postCode;
$street = $Addr->street;
}
}
save data to Mysql.
$NewCompany = new Company();
$NewCompany = Company::updateOrCreate($array,[
[ 'vat_id', $businessId],
[ 'name', $name],
[ 'form',$companyForm],
[ 'street', $Addr],
[ 'postcode', $postcode],
[ 'city', $city],
[ 'regdate', $registrationDate],
]);
}
IF Parse part and Save part is inside same function code works ok(save only one company),
but I need to separate them because later on it's easier to maintain.
Error which I am getting to return $ResData
" Using $this when not in object context"
Information is in JSON array.
Also foreach part save ONLY one company ?
foreach ($data->results as $company) {
$name = $company->name;
$Addr = $company->addresses;
$businessId = $company->businessId;
$companyForm = $company->companyForm;
$registrationDate = $company->registrationDate;
foreach ($company->addresses as $Addr) {
$city = $Addr->city;
$postcode = $Addr->postCode;
$street = $Addr->street;
}
So : 1) What is best way to create own function for parse JSON
and other for save data to DB?
2) As foreach loop save only one company data, What is
best way to fix it?
Thanks MikroMike.
Resolved my own question for saving companies to db
First get total number inside Array
use for-loop to make counting
use foreach-loop extract information per single company as object.
$data = json_decode($res->getBody()->getContents());
$total = $data->totalResults;
for ($i = 0; $i < $total; $i++){
$NewCompany = new Company();
foreach ($data->results as $company)
{
$name = $company->name;
$businessId = $company->businessId;
$companyForm = $company->companyForm;
$registrationDate = $company->registrationDate;
$array = [];
Arr::set($array, 'vat_id', $businessId);
Arr::set($array, 'name', $name );
Arr::set($array, 'form', $companyForm);
Arr::set($array, 'regdate', $registrationDate);
$NewCompany = Company::updateOrCreate($array,[
[ 'vat_id', $businessId],
[ 'name', $name],
[ 'form',$companyForm],
[ 'regdate', $registrationDate],
]);
}// END OF MAIN FOREACH
}// END OF For loop
}// END OF FUCNTION
} // END OF CLASS

JSON response return HTML inside a Loop

I have this function in Laravel 5.1
public function calcolaKilometri()
{
$partenza = Input::get('partenza');
$destinazione = Input::get('destinazione');
$distanceMatrix = new DistanceMatrix(new Client(), new GuzzleMessageFactory());
$response = $distanceMatrix->process(new DistanceMatrixRequest(
[$partenza],
[$destinazione]
));
foreach ($response->getRows() as $row) {
foreach ($row->getElements() as $element) {
$distance = $element->getDistance();
$text = $distance->text;
$value = $distance->value;
$data = ['text' => $text, 'value' => $value];
return \Response::json($data);
}
}
}
need to return to Ajax JSON data but this function return plain HTML response, because we are in a forech loop. How i can do the trick?
I'm not sure I fully understand what you're saying but I assume you want to return all of the data found when looping through your result set in a single JSON response.
Try something like this:
// Your previous code...
// Initialise a $data array here, that we're going to fill with data
$data = [];
foreach ($response->getRows() as $row) {
foreach ($row->getElements() as $element) {
$distance = $element->getDistance();
$text = $distance->text;
$value = $distance->value;
// Append the new set of data to your array
$data[] = ['text' => $text, 'value' => $value];
}
}
// Return the data as JSON only when we've filled it with everything
return response()->json($data);
Try This...
$json = json_encode($data);
return \Response::json($json);
Solved using sessions. If someone have the same issue:
public function calcolaKilometri()
{
$partenza = Input::get('partenza');
$destinazione = Input::get('destinazione');
$distanceMatrix = new DistanceMatrix(new Client(), new GuzzleMessageFactory());
$response = $distanceMatrix->process(new DistanceMatrixRequest(
[$partenza],
[$destinazione]
));
foreach ($response->getRows() as $row) {
foreach ($row->getElements() as $element) {
$text = $element->getDistance()->getText();
$value = $element->getDistance()->getValue();
\Session::put('testo', $text);
\Session::put('valore', $value);
}
}
// Return the data as JSON only when we've filled it with everything
$testo = \Session::get('testo');
$valore = \Session::get('valore');
$result = ['text' => $testo, 'value' => $valore];
return \Response::json($result);
}

get all rows from mysql tables in json format

i have to set my json file so i can display using the D3 JavaScript library graph this is my code:
<?php
$mns = DB::table('mns')
->join('phases','mns.phases_idphase','=','phases.idphase')
->join('users','mns.users_iduser','=','users.iduser')
->where('projets_idprojet','=',$id)
->order_by('mns.created_at','desc')
->take(1)
->get();
foreach ($mns as $mn )
{
$documents = DB::table('documents')
->where('mns_idmn','=',$mn->idmn)
->get();
$users = User::where('iduser','=',$mn->users_iduser)
->get();
$phases = Phase::where('projets_idprojet','=',$id)
->where('idphase','=',$mn->phases_idphase)
->get();
$nom_mn=$mn->nommn;
if ($mn->etat=='initié') $imagemn='http://localhost/batcoop/public/graph/mn_blue.png';
elseif ($mn->etat=='validé') $imagemn='http://localhost/batcoop/public/graph/mn_vert.png';
elseif ($mn->etat=='en attent') $imagemn='http://localhost/batcoop/public/graph/mn_gris.png';
else $imagemn='http://localhost/batcoop/public/graph/mn_rouge.png';
if(!empty($documents))
{
$table_corespond=0;
foreach ($documents as $document)
{
if ($document->etat=='initié') $imagedo='http://localhost/batcoop/public/graph/document_blue.png';
elseif ($document->etat=='validé') $imagedo='http://localhost/batcoop/public/graph/document_vert.png';
elseif ($document->etat=='en attent') $imagedo='http://localhost/batcoop/public/graph/document_gris.png';
else $imagedo='http://localhost/batcoop/public/graph/document_rouge.png';
$arraydoc= array('name' =>$document->nomdoc,'image'=>$imagedo,'group'=>3);
}
}
else
{
}
foreach ($phases as $phase)
{
$nom_phase=$phase->titrephase;
if ($phase->etatphase=='initié') $imageph='http://localhost/batcoop/public/graph/phase_blue.png';
elseif ($phase->etatphase=='validé') $imageph='http://localhost/batcoop/public/graph/phase_vert.png';
elseif ($phase->etatphase=='en attent') $imageph='http://localhost/batcoop/public/graph/phase_gris.png';
else $imageph='http://localhost/batcoop/public/graph/phase_rouge.png';
}
foreach ($users as $user)
{
$imageus="http://localhost/batcoop/public".$user->photousermin;
$nom_user=$user->nomuser." ".$user->prenomuser;
}
$nodes = array(array('name' =>$nom_mn,'image'=>$imagemn,'group'=>0),array('name' =>$nom_phase,'image'=>$imageph,'group'=>1),array('name' =>$nom_user,'image'=>$imageus,'group'=>2),$arraydoc);
$links = array(array("source"=>0,"target"=>1,"distance"=>6),array("source"=>2,"target"=>0,"distance"=>6),array("source"=>3,"target"=>0,"distance"=>6));
$graph='{ "nodes":'.json_encode($nodes).',"links":'.json_encode($links).'}';
$my_file='graph.json';
$handle = fopen($my_file, 'w') or die('Cannot open file: '.$my_file); //implicitly creates file
fwrite($handle, $graph);
the problem is that i have more than one document and in my json file shows only the last document
please can any one helps
Before line:
foreach ($documents as $document)
you should add:
$arraydoc = array();
and then change line:
$arraydoc= array('name' =>$document->nomdoc,'image'=>$imagedo,'group'=>3);
into:
$arraydoc[] = array('name' =>$document->nomdoc,'image'=>$imagedo,'group'=>3);