php - curl query to backend, mix up data - php

I'm not sure if this question was asked before, but I couldn't find anything.
When I CURL to the back-end from the front-end, I pass a JSON object containing a SQL query in base64:
base64(SELECT * FROM mytable) -> U0VMRUNUICogRlJPTSBteXRhYmxl
[{
'sql' : 'U0VMRUNUICogRlJPTSBteXRhYmxl'
}]
Back-end receives it, and then run that query over a sqlite3 database. It returns the data and put it into a JSON object:
[{
'column 1' : 'row 1 - data',
'column 2' : 'row 1 - data',
'column 3' : 'row 1 - data',
},{
'column 1' : 'row 2 - data',
'column 2' : 'row 2 - data',
'column 3' : 'row 2 - data',
},{
'column 1' : 'row 3 - data',
'column 2' : 'row 3 - data',
'column 3' : 'row 3 - data',
}]
and then returns it back with python flask server, I think with requests library.
My problem is that the JSON object that comes back doesn't look like the one above, but returns more like:
[{
'column 2' : 'row 1 - data',
'column 3' : 'row 1 - data',
'column 1' : 'row 1 - data',
},{
'column 2' : 'row 2 - data',
'column 3' : 'row 2 - data',
'column 1' : 'row 2 - data',
},{
'column 2' : 'row 3 - data',
'column 3' : 'row 3 - data',
'column 1' : 'row 3 - data',
}]
and I don't know why. I even tried to specify the SELECT statement as
SELECT "column 1", "column 2", "column 3" FROM mytable;
but still the same.
I can order it myself, but there isn't only 1 table to be queried.
My CURL code:
$query = $_POST['query'];
function safeQ($squery){
$denied = ["update","delete","insert","create","alter","drop"];
$squery = strtolower($squery);
foreach($denied as &$deny){
if (strpos($squery, $deny) !== false) {
return false;
}
}
return true;
}
print(getQuery($query));
function getQuery($query){
if (safeQ($query)){
$data->sql = base64_encode($query);
$jsonData = json_encode($data);
$ch = curl_init('https://www.example.com/api/sql_query');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($jsonData))
);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER, false);
$result = curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return $result;
}
}

To answer your question why, it is the same thing I said in the comments; when python is storing a dictionary, it does not care about order. Why the order turns out the way it does? That requires a more complicated knowledge of memory allocation that i'm currently capable of answering, but the point of using a key/value structure is not regarding the order the entries are in.
[{
'column 2' : 'row 1 - data',
'column 3' : 'row 1 - data',
'column 1' : 'row 1 - data',
},{
'column 2' : 'row 2 - data',
'column 3' : 'row 2 - data',
'column 1' : 'row 2 - data',
},{
'column 2' : 'row 3 - data',
'column 3' : 'row 3 - data',
'column 1' : 'row 3 - data',
}]
Is completely fine. If you start seeing this however;
[{
'column 2' : 'row 1 - data',
'column 3' : 'row 1 - data',
'column 1' : 'row 1 - data',
},{
'column 2' : 'row 3 - data',
'column 3' : 'row 3 - data',
'column 1' : 'row 3 - data',
},{
'column 2' : 'row 2 - data',
'column 3' : 'row 2 - data',
'column 1' : 'row 2 - data',
}]
It is a case for concern, since this time the array type structure got out of its original order.
You can make the following assertion yourself by opening an interpreter
>>> {'a':1,'b':2} == {'b':2,'a':1}
True

Related

Call to a member function toArray() on array

I’m trying to use this package: https://packagist.org/packages/digital-creative/conditional-container. However with this basic example:
return array_merge(
[
Select::make('Option', 'option')
->options([
1 => 'Option 1',
2 => 'Option 2',
3 => 'Option 3',
]),
/**
* Only show field Text::make('Field A') if the value of option is equals 1
*/
ConditionalContainer::make([ Text::make('Field A') ])->if('option = 1'),
Text::make('Title'),
Textarea::make('Description'),
],
$arr
);
I’m getting the error message: Call to a member function toArray() on array.
If I change to:
return array_merge(
[
[
Select::make('Option', 'option')
->options([
1 => 'Option 1',
2 => 'Option 2',
3 => 'Option 3',
]),
ConditionalContainer::make([ Text::make('Field A') ])->if('option = 1')
],
It shows:
message: "Call to a member function getUpdateRules() on array"
even with only the example like below it shows "message: "Call to a member function toArray() on array":
public function definition(): array
{
return [
Select::make('Option', 'option')
->options([
1 => 'Option 1',
2 => 'Option 2',
3 => 'Option 3',
]),
ConditionalContainer::make([ Text::make('Field A') ])->if('option = 1')
];
}
Do you know how to solve the issue? Thanks!
Not sure what is does, but you are sending an array to a class that class has a method toArray().
that's why i always use return types in my code cause it will break if the input does not match.
Could it be that it thinks that this is a collection or a class that needs to be inputted.
in some cases i am lazy and will try the following:
collect(return array_merge(
[
[
Select::make('Option', 'option')
->options([
1 => 'Option 1',
2 => 'Option 2',
3 => 'Option 3',
]),
ConditionalContainer::make([ Text::make('Field A') ])->if('option = 1')
],)
because many packages uses Collection as a way to handle, filter and search an array.
but this is more a guess than actuall knowledge. Look at the function getUpdateRules() in the vendor map, what does it do.
/**
* #param Resource|Model $resource
*
* #return array
*/
public function resolveDependencyFieldUsingResource($resource): array
{
$matched = $this->runConditions(
$this->flattenRelationships($resource)
);
return $matched ? $this->fields->toArray() : [];
}
this is the function so as you can see it expects a model or resource class
according to the docs:
return [
Select::make('Option', 'option')
->options([
1 => 'Option 1',
2 => 'Option 2',
3 => 'Option 3',
]),
//more suff
your return array
array_merge(
[ // <--- note the extra bracket
[
Select::make('Option', 'option')
->options([
1 => 'Option 1',
2 => 'Option 2',
3 => 'Option 3',
]),
ConditionalContainer::make([ Text::make('Field A') ])->if('option = 1')
],

JQuery Select2 - Format nested list from PHP/MySQL results

I have a Select2 list which I want to populate with a nested structure for the data:
Level 1
Condition 1
Condition 2
Level 2
Condition 3
Condition 4
etc
The JSON needs to be in the following format:
data: [{
'text': 'Level 1',
'children': [{
'id': 1,
'text': 'Condition 1'
}, {
'id': 2,
'text': 'Condition 2'
}, ],
'text': 'Level 2',
'children': [{
'id': 3,
'text': 'Condition 3'
}, {
'id': 4,
'text': 'Condition 4'
}, ]
}]
The JQuery Select2:
$.ajax( {
url: "scripts/get_conditions.php",
dataType: 'json'
} ).then( function ( response ) {
$( "#condition_tree" ).select2( {
placeholder: "Select a Condition...",
allowClear: true,
width: 'resolve',
containerCssClass: "show-hide",
data: response
} );
} );
Currently using the following PHP and MySQL which I am unsure of how to change to produce the required results:
$query = 'SELECT * FROM mcondition ORDER BY mcondition_name ASC';
$result = $connection->query( $query );
$presentations = array();
while ($row = mysqli_fetch_array($result)) {
$mconditions[] = array("id"=>$row['mcondition_pk'], "text"=>$row['mcondition_name']);
}
echo json_encode($mconditions);
?>
And the mcondition table:
+---------+-----------+------------------------------+
| mcondition_pk | mcondition_name | mcondition_level |
+---------+-----------+------------------------------+
| 1 | Condition 1 | Level 1 |
+---------+-----------+------------------------------+
| 2 | Condition 2 | Level 1 |
+---------+-----------+------------------------------+
| 3 | Condition 3 | Level 2 |
+---------+-----------+------------------------------+
| 4 | Condition 4 | Level 2 |
+---------+-----------+------------------------------+
Note PHP version is 5.3.3, no chance of upgrading at present.
Use the level name as key of a two-dimensional array to gather your data under, add each row’s data to the children under the appropriate key.
// fake mysql row data
$data = [
['mcondition_pk' => 1, 'mcondition_name' => 'Condition 1', 'mcondition_level' => 'Level 1'],
['mcondition_pk' => 2, 'mcondition_name' => 'Condition 2', 'mcondition_level' => 'Level 1'],
['mcondition_pk' => 3, 'mcondition_name' => 'Condition 3', 'mcondition_level' => 'Level 2'],
['mcondition_pk' => 4, 'mcondition_name' => 'Condition 4', 'mcondition_level' => 'Level 2'],
];
$temp = [];
// foreach loop over fake data, replace that with your original `while(…)` again
foreach($data as $row) {
$temp[$row['mcondition_level']]['text'] = $row['mcondition_level'];
$temp[$row['mcondition_level']]['children'][] = [
'id' => $row['mcondition_pk'],
'text' => $row['mcondition_name']
];
}
// replace the associative keys with simple numeric ones again
$temp = array_values($temp);
echo json_encode($temp);

php vfsStream is not parsing newline characters

I'm trying to unit test methods in isolation that work with csv files, using vsf-stream from here: https://github.com/mikey179/vfsStream
I've created a 2 dimensional data array to test, but when I try to add this to the mocked file it seems to parse the newline characters, instead of adding new lines. I've tried both fputcsv and fputs but both have the same results. Using the same data and php functions I can write successfully to a normal file, the issues seems to be with vfs-stream. Not much documentation on the net and completely lost:
$this->data = array(
array( 'col1', 'col2', 'col3', 'col4' ),
array( 'row 0 1', 'row 0 2', ' row 0 3', ' row 0 4' ),
array( 'row 1 1', 'row 1 2', ' row 1 3', ' row 1 4' ),
array( 'row 2 1', 'row 2 2', ' row 2 3', ' row 2 4' ),
array( 'row 3 1', 'row 3 2', ' row 3 3', ' row 3 4' ),
array( 'row 4 1', 'row 4 2', ' row 4 3', ' row 4 4' ),
array( 'row 5 1', 'row 5 2', ' row 5 3', ' row 5 4' ),
);
$this->root = vfsStream::setup('test-dir');
$file = vfsStream::url('test-dir/foo.csv');
$handle = fopen($file, "a+");
foreach( $this->data as $arr)
fputcsv($handle, $arr, "|"); //$content .= implode("|", $arr) . "\n";
The above code will produce the mocked file but without any newline characters, so parsing the mocked csv file later in the test won't work as it seems to all be written in the one long line:
var_dump( file_get_contents( $file ) );
will produce:
string(272) "col1|col2|col3|col4\n"row 0 1"|"row 0 2"|" row 0 3"|" row 0 4"\n"row 1 1"|"row 1 2"|" row 1 3"|" row 1 4"\n"row 2 1"|"row 2 2"|" row 2 3"|" row 2 4"\n"row 3 1"|"row 3 2"|" row 3 3"|" row 3 4"\n"row 4 1"|"row 4 2"|" row 4 3"|" row 4 4"\n"row 5 1"|"row 5 2"|" row 5 3"|" row 5 4"\n"
I'm hoping that I'm missing a flag for this and its not a bug. Any help appreciated, cheers.
The issue was using var_dump instead of print or echo to see the results. var_dump will give a descriptive and literal representation of the variable and not parse the \n chars - print or echo would print and parse the \n chars.
Therefore the above code works and its my stupidity or lack of sleep that is the issue.

Mysql Update mutiple row of datas

I would like to know how to efficiently update multiple rows of data with the UPDATE statement. I know I can insert multiple records like this one below.
INSERT INTO example
(example_id, name, value, other_value)
VALUES
(100, 'Name 1', 'Value 1', 'Other 1'),
(101, 'Name 2', 'Value 2', 'Other 2'),
(102, 'Name 3', 'Value 3', 'Other 3'),
(103, 'Name 4', 'Value 4', 'Other 4');
But how it works in Update, or if I have to loop the query and update one by one?
At the moment I have to use foreach to loop and update each SQL statement.
foreach() {
// update statement....
// and execute the query
}
You can use case when indise update..
An eg:
UPDATE users
SET value = CASE
WHEN id in (1,4) THEN 53
WHEN id = 2 THEN 65
WHEN id in (3,5) THEN 47
END
WHERE id IN (1,2,3,4,5)
Refer this so and this for more.
$data = array(
array(
100,
'Name 1',
'Value 1',
'Other 1'
),
array(
101,
'Name 2',
'Value 2',
'Other 2',
)
array(
102,
'Name 3',
'Value 3',
'Other 3'
)
)
for($i = 0; $i < count($data); $i++) {
for($j= 0; $j< count($data[$i]); $j++) {
$field1 = $data[$i][$j];
$field2 = $data[$i][$j];
$filed3 = $data[$i][$j];
$field4 = $data[$i][$j];
query("UPDATE TABLE SET.... WHERE id = $field1");
}
}
You can use CASE in MYSQL also:
Ex:
UPDATE example
SET example_id = CASE
WHEN example_id=100 THEN 1000
WHEN example_id=101 THEN 1001
WHEN example_id=102 THEN 1002
ELSE example_id*10
END
You can see another example, In this, there is a table Person and having wrongly entered Gender. So you need to correct them by updating Male to Female and Female to Male.
So here is your code:
UPDATE Person
SET Gender= CASE
WHEN gender= 'Male' THEN 'Female'
WHEN gender= 'Female' THEN 'Male'
ELSE gender
END

PHP json_decode Big(O) and optimization

I am trying to write php code which takes an NSArray of NSDictionaries and adds the records to a database. Unfortunately, this is taking around 20 seconds to process around 500 records with a total size of around 2mb.
function uploadTracks($tracks, $partyID, $pName) {
$tracks = json_decode($tracks, true);
$itemInfo = array();
foreach($tracks as $itemInfo){
$track = $itemInfo['songTitle'];
$artist = $itemInfo['artistName'];
$album = $itemInfo['albumName'];
$artwork = $itemInfo['artwork'];
$result = query("INSERT INTO partyRecords(Pkey,songName,songArtist,imageBinary,partyName) VALUES ('%s','%s','%s','%s','%s')" ,$partyID,$track,$artist,$artwork,$pName);
}
}
Is there anyway to optimize the above code? Could json_decode be what is taking the most time?
You can insert multiple records in single insert query. In this case your db indexes will be updated once and it gain you performance boost:
INSERT INTO partyRecords
(Pkey, songName, songArtist, imageBinary, partyName)
VALUES
(1, 'Name 1', 'Artist 1', 'Image 1', 'Party 1'),
(2, 'Name 2', 'Artist 2', 'Image 2', 'Party 2'),
(3, 'Name 3', 'Artist 3', 'Image 3', 'Party 3'),
(4, 'Name 4', 'Artist 4', 'Image 4', 'Party 4');
I would say 95% it is the queries. You need to compile the queries and insert them 100 or so at a time. It would be best to escape the query variables yourself (mysql: mysql_real_escape_string() ).
INSERT INTO partyRecords(Pkey,songName,songArtist,imageBinary,partyName) VALUES (2,'12312','12312321','12312332423','23423432');INSERT INTO partyRecords(Pkey,songName,songArtist,imageBinary,partyName) VALUES (2,'12312','12312321','12312332423','23423432');...

Categories