I have this code i am using to write json to a file
<?php
require_once 'vendor/autoload.php';
$faker = Faker\Factory::create();
function getAge($start = 18, $end = 100, $repeat = 20){
$result = null;
static $ages = array();
if ( empty($ages) ) {
for ($i= $start; $i <= $end; $i++) {
for($j = 0; $j < $repeat; $j++)
$ages[] = $i;
}
}
$index = rand(0, count($ages));
$result = $ages[ $index ];
unset($ages[ $index ]);
$ages = array_values($ages);
return $result;
}
$superstars = array("Adam Cole","Finn Balor","Pete Dunne","Jordan Devlin","Noam Dar");
$fan_favourite_superstar_name = $superstars[ mt_rand( 0, count($superstars) -1 ) ];
$cities = array("London","Manchester","Leeds","Bristol");
$fan_location = $cities[ mt_rand( 0, count($cities) -1 ) ];
$the_models = array("Iphone","Nokia","Huawei","Samsung");
$fan_phone_model = $the_models[ mt_rand( 0, count($the_models) -1 ) ];
for ($x = 1; $x <= 100; $x++) {
echo $x;
$array = Array (
"$x" => Array (
"id" => uniqid(),
"fan_favourite_superstar_name" => $fan_favourite_superstar_name,
"fan_location" => $fan_location,
"fan_phone_model" => $fan_phone_model,
"fan_name" => $faker->name,
"fan_age" => getAge(),
"fan_comments" => $faker->text,
"fan_picture" => rand(1,500),
"last_updated" => time() + rand(1,1000),
)
);
// encode array to json
$json = json_encode(array('fans' => $array));
//write json to file
if (file_put_contents("data.json", $json))
echo "JSON file created successfully..."."<br/>";
else
echo "Oops! Error creating json file...";
}
?>
When i run, only the first line is written. Why are the other lines not being written?.
You are overwriting the file in each iteration of the loop. You need to tell the file_put_contents function you want to append, like so:
file_put_contents("data.json", $json, FILE_APPEND)
Edit:
Even though this answers the posted question, As Nigel Ren pointed out, this won't create a valid JSON file. Concerning your follow-up comment about the desired format, you'd need to build your array inside the loop and then write once afterwards (by moving everything after $json = json_encode(array('fans' => $array)); outside of the loop).
The correct way to build it is to follow Nigel's first comment about assignment (something the other answers which were deleted in the meantime also dealt with) to avoid overwriting the array each time:
$array["$x"] = Array (
"id" => uniqid(),
...
So, ultimately, you wouldn't even need the appending flag.
Related
I need to generate an array whose keys are not pre-defined.
I have this array:
regions = [
{
"id":1,
"name":"Alaska",
"continent_id":5,
"owner_id":3,
....
},
{
"id":2,
"name":"Greenland",
"continent_id":5,
"owner_id":7,
....
}
I want to generate
$summary = [];
for ($i = 0; $i < count($owners); $i++) {
for ($j = 0; $j < count($regions); $j++) {
if ($owners[$i]['id'] == $regions[$j]['owner_id']) {
$summary[ $regions[$j]['continent_id'] ]++; <-- NEED HELP HERE
}
}
}
So I end up with $summary containing a "key" for each continent that the user owns regions in, and how may in each continent.
The above does not work as it returns undefined index. How do I generate the array keys on the fly and keep the count?
My expected output is:
$summary = ['1' => 12, '3' => 5, '5' => 7];
$summary[1] = 12;
$summary[3] = 5;
$summary[5] = 7;
When you first encounter a particular value of 'continent_id' - or in fact any element of an array that hasn't previously been encountered, it's better to do an isset and then create it if required.
if ($owners[$i]['id'] == $regions[$j]['owner_id']) {
if ( isset($summary[ $regions[$j]['continent_id'] ]) === false ) {
$summary[ $regions[$j]['continent_id'] ] = 0;
}
$summary[ $regions[$j]['continent_id'] ]++;
}
I am just learning PHP and using the Codeigniter framework.
I'm using this code in my controller when inserting new data and it's working.
//INSERT MULTI ROWS TABEL harga_inventori
$kode_inventori = $_POST['kode_inventori'];
$result = array();
foreach($_POST['kode_kategori_pelanggan'] AS $key => $val){
$result[] = array(
"kode_kategori_pelanggan" => $_POST['kode_kategori_pelanggan'][$key],
"kode_inventori"=>$kode_inventori,
"harga" => $_POST['harga_jual'][$key],
"diskon" => $_POST['diskon'][$key]
);
}
$res = $this->db->insert_batch('harga_inventori', $result);
redirect("inventori");
But when I'm using the same pattern for the updating function, it's not working at all.
for($i = 0; $i < count($_POST['harga_jual'][$i]); $i++) {
if($_POST['kode_kategori_pelanggan'][$i] != '') {
$res[] = array(
'harga' => $_POST['harga_jual'][$i],
'diskon' => $_POST['diskon'][$i],
);
$this->db->where('kode_inventori',$_POST['kode_inventori']);
$this->db->where('kode_kategori_pelanggan',$_POST['kode_kategori_pelanggan'][$i]);
$this->db->update('harga_inventori',$res);
}
}
redirect("inventori");
I'm trying the update_batch() but I got many errors, so I'm using for loop and updating a single row at a time.
What could be the problem here?
Its only a typo. You should pass the array $res not $data, and change $res[] to $res since it is not needed. You should also check with isset() to prevent errors of undefined:
for($i = 0; $i < count($_POST['harga_jual'][$i]); $i++) {
if(isset($_POST['kode_kategori_pelanggan'][$i])) {
$res = array(
'harga' => $_POST['harga_jual'][$i],
'diskon' => $_POST['diskon'][$i],
);
$this->db->where('kode_inventori',$_POST['kode_inventori']);
$this->db->where('kode_kategori_pelanggan',$_POST['kode_kategori_pelanggan'][$i]);
$this->db->update('harga_inventori',$res);
}
}
redirect("inventori");
It would help to see some of your data to know what you are trying to do. It seems a little strange that you initiate the counter $i at the same time using it as an array key in the for loop like this: for($i = 0; $i < count($_POST['harga_jual'][$i]); $i++)
It would help to know how the data in your $_POST looks like. You could try to remove the [$i] in your for loop. I would also check each POST variable it they are set before using them, something like:
for($i = 0; $i < count($_POST['harga_jual']); $i++) {
if(isset($_POST['kode_kategori_pelanggan'][$i])) {
// CHECK IF POST VARIABLES IS SET AND IF NOT SET A DEFAULT VALUE (IN THIS EXAMPLE AN EMPTY STRING):
$harga_jual = isset($_POST['harga_jual'][$i]) ? $_POST['harga_jual'][$i] : '';
$diskon = isset($_POST['diskon'][$i]) ? $_POST['diskon'][$i] : '';
$kode_inventori = isset($_POST['kode_inventori']) ? $_POST['kode_inventori'] : '';
$kode_kategori_pelanggan = $_POST['kode_kategori_pelanggan'][$i]; // ALREADY CHECKED ISSET ABOVE...
$data = array(
'harga' => $harga_jual,
'diskon' => $diskon,
);
$this->db->where('kode_inventori',$kode_inventori);
$this->db->where('kode_kategori_pelanggan', $kode_kategori_pelanggan);
$this->db->update('harga_inventori', $data);
}
}
redirect("inventori");
I know basic PHP and all I know I've learned on google during the past years.
With that said, I'm developing a new website and I'm experimenting with clean URLs for SEO purposes and multi-regional languages compatibility.
So I have this array:
$list['requests']['en'] = array(
'index' => array(
0,
'subscribe',
'search'
),
'services' => array(
0,
'next' => array(
'service1',
'service2',
'service3'
),
'subscribe',
'search'
),
'service1' => array(
0,
'subscribe'
),
'service2' => array(
1,
'next' => array(
'view'
),
'jump' => 1,
'subscribe',
'search'
),
'service3' => array(
1,
'subscribe',
),
'view' => array(
2,
'subscribe'
),
'bad-request' => array(
0,
'subscribe'
)
);
Where $list['requests']['en'][$page][0] is the level of the page in the url and $list['requests']['en'][$page]['next'] is a list of valid pages that can follow.
That array is used to validate a URLs, so this is a valid one: www.website.com/services/service2/view
My real problem is that I want to loop throug that array and follow every page in the 'next' list so I have a function to create files like this: en/services.service1.view.php
I alreday created a chain of loops that do the job, but it's not generic. It's limited to the amount of loops I type in myself. This code for example, only runs throug 4 loops:
if(isset($list['requests'][$lang][$list_keys[$j]]['next'])){
for($l = 0; !empty($list['requests'][$lang][$list_keys[$j]]['next'][$l]) && $l < $for_max; $l++){
$next = $list['requests'][$lang][$list_keys[$j]]['next'][$l];
$file_next = $file[0].'.'.$next;
$file[] = $file_next;
if(isset($list['requests'][$lang][$next]['next'])){
for($n = 0; !empty($list['requests'][$lang][$next]['next'][$n]) && $n < $for_max; $n++){
$next_1 = $list['requests'][$lang][$next]['next'][$n];
$file_next_1 = $file_next.'.'.$next_1;
$file[] = $file_next_1;
if(isset($list['requests'][$lang][$next_1]['next'])){
for($o = 0; !empty($list['requests'][$lang][$next_1]['next'][$o]) && $o < $for_max; $o++){
$next_2 = $list['requests'][$lang][$next_1]['next'][$o];
$file_next_2 = $file_next_1.'.'.$next_2;
$file[] = $file_next_2;
if(isset($list['requests'][$lang][$next_2]['next'])){
for($p = 0; !empty($list['requests'][$lang][$next_2]['next'][$p]) && $p < $for_max; $p++){
$next_3 = $list['requests'][$lang][$next_2]['next'][$p];
$file_next_3 = $file_next_2.'.'.$next_3;
$file[] = $file_next_3;
}
}
}
}
}
}
}
}
This code saves every unique file name from the array chain.
The output would be something like this:
index.php
services.php
services.service1.php
services.service2.php
services.service2.view.php
services.service3.php
...
I've tried to make generic functions to do this but with no success.
Any ideas?
EDIT:
I just came up with an idea to simplify the code with an include. Nevermind my variables, the point here is to make a script that perceives the depth of loops itself.
The hole script for the purpose of context:
<?php
include 'includes/lists/languages.php';
include 'includes/lists/requests.php';
$for_max = 15;
// create requests files for each language
for($i = 0; isset($list['languages'][$i]) && $i < $for_max; $i++){
$lang = $list['languages'][$i];
$requests_keys = array_keys($list['requests'][$lang]);
echo 'LANG: '.$lang.'<br/>';
for($j = 0; isset($list['requests'][$lang][$requests_keys[$j]]) && $j < $for_max; $j++){
if($list['requests'][$lang][$requests_keys[$j]][0] == 0){
$file = array();
$file[] = $requests_keys[$j];
/* NEXT PART LOOP */
$loop = array();
$depth = 0;
$part = array();
$part['next'] = array();
$part['file'] = array();
// these vars are unique for the first loop, then it's generic
$part['next'][$depth-1] = $requests_keys[$j];
$part['file'][$depth-1] = $file[0];
// loop through every 'next' part if it exists in the current part
if(isset($list['requests'][$lang][ $part['next'][$depth-1] ]['next'])){
include '___construct_files.recursive.php';
}
/* CREATE REQUEST FILE */
for($k = 0; $k < count($file); $k++){
$path = 'includes/requests/'.$lang.'/'.$file[$k].'.php';
// string to insert in the file
include '___construct_files.string.php';
// processing
if(!file_exists($path)){
file_put_contents($path, $string);
echo '<br/># created - '.$path.'<br/>';
}else if(file_exists($path)){
echo '<br/># exists - '.$path.'<br/>';
}else{
echo '<br/># error - '.$path.'<br/>';
}
}
}
}
echo '<br/><br/>';
}
?>
The loop is included and verifies if it's needed to be included again in itself (___construct_files.recursive.php):
<?php
for($loop[$depth] = 0; !empty($list['requests'][$lang][ $part['next'][$depth-1] ]['next'][ $loop[$depth] ]) && $loop[$depth] < $for_max; $loop[$depth]++){
$part['next'][$depth] = $list['requests'][$lang][ $part['next'][$depth-1] ]['next'][ $loop[$depth] ];
$part['file'][$depth] = $part['file'][$depth-1].'.'.$part['next'][$depth];
$file[] = $part['file'][$depth];
// if next part is set, increase depth and include loop
if(isset($list['requests'][$lang][ $part['next'][$depth] ]['next'])){
$depth++;
include '___construct_files.recursive.php';
}
}
// decrease depth when higher depth loop ends so the current loop can resume
$depth--;
?>
I have this xml file named flight-itinerary.xml. A scaled-down version is shown below.
<itin line="1" dep="LOS" arr="ABV">
<flt>
<fltav>
<cb>1</cb>
<id>C</id>
<av>10</av>
<cur>NGN</cur>
<CurInf>2,0.01,0.01</CurInf>
<pri>15000.00</pri>
<tax>30800.00</tax>
<fav>1</fav>
<miles></miles>
<fid>11</fid>
<finf>0,0,1</finf>
<cb>2</cb>
<id>J</id>
<av>10</av>
<cur>NGN</cur>
<CurInf>2,0.01,0.01</CurInf>
<pri>13000.00</pri>
<tax>26110.00</tax>
<fav>1</fav>
<miles></miles>
<fid>12</fid>
<finf>0,0,0</finf>
</fltav>
</flt>
</itin>
The complete file contains 8 itinerary <itin> elements. The <fltav> element of each of the <itin> elements contains 11 of the <cb>1</cb> to <finf>0,0,1</finf> groups.
And below is the code I am using to process the file:
<?php
function processFlightsData()
{
$data = array();
$dom= new DOMDocument();
$dom->load('flight-itinerary.xml');
$classbands = $dom->getElementsByTagName('classbands')->item(0);
$bands = $classbands->getElementsByTagName('band');
$itineraries = $dom->getElementsByTagName('itin');
$counter = 0;
foreach($itineraries AS $itinerary)
{
$flt = $itinerary->getElementsByTagName('flt')->item(0);
$dep = $flt->getElementsByTagName('dep')->item(0)->nodeValue;
$arr = $flt->getElementsByTagName('arr')->item(0)->nodeValue;
$time_data = $flt->getElementsByTagName('time')->item(0);
$departure_day = $time_data->getElementsByTagName('ddaylcl')->item(0)->nodeValue;
$departure_time = $time_data->getElementsByTagName('dtimlcl')->item(0)->nodeValue;
$departure_date = $departure_day. ' '. $departure_time;
$arrival_day = $time_data->getElementsByTagName('adaylcl')->item(0)->nodeValue;
$arrival_time = $time_data->getElementsByTagName('atimlcl')->item(0)->nodeValue;
$arrival_date = $arrival_day. ' '. $arrival_time;
$flight_duration = $time_data->getElementsByTagName('duration')->item(0)->nodeValue;
$flt_det = $flt->getElementsByTagName('fltdet')->item(0);
$airline_id = $flt_det->getElementsByTagName('airid')->item(0)->nodeValue;
$flt_no = $flt_det->getElementsByTagName('fltno')->item(0)->nodeValue;
$flight_number = $airline_id. $flt_no;
$airline_type = $flt_det->getElementsByTagName('eqp')->item(0)->nodeValue;
$stops = $flt_det->getElementsByTagName('stp')->item(0)->nodeValue;
$av_data = $flt->getElementsByTagName('fltav')->item(0);
$cbs = iterator_to_array($av_data->getElementsByTagName('cb')); //11 entries
$ids = iterator_to_array($av_data->getElementsByTagName('id')); //ditto
$seats = iterator_to_array($av_data->getElementsByTagName('av')); //ditto
$curr = iterator_to_array($av_data->getElementsByTagName('cur')); //ditto
$price = iterator_to_array($av_data->getElementsByTagName('pri')); //ditto
$tax = iterator_to_array($av_data->getElementsByTagName('tax')); //ditto
$miles = iterator_to_array($av_data->getElementsByTagName('miles')); //ditto
$fid = iterator_to_array($av_data->getElementsByTagName('fid')); //ditto
$inner_counter = 0;
for($i = 0; $i < count($ids); $i++)
{
$data[$counter][$inner_counter] = array
(
'flight_number' => $flight_number,
'flight_duration' => $flight_duration,
'departure_date' => $departure_date,
'departure_time' => substr($departure_time, 0, 5),
'arrival_date' => $arrival_date,
'arrival_time' => substr($arrival_time, 0, 5),
'departure_airport_code' => $dep,
'departure_airport_location_name' => get_airport_data($dep, $data_key='location'),
'arrival_airport_code' => $arr,
'arrival_airport_location_name' => get_airport_data($arr, $data_key='location'),
'stops' => $stops,
'cabin_class' => $ids[$i]->nodeValue,
'ticket_class' => $ids[$i]->nodeValue,
'ticket_class_nicename' => formate_ticket_class_name($ids[$i]->nodeValue),
'available_seats' => $seats[$i]->nodeValue,
'currency' => $curr[$i]->nodeValue,
'price' => $price[$i]->nodeValue,
'tax' => $tax[$i]->nodeValue,
'miles' => $miles[$i]->nodeValue,
);
++$inner_counter;
}
return $data;
}
?>
Now, the outer loop iterates 8 times for each <itin> element, and during each iteration of the outer loop, the inner loop iterates 11 times, resulting in a total of 88 iterations per pass and causing serious performance issues. What I am looking for is a faster method of processing the file. Any helps will be greatly appreciated.
I don't think the loop is the bottle-neck. You should check your operations that are called within the loop, get_airport_data and formate_ticket_class_name.
Trying your code (without the auxiliary operations) on a number of itin elements takes less than a second, check this fiddle: http://phpfiddle.org/main/code/7fpi-b3ka (Note that the XML might not be similar to yours, I've guessed a lot of elements that were missing).
If there are operations that are called which increases the processing time substantially, try to call the operation with bulk data or cache the responses.
I have a problem. I want to put dates into an array but when I make print_r() I get only the last value from checkbox.
My code is:
$id = Input::get('id');
$aObjects = Input::get('aObjects');
$iCount = count($aObjects);
for($i=0; $i < $iCount; $i++)
{
$test = array ($aGoupes = array(
'idGroupe' => $id,
'idObject' => $aObjects[$i]
));
}
echo '<pre>';
print_r($test);
echo '</pre>';
The output is:
Array
(
[0] => Array
(
[idGroupe] => 6
[idObject] => 8
)
)
So the problem is that only the last value checked from checkbox is put in this table. Please help me!! Thnx
Your problem is that you're resetting $test each time.
Try this:
$id = Input::get('id');
$aObjects = Input::get('aObjects');
$iCount = count($aObjects);
$test = array();
for ($i = 0; $i < $iCount; $i++) {
$test[] = array (
'idGroupe' => $id,
'idObject' => $aObjects[$i]
);
}
echo '<pre>';
print_r($test);
echo '</pre>';
I'm not too sure what your code is supposed to do, but the idGroupe will always be the same in each array, as you're setting it to $id which is never changed. That may well be correct, though.