I am collecting ADSB data on a Raspberry Pi via a JSON file; I am using someones PHP code that is producing a SQL data base from the JSON file.However I need a csv file to feed into an analsis program (SPSS) that I have developed.
Here is the PHP code that creates the sql database
// generate sql insert statement per aircraft in range of user set alt_geom/latitude/longitude and optionally according only to hex or flight numbers in hex_code_array.txt and flight_code_array.txt
#var_dump($hex_code_array); var_dump($flight_code_array); // show arrays for debug
if ($user_set_array['filter_mode_database'] && $user_set_array['filter_mode_database_limited']) {
if (($ac_alt_geom != '' && $ac_alt_geom < $user_set_array['max_alt'] && $ac_lat < $user_set_array['max_lat'] && $ac_lat > $user_set_array['min_lat'] && $ac_lon < $user_set_array['max_lon'] && $ac_lon > $user_set_array['min_lon']) && (func_wildcard_search($ac_hex, $hex_code_array, $user_set_array['filter_mode_wildcard']) || ($ac_flight != '' && func_wildcard_search($ac_flight, $flight_code_array, $user_set_array['filter_mode_wildcard'])))) {
$sql .= "INSERT INTO aircrafts VALUES (NULL, '" . date("Y-m-d G:i:s l", $ac_now) . "', '$ac_now', '$ac_hex', '$ac_flight', '$ac_dist', ";
$sql .= "'$ac_alt_geom', '$ac_lat', '$ac_lon', '$ac_track', '$ac_gs', '$ac_baro_rate', '$ac_seen_pos', '$ac_seen', ";
$sql .= "'$ac_rssi', '$ac_messages', '$ac_category', '$ac_squawk', '$ac_alt_baro', '$ac_mlat', '$ac_tisb', '$message_rate');";
$sql .= PHP_EOL;
As I am going up a steep learning curve with PHP I have adapted some code that I found else where on Stack but its not producing a csv file. My objective was to take the variables that create the sql arrays and continually update the csv file .
$data= "id,now,hex,flight,distance,altitude,lat,long,track,gs,baro-rate,seen-pos,seen,rasi,messages,category,squark,alt-baro,mlat,tisb,rec-mag-sec\n";
$i = 1;
#echo $data;
$data = array(
array( '$i' ),
array( '$ac_id' ),
array( '$ac_now' ),
array( '$ac_hex' ),
array( '$ac_flight' ),
array( '$ac_distance' ),
array( '$ac_alt_geom' ),
array( '$ac_lat' ),
array( '$ac_long' ),
array( '$ac_track' ),
array( '$ac_gs' ),
array( '$ac_baro_rate' ),
array( '$ac_seen_pos' ),
array( '$ac_seen' ),
array( '$ac_rssi' ),
array( '$ac_messages' ),
array( '$ac_category' ),
array( '$ac_squark' ),
array( '$ac_alt_baro' ),
array( '$ac_mlat' ),
array( '$ac_tisb' ),
array( '$ac_rec_mag_sec' ),
);
}
function outputCSV($data) {
$outputBuffer = fopen("php://output", 'w');
foreach($data as $val) {
fputcsv($outputBuffer, $val);
}
fclose($outputBuffer);
}
$filename = 'aircrafts';
header("Content-type: text/csv");
header("Content-Disposition: attachment; filename=($filename).csv");
header("Pragama: no-cache");
hwader("Expires: 0");
outputCSV($data);
First of all, it looks like you are mixing and matching 2 separate methods of working with an array. If you are working with data that starts off as comma separated string like this:
$data= "1,'2019-2-15 12:00:00','#f6F0C1',1040,345,12500,32.1465,80.1263, ...";
Then you can convert $data into an array like this:
$data = explode(",", $data);
Note that when doing this, you are not using variable names but actual raw data that you want in the csv.
However, if your data is coming from a bunch of variables, then you declare your array like this:
$data= array($i, $ac_id, $ac_now, $ac_hex, $ac_flight, $ac_distance, $ac_alt_geom, $ac_lat ...);
Of note, since each element of your $data array is only one value, you don't need to make arrays out of them. Also, because you want to call these values as variables, you don't want to put them in quotes. If you put them in quotes, they will be evaluated as strings instead of variables.
Once you have used the appropriate method above to make an array called $data, you need to push it to your CSV. Another thing to note here is that you are only trying to put one line into the CSV at a time; so, you do not need to loop it at all. Looping is used for when you have an array of arrays where each subarray represents a single line in the CSV file. Since you are just doing a single line at a time, you can simplify your code as shown below.
function outputCSV($data) {
$outputBuffer = fopen("php://output", 'w');
fputcsv($outputBuffer,$data);
fclose($outputBuffer);
}
Related
how can optimization function this code in PHP smarty?
now I've a code to confuse me, there is a simple code.
$sql_set_land = "select * from set_new_land where id_rent_house =".Tools::getValue("id_rent_house");
//print_r($sql_set_land);
$n_land = Db::rowSQL($sql_set_land,true);
$landTitle1 = $n_land['landTitle1'];
$landTitle2 = $n_land['landTitle2'];
$landBuilderNumber = $n_land['landBuilderNumber'];
$landLandMark = $n_land['landLandMark'];
$land_1 = $n_land['land_1'];
$land_2 = $n_land['land_2'];
$land_3 = $n_land['land_3'];
...
...
...
$land_30 = $n_land['land_30'];
$land_31 = $n_land['land_31'];
$land_32 = $n_land['land_32'];
when I search the code that I need to push the value.
$this->context->smarty->assign([
'park_space' =>$park_space,
'recording_data' =>$recording_data,
'clode_number' => $clode_number,
'ad_choose_top' => $ad_choose_top,
'ad_choose_type' => $ad_choose_type,
'ad_choose_payment_type' => $ad_choose_payment_type,
'ad_choose_payment_type1' => $ad_choose_payment_type1,
'landTitle1' => $landTitle1,
'landTitle2' => $landTitle2,
'landBuilderNumber' => $landBuilderNumber,
'landLandMark' => $landLandMark,
'land_1' => $land_1,
'land_2' => $land_2,
'land_3' => $land_3,
...
...
...
'land_30' => $land_30,
'land_31' => $land_31,
'land_32' => $land_32,
how can optimization function? Can I write to array? if It's can write into array, how can I do?
Your problem is not in the PHP code, it is in the design of your database. Any time you need to have numbers in column names is a sign that you've failed to normalize your data.
If you expanded the *, which is generally good practice to avoid surprises when you make changes to your database, you would have to write this:
select
landTitle1,
landTitle2,
landBuilderNumber,
landLandMark,
land_1,
land_2,
land_3,
land_4,
land_5,
land_6,
land_7,
land_8,
land_9,
land_10,
land_11,
land_12,
land_13,
land_14,
land_15,
land_16,
land_17,
land_18,
land_19,
land_20,
land_21,
land_22,
land_23,
land_24,
land_25,
land_26,
land_27,
land_28,
land_29,
land_30,
land_31,
land_32
from set_new_land
where id_rent_house = :id
With a properly normalised database, you would instead write something like this:
select
SND.landTitle1,
SND.landTitle2,
SND.landBuilderNumber,
SND.landLandMark,
L.landNumber,
L.land
from set_new_land as SND
join lands as L
On L.set_new_land_id = SND.set_new_land_id
where SND.id_rent_house = :id
Then in PHP, you can use the array_column function:
$lands = array_column($dbResults, 'land');
// or, if the land numbers are important
$lands = array_column($dbResults, 'land', 'landNumber');
If you can't fix your data, though, you can transform it into a more sensible form in PHP, with a loop that counts from 1 to 32:
$lands = [];
for ( $landNumber=1; $landNumber<=32; $landNumber++ ) {
$columnName = 'land_' . $landNumber;
$lands[] = $messyDbResults[ $columnName ];
}
Hey I am building a chatbot using dialogflow and I am generating the responses by using a customized Webhook (I am programming in php). I am extracting data from my database and storing it in an array but when I send the array as a response to dialogflow it only shows the first row.
Here is my code:
<?php
header('Content-Type: text/html; charset=utf-8');
date_default_timezone_set("Asia/Bangkok");
$date = date("Y-m-d");
$time = date("H:i:s");
$json = file_get_contents('php://input');
$request = json_decode($json, true);
$input = fopen("log_json.txt", "w") or die("Unable to open file!");
fwrite($input,$json);
fclose($input);
function processMessage($update) {
if($update["queryResult"]["action"] == "ques"){
$bdd= new PDO('mysql:host=localhost;dbname=****', '****', '***', array(
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8")) ;
$data = array();
$nom= $update["queryResult"]["parameters"]["nom_aliment"];
$info=$update["queryResult"]["parameters"]["Information"];
$quantite=$update["queryResult"]["parameters"]["Quantite"];
$req=$bdd->prepare("SELECT * FROM TableCiqual WHERE alim_nom LIKE ? ");
$req->execute(array("%$nom%"));
while($resultat=$req->fetch()){
$variab=$resultat[$info]*$quantite/100;
$ppp =$resultat['alim_nom'].' '.$info.' : '.$variab;
$data=$ppp;
}
sendMessage(array(
"source" => $update["responseId"],
"fulfillmentText"=>$data,
"payload" => array(
"items"=>[
array(
"simpleResponse"=>
array(
"textToSpeech"=>"Bad request"
)
)
],
),
));
}
}
function sendMessage($parameters) {
echo json_encode($parameters);
}
I know that my query returns multiple results all these results are stored in the array $data that I send as a response in dialogflow. The problem is that dialogflow only shows me the first row of the array $data instead of the whole array with all the rows.
My question is : Is it possible to send an array as a response in dialogflow and if yes how so.
I think there are two issues here.
The first is that $data is not actually containing a list of your results. The line
$data = $ppp;
is assigning $ppp, which is a string, to $data rather than adding on to the end of the array. I think, for that line, you want something more like
$data[] = $ppp;
However, this doesn't solve your problem completely, since the fulfillmentText attribute in JSON isn't expecting an array - it is expecting a string. So you probably want to concatenate all of those entries with something like
"filfillmentText" => implode( "\n", $data );
However, this assumes that you both want a new line in between each answer and that the chat system you're using supports the feature this way - not all do. (And you haven't indicated which one you're using.)
I am having the foreach loop that will run minimum 2000 loops
foreach ($giftCardSchemeData as $keypreload => $preload) {
for ($i=0; $i <$preload['quantity'] ; $i++) {
$cardid = new CarddetailsId($uuidGenerator->generate());
$cardnumber = self::getCardNumber();
$cardexistencetype = ($key == "giftCardSchemeData") ? "Physical" : "E-Card" ;
$giftCardSchemeDataDb = array('preload' => array('value' => $preload['value'], 'expirymonths' => $preload['expiryMonths']));
$otherdata = array('cardnumber' => $cardnumber, 'cardexistencetype' => $cardexistencetype, 'isgiftcard' => true , 'giftcardamount' => $preload['value'],'giftCardSchemeData' => json_encode($giftCardSchemeDataDb), 'expirymonths' => $preload['expiryMonths'], 'isloyaltycard' => false, 'loyaltypoints' => null,'loyaltyCardSchemeData' => null, 'loyaltyRedeemAmount' => null, 'pinnumber' => mt_rand(100000,999999));
$output = array_merge($data, $otherdata);
// var_dump($output);
$carddetailsRepository = $this->get('oloy.carddetails.repository');
$carddetails = $carddetailsRepository->findByCardnumber($cardnumber);
if (!$carddetails) {
$commandBus->dispatch(
new CreateCarddetails($cardid, $output)
);
} else {
self::generateCardFunctionForErrorException($cardid, $output, $commandBus);
}
}
}
Like above foreach I am having totally 5 of them. When I call the function each time the 5 foreach runs and then return the response. It take more time and the php maximum execution time occurs.
Is there a any way to send the response and then we could run the foreach in server side and not creating the maximum execution time issue.Also need an optimization for the foreach.
Also In symfony I have tried the try catch method for the existence check in the above code it return the Entity closed Error. I have teprorily used the existence check in Db but need an optimization
There seems to be a lot wrong (or to be optimized) with this code, but let's focus on your questions:
First I think this code shouldn't be in code that will be triggered by a visitor.
You should seperate 2 processes:
1. A cronjob that runs that will generate everything that must be generated and saved that generated info to a database. The cronjob can take as much time as it needs. Look at Symfony's console components
2. A page that displays only the generated info by fetching it from the database and passing it to a Twig template.
However, looking at the code you posted I think it can be greatly optimized as is. You seem to have a foreach loop that fetches variable data, and in that you have a for-loop that does not seem to generate much variability at all.
So most of the code inside the for loop is now being executed over and over again without making any actual changes.
Here is a concept that would give much higher performance. Ofcourse since I don't know the actual context of your code you will have to "fix it".
$carddetailsRepository = $this->get('oloy.carddetails.repository');
$cardexistencetype = ($key == "giftCardSchemeData") ? "Physical" : "E-Card";
foreach ($giftCardSchemeData as $keypreload => $preload) {
$cardnumber = self::getCardNumber();
$carddetails = $carddetailsRepository->findByCardnumber($cardnumber);
$giftCardSchemeDataDb = array('preload' => array('value' =>
$preload['value'], 'expirymonths' => $preload['expiryMonths']));
$otherdata = array('cardnumber' => $cardnumber, 'cardexistencetype' =>
$cardexistencetype, 'isgiftcard' => true , 'giftcardamount' =>
$preload['value'],'giftCardSchemeData' =>
json_encode($giftCardSchemeDataDb), 'expirymonths' =>
$preload['expiryMonths'], 'isloyaltycard' => false, 'loyaltypoints' =>
null,'loyaltyCardSchemeData' => null, 'loyaltyRedeemAmount' => null,
'pinnumber' => 0);
$output = array_merge($data, $otherdata);
for ($i=0; $i <$preload['quantity'] ; $i++) {
$cardid = new CarddetailsId($uuidGenerator->generate());
$output['pinnumber'] = mt_rand(100000,999999);
if (!$carddetails) {
$commandBus->dispatch(
new CreateCarddetails($cardid, $output)
);
} else {
self::generateCardFunctionForErrorException($cardid, $output, $commandBus);
}
}
}
Also: if in this code you are triggering any database inserts or updates, you don't want to trigger them each iteration. You will want to start some kind of database transaction and flush the queries each X iterations instead.
I am having troubles converting a string which contains tab delimited CSV output
into an array. While using the following code :
$data = stream_get_contents($request->getShipmentReport());
I get back data as following:
Date Shipped Comments Feedback Arrived on Time
5/11/15 2 comment response Yes
Now I would like to process this data into an array with the returned headers(line 1) as the index containing the value for each line which follows after that.
I am trying to end up with something like this :
$line['Date'] = 5/11/15
$line['Shipped'] = 2
$line['Feedback'] = response
$line['Arrived on Time'] yes
What would be the best way to achieve this ?
I recommend using a library for handling CSV for example the CSV-Package by The League of Extraordinary Packages
You can pass your data and start working with array structures right away:
$csvString = stream_get_contents($request->getShipmentReport());
$csvReader = \League\Csv\Reader::createFromString($csvString);
$data = $csvReader->fetchAssoc(
array('Date', 'Shipped', 'Comments', 'Feedback', 'Arrived on Time')
);
// Or since line 0 contains header
$data = $csvReader->fetchAssoc(0); // 0 is offset of dataset containing keys
Now your data should be in a structure like:
$data = array(
array(
'Date' => '5/11/15',
'Shipped' => '2',
...
),
array(
...
)
);
You can even filter out specific datasets and all kinds of fancy stuff. Just check the documentation I linked to.
League CSV reader gives me a bad result. I use this instead:
$csvReportString = stream_get_contents($request->getReport());
$csvReportRows = explode("\n", $csvReportString);
$report = [];
foreach ($csvReportRows as $c) {
var_dump($c);
if ($c) { $report[] = str_getcsv($c, "\t");}
}
var_dump($report);
I'm having some troubles with NuSOAP trying to send duplicate tags. This is the code i need to send :
<PartNumbers>
<string>string1</string>
<string>string2</string>
</PartNumbers>
I'm doing the call with this code:
$pn[] = 'APPSP2101V2';
$pn[] = 'ME665Y/A';
$PartNumbers = array( 'PartNumbers' => array('string' => $pn));
$result = $client->call('GetDataSheetsLastUpdate', $PartNumbers );
I'm sending those two PartNumbers but instead of send the two codes it's sending the last one "ME665Y/A"
Also if i try
$PartNumbers = array( 'PartNumbers' => array('string' => 'APPSP2101V2', 'string' => 'ME665Y/A'));
$result = $client->call('GetDataSheetsLastUpdate', $PartNumbers );
Only send the last string.
How can i make an array with the same keys but different value to make the XML look like in the beggining of the question.
Thank you in advance to all
With the following code:
$pn[] = 'APPSP2101V2';
$pn[] = 'ME665Y/A';
$PartNumbers = array( 'PartNumbers' => array('string' => $pn));
$result = $client->call('GetDataSheetsLastUpdate', $PartNumbers );
Works perfect , the problema was in the webservice.. if the P/N isn't correct only return the P/N with information on it.