PHP - Dealing With Large Json Responses
I am using Guzzle as a HTTP client, and the following script results in the following error: $response = $this->httpClient->request('GET', "http://$this->host:$this->port/query", ['query' => $data]); $body = $response->getBody(); $rs=json_decode($body, true); Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 136956008 bytes) in /var/www/vendor/guzzlehttp/psr7/src/Stream.php on line 80 What are the work arounds? Instead of trying to convert it into an array all at once, how can I do so in pieces? I know the expected format so it seems I will need to read just the appropriate amount of bytes and then decode parts at a time. Seems like a pain. Are there any classes designed to do so, or can any of the following Guzzle built in methods be used? Thanks Guzzle Response methods: __construct getStatusCode getReasonPhrase withStatus getProtocolVersion withProtocolVersion getHeaders hasHeader getHeader getHeaderLine withHeader withAddedHeader withoutHeader getBody withBodyGuzzle Body methods: __construct __destruct __toString getContents close detach getSize isReadable isWritable isSeekable eof tell rewind seek read write getMetadataSimilar TutorialsThis topic has been moved to JavaScript Help. http://www.phpfreaks.com/forums/index.php?topic=355144.0 Hello All, running into a situation that I have not seen before. I have been seeing in multiple areas of my application that the response received from the server has 2 JSON responses in it. Here is a sample function: private function getCatalogItems(){ $start = ($_REQUEST["start"] == null)? 0 : $_REQUEST["start"]; $count = ($_REQUEST["limit"] == null)? 20 : $_REQUEST["limit"]; $q = "SELECT c.`id`, c.`catalog_number`, c.`long_description`, CONCAT(c.`catalog_number`, ' - ', c.`long_description`) AS `display` FROM catalog c"; if(!empty($_REQUEST['query'])){ $q .= " WHERE c.`catalog_number` LIKE '%".$_POST['query']."%'"; } $q .= " ORDER BY c.`catalog_number` ASC LIMIT ".$start.",".$count; $rs = $this->db->get_results($q); $total = $this->db->num_rows; $buff = '{"total":"'.$total.'","data":'.json_encode($rs).'}'; $this->c->returnJSON($buff); } The "returnJSON" function looks like this. public function returnJSON($json){ $contentType = "application/json; charset=utf-8"; header("Content-Type: {$contentType}"); header("Content-Size: " . strlen($json)); echo $json; } As you can see this simply sets the headers of the response. It has been a real head scratcher. Anyone come across something like this before? I have the following tables: department id course id department_id CASCADE DELETE student id student_courses course_id CASCADE DELETE student_id CASCADE DELETEI also have the following REST API endpoints: DELETE department/123 (deletes targeted department and associated courses as well as the list of students in the course) DELETE course/321 (deletes targeted course as well as the list of students in the course) DELETE student/111 (deletes targeted student as well as the list of students in the course)The user should be informed before deleting a given record if that record will affect other tables. For instance, if deleting a department which has some courses or deleting a student which belows to a course. One option is to respond to DELETE department/123 with 400 {recordUsed: {courses:[bla, bla], student_courses:[bla, bla]}} if used. For this option, the client would then prompt the user of the implications and if desired repeat the request but include a "force" parameter of TRUE in the request which will delete the record regardless of being used. Another option is to add some new endpoints which will return the resources which are associated with the to be deleted entity. If empty, a DELETE request would automatically be made and if not empty the user will first be prompted whether the DELETE request should be made and the server would delete the record(s) regardless of being used. GET department/utilized/123 GET course/utilized/321 GET student/utilized/111Any thoughts on which approach should be used? Or maybe some other strategy? Thanks How to make a form using HTML/PHP with conditional responses based on zip code? What I want to do exactly... zip codes 91900-92600 go to URL www.example.com after submit. All others go to URL www.example.com/page after submit. Any help would be much appreciated. Hi everyone... I would like to implement a questionnaire/survey system that has only two Answers (Yes /No). Basically, this questionnaire system will be widely used on Mobile Phones. It will be looking something like this below: http://awardwinningfjords.com/2009/06/16/iphone-style-checkboxes.html Lets say a user selects a response as No (Using the above slider button for a question). That response should be recorded in the database with User Details + Time Stamp. Also, I would like to generate a report for each question (Responses of Multiple Users) and a report at a User Level for the entire questionnaire/survey (s). Can some one guide me the fastest & easiest way to achieve this? I'm a new learner of PHP. Regards Sandeep So if I have this code (while working on my local machine )... Code: [Select] for ($i=1; $i<=15; $i++) { if ($timelimit == $i) { ${"time".$i}="selected='selected'"; } } <select name="timelimit"> <option value="1" <?php echo $time1;?>>1</option> <option value="2" <?php echo $time2;?>>2</option> <option value="3" <?php echo $time3;?>>3</option> <option value="4" <?php echo $time4;?>>4</option> <option value="5" <?php echo $time5;?>>5</option> <option value="6" <?php echo $time6;?>>6</option> <option value="7" <?php echo $time7;?>>7</option> <option value="8" <?php echo $time8;?>>8</option> <option value="9" <?php echo $time9;?>>9</option> <option value="10" <?php echo $time10;?>>10</option> <option value="11" <?php echo $time11;?>>11</option> <option value="12" <?php echo $time12;?>>12</option> <option value="13" <?php echo $time13;?>>13</option> <option value="14" <?php echo $time14;?>>14</option> <option value="15" <?php echo $time15;?>>15</option> </select> When I view the select menu in the browser, all but one of the options says "Notice: Undefined variable: time1 in C:\wamp\www\yyyyyy\create.php on line 112". It doesn't say this if I publish everything to the internet. So the question is, should I put code in to eliminate those Notices, or does it not matter. In other words, if I add this snippet below to declare all the other variables, it eliminates all the Notices. But is this necessary/good practice to do?.. Code: [Select] for ($i=1; $i<=15; $i++) { ${"time".$i}=""; } Hi I found a tutorial on dealing with databases he http://www.phpfreaks.com/tutorial/php-basic-database-handling It's great, except that I need it to do more than just a name; I need first, last, dob and email. I have it figured out how to order, insert and delete, but can someone help me figure out how to do the updating? The tutorial creates an array called cname and loops through it to do the update, but when I add more fields, it only holds the last fileds (emails in this case) I just need to be able to update all the fields for each user instead of just the name. Sounds easy but I've gotten nowhere Everything I have tried is posted below. Any help? Thanks Code: [Select] // INSERT: if we have a name to add... if($_POST['fname']) { // little bit of cleaning... $fname = mysql_real_escape_string($_POST['fname']); $lname = mysql_real_escape_string($_POST['lname']); $dob = mysql_real_escape_string($_POST['dob']); $email = mysql_real_escape_string($_POST['email']); // check for previous entry $sql_check = "SELECT id FROM test WHERE fname='$fname' AND lname='$lname'"; $res_check = mysql_query($sql_check, $conn) or trigger_error("SQL", E_USER_ERROR); if (mysql_num_rows($res_check) == 1) { while ($row = mysql_fetch_assoc($res_check)) { $id = $row['id']; } // update $sql = "UPDATE test SET Current=1 WHERE id='$id'"; $res = mysql_query($sql, $conn) or trigger_error("SQL", E_USER_ERROR); } else { // insert new name into table $sql = "INSERT INTO test (id, fname, lname, dob, email) VALUES ('', '$fname', '$lname', '$dob', '$email')"; $result = mysql_query($sql, $conn) or trigger_error("SQL", E_USER_ERROR); } } // end if // UPDATE: if we have name(s) to change... if($_POST['udata']) { /* // for each name to change... foreach ($_POST['udata'] as $input => $v) { echo "$input = $v<br />"; $sql = "UPDATE test SET "; foreach ($v as $id => $value) { echo "$id = $value<br />"; } $sql .= "WHERE ..."; } echo "<hr />$sql<hr />"; print_r($_POST['udata']); */ for ($i = 0; $i < count($_POST['udata']['fname']); $i++) { $fname = $_POST['udata']['fname'][$i]; echo "$i = $fname<br />"; } /* foreach($_POST['cname'] as $cid => $cname) { // little bit of cleaning... $id = mysql_real_escape_string($cid); $fname = mysql_real_escape_string($cname); $lname = mysql_real_escape_string($cname); $dob = mysql_real_escape_string($cname); $email = mysql_real_escape_string($cname); // update name in the table $sql = "UPDATE test SET fname = '$fname', lname='$lname', dob='$dob', email='$email' WHERE id = '$id'"; $result = mysql_query($sql, $conn) or trigger_error("SQL", E_USER_ERROR); } // end foreach */ } // end if // DELETE: if we have a name to delete... if($_GET['id']) { // little bit of cleaning... $id = mysql_real_escape_string($_GET['id']); // delete name from table $sql = "UPDATE test SET Current=0 WHERE id= '$id'"; $result = mysql_query($sql, $conn) or trigger_error("SQL", E_USER_ERROR); } // end if // ORDERBY: if one of the links was clicked.. if ($_GET['orderby']) { // make an aray of allowed names $allowed = array('id','fname', 'lname', 'dob', 'email'); // bit of cleaning... $order = mysql_real_escape_string($_GET['orderby']); // is it a valid column name? yes: use it. no: default to 'id' $order = (in_array($order, $allowed))? $order : "id"; // if no link clicked, default to 'id' } else { $order = "id"; } // end else // SELECT: get the list of names from database $sql = "SELECT id, fname, lname, dob, email FROM test WHERE Current=1 ORDER BY $order"; //$result = mysql_query($sql, $conn) or trigger_error("SQL", E_USER_ERROR); $result = mysql_query($sql, $conn) or die(mysql_error()); /**** end deal with the database ****/ /**** list everything out ****/ // list columns echo "<form action = '{$_SERVER['PHP_SELF']}' method = 'post'>\r\n"; echo "<table border = '1'>\r\n"; echo "<tr>\r\n"; echo "<td><a href = '{$_SERVER['PHP_SELF']}?orderby=id'>id</a></td>\r\n"; echo "<td><a href = '{$_SERVER['PHP_SELF']}?orderby=fname'>fname</a></td>\r\n"; echo "<td><a href = '{$_SERVER['PHP_SELF']}?orderby=lname'>lname</a></td>\r\n"; echo "<td><a href = '{$_SERVER['PHP_SELF']}?orderby=dob'>dob</a></td>\r\n"; echo "<td><a href = '{$_SERVER['PHP_SELF']}?orderby=email'>email</a></td>\r\n"; echo "<td>delete</td>\r\n"; echo "</tr>\r\n"; // loop through list of names while ($list = mysql_fetch_assoc($result)) { echo "<tr>\r\n"; echo "<td>{$list['id']}</td>\r\n"; echo "<td><input type = 'text' name = 'udata[fname][{$list['id']}]' value = '{$list['fname']}' />\r\n"; echo "<td><input type = 'text' name = 'udata[lname][{$list['id']}]' value = '{$list['lname']}' />\r\n"; echo "<td><input type = 'text' name = 'udata[dob][{$list['id']}]' value = '{$list['dob']}' />\r\n"; echo "<td><input type = 'text' name = 'udata[email][{$list['id']}]' value = '{$list['email']}' />\r\n"; echo "<td><a href = '{$_SERVER['PHP_SELF']}?id={$list['id']}'>delete</a></td>\r\n"; echo "</tr>\r\n"; } // end while // list input box for adding new entry echo "<tr>"; echo "<td bgcolor = 'gray'></td>\r\n"; echo "<td><input type = 'text' name = 'fname' /></td>\r\n"; echo "<td><input type = 'text' name = 'lname' /></td>\r\n"; echo "<td><input type = 'text' name = 'dob' /></td>\r\n"; echo "<td><input type = 'text' name = 'email' /></td>\r\n"; echo "<td bgcolor = 'gray'></td>\r\n"; echo "</tr><tr>\r\n"; echo "<td></td>\r\n"; echo "<td align = 'center'><input type = 'submit' value = 'submit' /></td>\r\n"; echo "<td></td>\r\n"; echo "</tr></table></form>\r\n"; /**** end list everything out ****/ <?php if ($beyondportal % 26 == 0 || $beyondportal == 0){ ?> MY CONTENT <?php } ; ?> This code compares my variable $beyondportal and if it is a multiple of 26 counting up from 0, it prints my content. This is great but sometimes the number comes up a negative that is a multiple counting down from 0 like -26, -52, etc.. if I could do the opposite of a modulus I would think it would work but I'm not sure how to in php. any suggestions? I am using file_get_contents to get file off the internet for further processing but somtetimes there is error fetching that file off the web in which case it would be nice to try to reload it again but I am not sure what would be best way to do it? How can I jump back on error? I guess there would have to be some jump to label condition, but how do I implement this? This topic has been moved to Miscellaneous. http://www.phpfreaks.com/forums/index.php?topic=313673.0 I have a mysql table like so ID OrderID Name Image CatalogID 1 1 test pic1.jpg 1 2 2 test2 pic2.jpg 1 3 1 test3 pic3.jpg 2 4 1 test4 pic4.jpg 3 5 1 test5 pic5.jpg 4 6 2 test6 pic6.jpg 4 7 3 test7 pic7.jpg 4 etc etc (1) I want to use up and down buttons so that the OrderID can be modified to reflect the users order preference, how would I code it so it changes all the OrderID values in the table as necessary to produce the correct order using the buttons, the only affected items each time would be the ones in the same CatalogID group. (2) How do I re number the OrderID when an item is deleted so that it moves all the items below it in the same CatalogID group up one value to still reflect the correct order and not skip OrderID values. This topic has been moved to Application Design. http://www.phpfreaks.com/forums/index.php?topic=347191.0 Hi All, I've a loop which creates an array as follows: $product_table[] = ['SKU' => $sku, 'Label' => $attribute_name, 'Value' => $term_obj->name ]; I'm then grouping the data by SKU code: #group the products by SKU $group_products = array(); foreach ($product_table as $element) : $group_products[$element['SKU']][] = $element; endforeach; Finally, I output the data: #output the data foreach ($group_products as $itemName => $rows) : echo '<tr>'; #echo '<td>', $element['SKU'], '</td>'; $i=0; foreach ($rows as $row) : $i++; #echo '<td>'. $row["SKU"]. '</td><td>'. $row["Label"]. '</td><td>'. $row["Value"]. '</td>'; if ($i == 1): echo '<td>'. $row["SKU"]. '</td><td>'. $row["Value"]. '</td>'; else: echo '<td>'. $row["Value"]. '</td>'; endif; #echo '<td>'. $row["Value"]. '</td>'; endforeach; echo '</tr>'; endforeach; ?> And looks like: Product code System Pack Quantity XT1CWH System 1 1 x 3m XT2CWH System 2 1 x 3m XT3CWH System 3 1 x 3m
This works perfectly fine. However, some products share the same SKU and therefore it causes an issue, like the below: Product code System Pack Quantity XT1CLWH System 1 8 x 3m System 2 8 x 3m System 3 8 x 3m Is there a way I can avoid this, so if perhaps creates the new row but shows the same SKU code? Many thanks How can I check if the text entered in a textarea field equals the text I have stored in a mysql table? Code: [Select] $submitted_description = trim(mysqli_real_escape_string($db,$_POST['description'])); $query = "SELECT description FROM pets"; $result = $db->query($query); $row = $result->fetch_assoc(); $sql_description = $row['description']; Here's what they echo: Quote submitted_description: Testing...\r\n\r\n1\r\n\r\n2\r\n\r\n3 sql_description: Testing... 1 2 3 I tried adding the following to get rid of \r\n from $submitted_description but they both still don't equal but echo the same text. Code: [Select] $submitted_description = str_replace(array("\r","\n",'\r','\n'),' ', $submitted_description); They following code only matches when no spaces are entered in the textarea field. Code: [Select] if($submitted_description == $sql_description) { echo "Match!"; } else { echo "Don't Match!"; } How can this be done? I also tried adding nl2br() to both variables but that didn't work either. I'm dealing with data that WordPress creates for Users when they register and subscribe, and to use it for other purposes, I have to wrap my head around serialized data. It's not sinking in well. The below code works well for what I wanted at the time. It takes into consideration where the Subscriber lives (divided up into five areas) and counts how many I have. That is noted by wp_s2member_custom_fields and ANY s2member_level. There are three levels, and I need to actually note how many there are at each Member level. There is another line of data for each user_id meta_key = wp_capabilities meta_value = a:1:{s:15:"s2member_level2";s:1:"1";} Code: [Select] $custom = 'SELECT * FROM wp_usermeta WHERE meta_key = "wp_s2member_custom_fields" AND user_id IN (SELECT user_id FROM wp_usermeta WHERE meta_value LIKE "%s2member_level%")'; $c_results = mysql_query($custom); $region = array(); while($line = mysql_fetch_assoc($c_results)) { $meta_value = unserialize($line['meta_value']); $region[$meta_value['county']]++; }; foreach ($region as $key => $value) { echo "Region $key: $value members<br>"; } Hi I am new to PHP / mySQL although not to programming and am trying to work out how to deal with the following situation: I have a form for a user to add a book to a database, along with the genres that the book belongs to. Each book can have a number of genres . There are 3 tables, books, genres and bg_xref in the following formats table: books fields: id, title, author, date published table: genres fields: id, genre table: bg_xref fields: id, book_id, genre_id I am now trying to build the form that allows the user to update an existing entry for a book. the genres are selectable from a multi-selection list which I am populating from all the possible values in the genres table. Currently I have the following database selections: mysql_select_db($database_conn, $conn1); $query_rs_getBooks = "SELECT books.id, books.title, books.author, bg_xref.genre_id FROM books LEFT JOIN bg_xref ON books.id = bg_xref.book_id"; $rs_getBooks = mysql_query($query_rs_getBooks, $conn1) or die(mysql_error()); $row_rs_getBooks = mysql_fetch_assoc($rs_getBooks); mysql_select_db($database_conn, $conn1); $query_rs_getGenre = "SELECT * FROM book_genres ORDER BY genre ASC"; $rs_getGenre = mysql_query($query_rs_getGenre, $conn1) or die(mysql_error()); $row_rs_getGenre = mysql_fetch_assoc($rs_getGenre); I have then created a form that the user uses to update the book, but am trying to work out how to prepopulate the selection list based on teh results of the join e.g. <form method="POST" action="<?php echo $editFormAction; ?>" name="update_book"> <fieldset class="full"> <legend>Enter book details below</legend> <table> <tr><td>Title: </td><td><input type="text" size="50" value="<?php echo htmlentities($row_rs_getBooks['title'], ENT_COMPAT, 'iso-8859-1'); ?>" name="title"></td></tr> <tr><td>Author: </td><td><input type="text" size="30" value="<?php echo htmlentities($row_rs_getBooks['author'], ENT_COMPAT, 'iso-8859-1'); ?>" name="author_surname"></td></tr> <tr><td>Genre(s)</td><td><select name="genre" multiple size="4"> <?php do { ?> <?php if (($row_rs_getBooks['genre_id']) != $row_rs_getGenre['id']) { ?> <option value="<?php echo $row_rs_getGenre['id']?>"><?php echo $row_rs_getGenre['description']?></option> <?php } else { ?> <option value="<?php echo $row_rs_getGenre['id']?>" selected><?php echo $row_rs_getGenre['description']?></option> <?php } } while ($row_rs_getGenre = mysql_fetch_assoc($rs_getGenre)); $rows = mysql_num_rows($rs_getGenre); if($rows > 0) { mysql_data_seek($rs_getGenre, 0); $row_rs_getGenre = mysql_fetch_assoc($rs_getGenre); } ?> </select></td></tr> </table> </fieldset> <input type="hidden" name="id" value="<?php echo $row_rs_getBooks['id']; ?>"> <input type="submit" value="Update book details"> <input type="hidden" name="MM_update" value="update_book"> </form> Book id = 1 is classified against genres 1 and 5, so my SQL query returns 2 rows: book.id = 1 + bg_xref.genre_id = 1 book.id = 1 + bg_xref.genre_id = 5 At the moment the form is generated for the first row of the results set with <tr><td>Genre(s)</td><td><select name="genre" multiple size="4"> <option value="5">Humour</option> <option value="4">Non Fiction</option> <option value="2">Novel</option> <option value="3">Picture Books</option> <option value="1" selected>Poetry</option> with a second entry in the results set for book 1 and genre 5. What I need to end up with is a second occurence of book 1 with both genres 1 and 5 set in the form. Thanks Stuart MySQL returns an error in the form of a number, a state, and a message. Without parsing the message you will not be able to determine what column is duplicated.While parsing the error code, I have also notice that, if you have multiple unique fields as duplicates, only the first duplicate encountered will be returned in the message. This is not very helpful to the end user.
Is there any way to parse the returned error code to reflect all duplicate fields, please see sample code below?
$error=array(); $sql = 'INSERT INTO staff(username, email, phone) VALUES (?, ?, ?)'; $stmt = $conn->stmt_init(); $stmt = $conn->prepare($sql); // bind parameters and insert the details into the database $stmt->bind_param('sss', $username, $email, $phone); $stmt->execute(); if ($stmt->errno == 1062) { $errors[] = "One of the fields is already in use."; } Man, I'm having a rough week with questions--if you're following at home. Basically matching a Coach's first and last name to another table, which if matched will yield information about that coach's team. Code: [Select] // or get user by username $current_user = wp_get_current_user(); $current_first = $current_user->user_firstname; $current_last = $current_user->user_lastname; $current_id = $current_user->ID; echo '<div class="contact_form">'; echo $current_first . ' ' . $current_last .' :: '; $query = "SELECT * FROM schools WHERE coachFirst='".$current_first."' AND coachLast='".$current_last."'"; $result = mysql_query ($query); if(!$result) { echo 'There is not a match for your name.'; } else { while($school= mysql_fetch_array($result)) { echo $school['school'] . ' ' . $school['id']; include(ABSPATH ."wp-content/plugins/my-team/form.php"); } echo '</div>'; echo '<div class="roster">'; include(ABSPATH ."wp-content/plugins/my-team/roster.php"); echo '</div>'; } Hi guys, I am currently receiving a large text file ( > 500mb), once per week which I have been manually splitting then processing to obtain the required CSV files. However, this is taking in the region of 2 to 3 hours. Very soon, these files will be sent daily and I really dont have the time to split and process this everyday I have been playing for a while to try and parse everything properly/automatically with fopen, feof and fgets ( and other 'f' options), but the script never seems to read the file all the way to the end - I assume this is due to memory usage. The data received in the file follows a strict pattern throughout the file which is: Code: [Select] BSNY990141112271112270100000 POO2C35 122354000 DMUS 075 O BX NTY LOLANCSTR 1132 11322 TB LIMORCMSJ 1135 00000000 LICRNFNJN 1140 00000000 H LICRNF 1141H1142H 11421142 T LISDAL 1147H1148H 11481148 T LIARNSIDE 1152H1153 11531153 T LIGOVS 1158 1159 11581159 T LIKTBK 1202 1202H 12021202 T LICARK 1206 1207 12061207 T LIULVRSTN 1214H1215H 12151215 T LIDALTON 1223 1223H 12231223 T LIDALTONJ 1225 00000000 LIROOSE 1229 1229H 12291229 T 2 LTBAROW 1237 12391 TF That is just one record of informaton (1 of around 140,000 records), each record has no fixed amount of lines but each line in each record is fixed to 80 characters and all lines in each record need to have the same unique 'id', at present, Im using an md5 hash of microtime. The first line of every record starts with 'BS' and the last line of each record starts with 'LT' terminating with 'TF'. All the other stuff between also follows a certain pattern of which I can break down effectively. The record above show one train service schedule, hence why each line in each record needs the same unique id. Anyone got any ideas on how I could process such a file effectively?? Many thanks Dave Hi all So... I am creating an import script for putting contacts into a database. The script we had worked ok for 500kb / 20k row CSV files, but anything much bigger than that and it started to run into the max execution limit. Rather than alter this I wish to create something that will run in the background and work as efficiently as possible. So basically the CSV file is uploaded, then you choose if the duplicates should be ignored / overwritten, and you match up the fields in the CSV (by the first line being a field title row), to the fields in the database. The field for the email address is singled out as this is to be checked for duplicates that already exist in the system. It then saves these values, along with the filename, and puts it all into an import queue table, which is processed by a CRON job. Each batch of the CRON job will look in the queue, find the first import that is incomplete, then start work on that file from where it left off last. When the batch is complete it will update the row to give a pointer in the file for the next batch, and update how many contacts were imported / how many duplicates there were So far so good, but when checking for duplicity it is massively slowing down the script. I can run 1000 lines of the file in 0.04 seconds without checking, but with checking that increases to 14-15 seconds, and gets longer the more contacts are in the db. For every line it tries to import its doing a SELECT query on the contact table, and although I am not doing SELECT * its still adding up to a lot of DB activity. One thought was to load every email address in the contacts table into an array before hand, but this table could be massive so thats likely to be just as inefficient. Any ideas on optimising this process? |