php - why post request is taking too much time? - php

Using php-mysql, I am fetching data, pushing it into an array. An array consists of 486 records. It's an associative array with 7 column for each record.
When there is a GET request, it works fine. Getting data, binding it to table, chart and dropdown. Everything works fine.
I need to populate dropdown based on selection of another dropdown. And in that case I am making a POST request. And searching in the same array of 486 records.
$temp = Array();
$teamSelectData = Array();
foreach ($allBookingsData as $key => $value) {
if($value['PDG'] == $passedPDG){
array_push($temp, $value["Team_Name"]);
}
}
$tempTeam = array_iunique($temp);
foreach ($tempTeam as $key => $value) {
array_push($teamSelectData, Array(
'name' => $value,
'value' => $key,
'title' => $value
));
}
$returnArray['TeamSelectData'] = $teamSelectData;
// get unique items from array
function array_iunique($array) {
$upper = array_map('strtolower', $array);
return array_intersect_key($array, array_unique($upper));
}
I couldn't able to figure out why is it taking too much time to execute. The comparison if($value['PDG'] == $passedPDG) is the issue or the function array_iunique. And the same way I am populating dropdown for PDG. Based on a selection of PDG, I need to fill dropdown of Team.
How to make this function efficient ?

Related

Populate selection box based on query

I have a form (queform plugin on wordpress) that I am trying to populate based on some table information.
Initially I had a shortcode plugged in which is running the query and puts the results in a comma separated list - However, when using the drop down all of the table tags were being displayed, so I thought that I need to query in place of the shortcode.
I think I am close, but missing something. If I use concat the drop down displays the number 1. If I use group_concat the drop down displays the number 15 (which is how many rows there are on the table).
<?php
add_action('quform_pre_display_7', function (Quform_Form $form) {
$element = $form->getElement('quform_7_3');
if ($element instanceof Quform_Element_Multi) {
$options = array();
global $wpdb;
$results = $wpdb->query("SELECT CONCAT(Name) FROM `NAME_TABLE`");
$results = array_map('trim', explode(',', $results));
foreach ($results as $index => $option) {
$options[] = array('label' => $option, 'value' => $option, 'id' => $index + 1);
}
$element->setOptions($options);
}
});
I figured out all that was needed was to change it from "query" to "get_var" and it set the menu options.

Laravel 8.X validation on attributes that contain a certain string

I'm trying to make an application that saves grocery lists and retrieves them from a database. In the request, the values get passed along in JSON format:
"item:47" => "{"id":47,"name":"Beer","brand":"Jupiler","weight":null,"note":"Six pack;_bottles","order_id":15}"
"item:88" => "{"id":88,"name":"Tomatoes","brand":null,"weight":null,"note":null,"order_id":15}"
"item:110" => "{"id":110,"name":"Gura_Bread","brand":null,"weight":0.3,"note":null,"order_id":15}"
"item:-1" => "{"id":-1,"name":"Beef_Jerky","brand":"Canadon","weight":0.5,"notes":"Spicy_Ones"}"
New items are marked with a descending negative id, while existing items retain their id from the DB
When this arrives in the back-end of the laravel application, I would like to validate the JSON string with Laravel's validate(). The only problem is that the amount of items that can be passed varies in amount. Sometimes it can be one item, while other times it could be 10 items instead.
Is there a way to add this JSON rule that could only trigger when it notices that there's a certain string in one or multiple attributes of an incoming request? In this case, it should trigger when it sees that the string item:.
For context, here are the parameters of an example request.
"picking_method" => "Cheapest"
"item:47" => "{"id":47,"name":"Beer","brand":"Jupiler","weight":null,"note":"Six pack;_bottles","order_id":15}"
"item:88" => "{"id":88,"name":"Tomatoes","brand":null,"weight":null,"note":null,"order_id":15}"
"item:110" => "{"id":110,"name":"Gura_Bread","brand":null,"weight":0.3,"note":null,"order_id":15}"
"item:-1" => "{"id":-1,"name":"Beef_Jerky","brand":"Canadon","weight":0.5,"notes":"Spicy_Ones"}"
"store_street" => "Haag Pines"
"store_number" => "1855"
"store_postal_code" => "82792-01"
"store_city" => "Port Muhammadhaven"
"store_country" => "Guernsey"
"delivery_street" => "Rosenbaum Island"
"delivery_number" => "4974"
"delivery_postal_code" => "61093"
"delivery_city" => "East Carlee"
"delivery_country" => "Slovenia"
"delivery_notes" => null
"medical_notes" => null
After experimenting some more, I came up with this solution.
In order for this method to work, you'll need to have a substring that is the same across all the attributes that you want to check.
Before performing any validation at all, I decided to collect all the attributes that I want to check into an array with a foreach loop. This is where the substring part is important because it will be used to decide which attributes will be collected:
$item_attributes = [];
foreach ($request->post() as $key => $value) {
if (str_contains($key, 'item:')) {
array_push($item_attributes, $key);
}
}
After that, I looped over the $item_attributes array and used it to make a rules array, where every value in the $item_attributes is used as a key. As value, I added the json rule.
$rules = [];
foreach ($item_attributes as $attribute) {
$rules[$attribute] = "json";
}
After that, I validate the data and returned it, so it can be used in the main function of my code:
return $request->validate($rules);
When combined, this will result into the following method:
function validateItems(Request $request)
{
$item_attributes = [];
foreach ($request->post() as $key => $value) {
if (str_contains($key, 'item:')) {
array_push($item_attributes, $key);
}
}
$rules = [];
foreach ($item_attributes as $attribute) {
$rules[$attribute] = "json";
}
return $request->validate($rules);
}

Find which keys of separate arrays intersect using a function

Ok so I have two arrays, one is an input array full of data like :
$array1 = ["_token" => "62d46d4h6dfh841df8h", "sku62" => "3e", "name62" => "meh", "sku61" => "3e", "name61" => "mah", "sku64" => "3e", "name64" => "moh"]
The other holds simply id's: $array2 = [64, 74, 61]
edit for clarity: $array1 is a snippet of input from a post request i.e. $array1 = $request->all(); The numbers present within the keys of this array are unique Id's appended on form generation to distinguish between rows with multiple form elements.
Each row has an "update" checkbox also with an appended unique id. When ticked this id shows up in the request e.g. update64.
$array2 was populated by doing a foreach through the request, identifying the update string and isolating the id:
foreach ($array1 as $id => $value) {
$idInt = filter_var($id, FILTER_SANITIZE_NUMBER_INT);
$str = preg_replace('/[0-9]+/', '', $id);
if ($str === "update") {
array_push($array2, $idInt);
}
}
I want a solution that returns the elements from $array1 that have the appended ids found in $array2.
My own attempt looks like this:
$relevant_keys = function($key1, $key2) {
return ((preg_replace('/[0-9]+/', '', $key1) === $key2)) ? 1 : -1;
};
$filtered = array_intersect_ukey($array1, array_flip($array2), $relevant_keys);
However $filtered is returning empty and if I dd($key2) within the function it's not even returning an element from $array2, I get something from $array1 instead so this has left me confused.
Would appreciate any help.
Here's the solution to the exact problem you posted:
$filtered = [];
foreach ($array1 as $key => $value)
{
if ( ! preg_match('/(\d+)$/', $key, $matches)) continue;
if ( ! isset($matches[1]) || ! in_array($matches[1], $array2)) continue;
$filtered[$key] = $value;
}
But I'm not sure you're approaching this correctly. That input looks suspicious.
Are you sure there's no better way to format the request?
I have a few important insights to share based on your coding attempt.
array_intersect_ukey() should be the perfect function call for his task, but alas, it is not. I'll tell you why.
array_intersect_ukey() suffers in the same way as array_intersect_uassoc() and array_uintersect_uassoc() because the internal algorithm will stop looking for additional qualifying keys after it encounters its first one. I first came upon this reality here.
Also, the way that you've declared and used the custom function arguments ($key1 and $key2) indicates that you believe $key1 always relates to the first nominated array and $key2 always relates to the second nominated array. This is not true and I have seen many developers with this same false impression. The truth is that under the hood, the two parameters fed into the custom function may come from either array.
For the reasons in #1, I'll recommend that you shift your focus to array_filter(). By establishing a lookup array containing whitelisted keys and filtering on keys, you can swiftly filter your data. Inside the callback, I am using trim() to remove the letters before the id number at the end. This is just one way of isolating the whole number at the end of each key.
Code: (Demo)
$lookup = array_flip($array2);
var_export(
array_filter(
$array1,
fn($key) => isset($lookup[ltrim($key, 'a..z')]),
ARRAY_FILTER_USE_KEY
)
);
Output:
array (
'sku61' => '3e',
'name61' => 'mah',
'sku64' => '3e',
'name64' => 'moh',
)

Update database field with array in CodeIgniter

Again I find myself at the mercy of the stackoverflow community!
I've gone over to use CodeIgniter for my PHP projects and it's been a breeze so far, hoever I've gotten stuck trying to update a database field with some post data.
My array is the usual: array(name => value, name => value, name => value);
which again is populated from the submitted $_POST data.
Similarly to the array, I have a database table with 2 fields: setting and value, where the names under setting corresponds to the array keys and value to the array keys' value.
(Did I explain that right?)
Nonetheless, I've been trying for a little while now to get this to work as it should, but, I'm really just waving my hands around in the dark.
I hope some of you bright minds out there can help me with this annoying issue!
Edit:
Thanks to everyone who replied! I managed to produce the result that I wanted with the following code:
foreach ($form_data as $key => $val)
{
$this->db->where ('setting', $key);
$this->db->set ('value', $val);
$this->db->update ('recruitment');
}
Now, I tried following up with this by adding:
if ($this->db->affected_rows() >= '1') { return true; }
return false;
To my model, and
if ($this->RecruitmentSettings->Update($form_data) == TRUE)
{
redirect('recruitment/success');
}
to my controller, but it's not working as expected at all. Any ideas what I'm doing wrong?
There are a lot of questions here. Do you already have values in the database and you want to update them? Or do you want to put in new data every time? The answer depends on that.
What you want is the insert_batch() or update_batch() methods of the active record class (if that's what you're using for the db).
foreach($post_array as $key => $value)
{
$settings[] = array(
'setting' => $key,
'value' => $value
);
}
$this->db->insert_batch('your_db_table', $settings);
OR, for updates:
$this->db->update_batch('your_db_table', $settings, 'setting');
You could do a query to check for settings and do insert_batch or update_batch depending on if there are results. If you wanted to insert every time, you could delete the rows in the table before you do the insert. I wouldn't do that without a transaction, however.
So you want to store the array data in the database? You could do this
Model
foreach ($data as $key => $item)
{
$this->db->set ('setting', $key);
$this->db->set ('value', $item);
$this->db->insert ('table_name');
}
return ($this->db->affected_rows() > 0);
Controller
if ($this->RecruitmentSettings->Update($form_data))
{
redirect('recruitment/success');
}
else
{
echo "error";
}

Converting a multidimensional array into a single dimensional one

If from a function I am returned a multidimensional array like this..
array(0 => array('a' => 5), 1 => array('a' => 8))
But I just really need the contents of the key 'a' what is the best way for me to convert.
Current I have been doing something like..
$new_array = array();
foreach ($multi_array AS $row) {
$new_array[] = $row['a']
}
without foreach:
$array = array(0 => array('a' => 1), 1 => array('a' => 8));
$new_array = array_reduce($array, function ($result, $current) {$result[]=current($current); return $result;}, array());
If that is all your requirements are, I think that is the best way. Anything else will have the same processing. Even after looking through the Array functions, I would say that this would be the best way. You can, however, make it a function to make it a bit more versatile:
$array = array(0 => array('a' => 1), 1 => array('a' => 8));
$new_array = flatten($array, 'a');
function flatten($array, $index='a') {
$return = array();
if (is_array($array)) {
foreach ($array as $row) {
$return[] = $row[$index];
}
}
return $return;
}
But yea, I would say what you have would be the most efficient way of doing it.
You Can Try As Like Following ......
$multi_array = array(0 => array('a' => 5), 1 => array('a' => 8));
$new_array = array();
foreach ($multi_array AS $key => $value) {
$new_array[] = $value['a'];
}
I recently found myself facing this problem, and I believe I have found the solution.
I will go over the problem itself, and also the solution, trying to explain everything along the way.
The problem was that I didn't have a two-dimensional array, but an array which could have any number of arrays inside arrays, so the solution by Brad F Jacobs couldn't apply here, although it's very simple and functional.
I had to work with a self-referencing database table called 'webpage', where one of the columns was 'parentWebpageId', which referenced an Id of some other row in that same table. This way, a tree structure can be built and easily managed, if you get your loops right.
Ia easily made a function which is supposed to generate a multi-dimensional array from one-dimensional self-referencing array, but the problem arose when I tried to make a function which should to the opposite. I needed this because if I wanted to delete a certain webpage, all it's children should also be deleted, in order to preserve the self-referential integrity.
It was easy to generate a tree whose root was the page that was initially to be deleted, but then I needed a list of all child webpage's Ids, in order to delete all of them.
So, the structure I had was something like this:
webpage1
id
title
...
childWebpageArray
webpage2
id
title
...
childWebpageArray
webpage2.1
id
url
...
childWebpageArray
webpage2.2
id
url
...
childWebpageArray
webpage2.2.1
id
url
...
childWebpageArray
webpage2.2.2
id
url
...
childWebpageArray
webpage2.3
id
url
...
childWebpageArray
webpage3
id
title
...
childWebpageArray
As you can see, the depth can go forever.
What I came up with is this:
function flattenMultidimensionalArray($multidimensionalArray) {
// Set anchor.
ohBoyHereWeGoAgain:
// Loop through the array.
foreach ($multidimensionalArray as $key1 => $value1) {
// Check if the webpage has child webpages.
if (isset($multidimensionalArray[$key1]["childWebpageArray"]) && (count($multidimensionalArray[$key1]["childWebpageArray"]) > 0)) {
// If it does, loop through all the child webpages, and move them into the initial multi-dimensional array.
foreach ($multidimensionalArray[$key1]["childWebpageArray"] as $key2 => $value2) {
$multidimensionalArray[] = $multidimensionalArray[$key1]["childWebpageArray"][$key2];
}
// Unset element's child pages, because all those child pages, along with their child pages
// have been moved into the initial array, thus reducing the depth of a multi-dimensional array by 1.
unset($multidimensionalArray[$key1]["childWebpageArray"]);
}
}
// Loop once again through the whole initial array, in order to check if any of the pages has children
foreach ($multidimensionalArray as $key => $value) {
// If a page which has children is found, kick the script back to the beginning, and go through it again.
if (isset($multidimensionalArray[$key]["childWebpageArray"]) && (count($multidimensionalArray[$key]["childWebpageArray"]) > 0)) {
goto ohBoyHereWeGoAgain;
}
}
// In the end, when there are no more pages with children, return an array of pages.
return $multidimensionalArray;
}
This solution worked in my case, and I believe is the right one for this kind of problem. It probably isn't much of a hassle to change it in order to fit your particular needs.
Hope this helps!

Categories