Grab array from textarea and convert it into an array - php

I need user to enter an array in a textarea and this array might be big array, I tried to serialize it and save it encoded in DB but it failed,
This is my code:
if( strpos( $_POST['textarea_array'], 'array' ) !== FALSE ) {
$temp_serialized = serialize( $_POST['textarea_array'] );
if( ( $temp_unserialized = #unserialize( $temp_serialized ) !== FALSE )
&& is_array( $temp_unserialized ) ) {
/* Condition FAILED */
$temp_json = json_encode( $temp_unserialized );
$final_value = base64_encode( $temp_json );
}
}
Example of what would be entered in the textarea a simple or a complicated array with sub array for each key
array(
'x_sub_array' => array(
'x_1' => 'X 1',
'x_2' => 'X 2',
'x_3' => 'X 3',
);
'x_2' => 'X 2',
'x_3' => 'X 3',
);

First of all, there are easier ways to pass data. But if this is the absolute ONLY way, might as well answer it bluntly. (If your user strictly adheres to the format...)
if(isset($_POST['textarea_array'])){
$raw = $_POST['textarea_array'];
//Parse the array section
$start = strpos($raw, "(");
$end = strpos($raw, ")");
$full = substr($raw,$start+1,$end - ($start+1));
//Remove quotations
$full = str_replace("'","",$full);
//Divide string into array of segments `key=>value` as one segment
$segments = explode(",", $full);
foreach($segments as $segment){
//Divide each segment `key=>value` to a temp array
//Index 0 will hold the key, Index 1 will hold value
$array_part = explode("=>",$segment);
//Remove spaces
$key = trim($array_part[0]);
$value = trim($array_part[1]);
//insert into associative array
$final[$key] = $value;
}
//$final now has your associative array
echo json_encode($final);
}
Again, there are better alternatives.
-How bout having the user pass a json object via AJAX?
-Or how bout the user enter each element and separate with a newline?
But never rely on serialize or eval especially since you dont want users to have access to your php pages.

Related

Take the value from array in php and explode

I have this the values of in my array as
$itsthere = (item1-0-100, item2-0-50, item3-0-70, item4-0-50, item5-0-100);
If the user enter the value item3 he has to get 70 which is present in array. I tried alot using explode but its not showing proper value. Can any one help me.
Try with:
$itsthere = array(
'item1-0-100',
'item2-0-50',
'item3-0-70',
'item4-0-50',
'item5-0-100'
);
$search = 'item3';
$output = '';
foreach ( $itsthere as $value ) {
if ( strpos($search . '-', $value) === 0 ) {
$output = explode('-', $value)[2];
break;
}
}
When you say item3 are you refering to the third position or the item3 as array key? I think you can create a assoc array and make item names as key
$isthere = array('item1' => '0-100', 'item2' => '0-50' ,'item3' => '0-70', ....,);
echo $isthere['item3']; // This would give you the value.
If you only want to know if this key is in the array use array_key_exists.
Try this :
$item = 'item3';
$itsthere = array('item1-0-100', 'item2-0-50', 'item3-0-70', 'item4-0-50', 'item5-0-100');
foreach($itsthere as $there)
{
$exp = explode('-',$there);
if($exp[0] == 'item3') {
echo $val = $exp[2];
};
}

comparing two arrays and create a statement

What: I'm attempting to compare data in two arrays and write a statement based on the comparison,
$sys = array("1"=>'kitchen lights', "2"=>'living lights', "3"=>'living fan');
$input = array('off kitchen lights','on living fan');
Note: The input can come in any order! :-/ any ideas
Compare these to allow for me to change the state in a database and write to a change log.
The sys array key is also important here.
Im shooting for a result like the following:
$write = '1:0,2:256';// means off kitchen lights and on living fan
The write is broken into bits like this:
($sys array key number):('256' on or off '0'),(separate next listing...)
Im familiar with array_intersect.
$wordin = explode(" ", $input);
$wordsys = explode(" ", $sys);
$result = array_intersect($wordin, $wordsys);
Im sure I could loop through the array looking for lets say on and replace it with 256 or 0 but im running to issues thinking of how to do the following:
Handle variations like lights versus light...I need them to be equal for this...
Preserve the sys array key number
Note: Im not sure of a "easier" method but I will take any feed back!
Thanks,
JT
More Info: A user types a string. Im pulling all the detail out of the string and arriving at the input array. The sys is a predefined database that the user set up.
To have different triggers for the same thing, you can do something like this (allows you to add more triggers easily). You could also place some regex in the triggers and evaluate them, but you can figure that out yourself ;)
<?php
define('SWITCHED_ON', 256);
define('SWITCHED_OFF', 0);
$sys = array(
'1' => array(
'name' => 'Kitchen Lights',
'triggers' => array(
'kitchen light',
'kitchen lights',
),
),
'2' => array(
'name' => 'Living Lights',
'triggers' => array(
'living lights',
'lights in living room',
'light in living room',
),
),
'3' => array(
'name' => 'Living Fan',
'triggers' => array(
'living fan',
'fan in living room',
),
),
);
$input = array('off kitchen lights','on living fan');
$output = array();
foreach ( $input as $command ) {
// split command at first whitespace
// $command_array = preg_split('%\s+%', $command, 2);
// update to allow input like $input = array('kitchen off lights','living fan on');
$split = preg_split('%\s+%', $command);
$input_switch = false;
$input_trigger = array();
foreach ( $split as $part ) {
if ( $input_switch === false ) {
switch ( $part ) {
case 'on': $input_switch = SWITCHED_ON; break;
case 'off': $input_switch = SWITCHED_OFF; break;
default: $input_trigger[] = $part; break;
}
} else {
$input_trigger[] = $part;
}
}
if ( $input_switch === false || empty($input_trigger) ) {
continue;
}
$input_trigger = implode(' ', $input_trigger);
// insert check if command is valid (for example contains only spaces and alphanumerics.. etc..)
// ...
foreach ( $sys as $syskey => $conf ) {
foreach ( $conf['triggers'] as $trigger ) {
if ( $trigger == $input_trigger ) {
$output[] = $syskey.':'.$input_switch;
continue 3; // continue outer foreach
}
}
}
// if you arrive here, the command was not found in sys
}
$output = implode(',', $output);
echo $output;
PS: The $sys array looks different, but as u say the user sets them up. So there would be no way to check for all cases of "kitchen lights", "kitchen light", and what other stuff the user puts into the array. So they could just fill the array like above, with different triggers for the same thing. I think the ease of use makes up the extra structure of the new $sys. ^^
UPDATE: Updated to allow unordered input. I think the unordered input is kind of hard to deal with, if you can not be sure how many instances of the word "off" or "on" are found in one command. If there are more instances, you won't be able to decide which "on" or "off" is the correct one. There could be a rule.. like "The first instance of "on" or "off" is the one we'll use" or something. The code above will use that rule. So if you input a command like "kitchen off lights on off", it will result in trying to turn OFF the thing that has a trigger "kitchen lights on off". Another possible way is to reject the command if there are more instances of "on"|"off". Or to cut multiple instances of "on"|"off".
Try this:
$values = array();
foreach ($input as $i) {
$parts = explode(' ', $i);
// first word: 'on' || 'off'
$val = array_shift($parts);
// attach the remaining words again to form the key
$key = implode(' ', $parts);
// get the index of the $key value in $sys array
// and concat 0 or 156 depending on $val
$values[] = array_shift(array_keys($sys, $key)).':'.($val == 'on' ? 256: 0);
}
$write = implode(';', $values);
makes use of the second parameter of array_keys to fetch the correct key of the $sys array.
See it in action in this fiddle
edit
For managing different inputs in different formats (without changing the $sys array):
$alts = array(
'kitchen lights' => array(
'kitchen lights', 'kitchen lights', 'lights in kitchen', 'light in kitchen'
),
'living fan' => array(
'living fan', 'living fans', 'fans in living', 'fan in living'
),
);
foreach ($input as $i) {
$i = strtolower($i); // make sure we have all lower caps
// check if on in in the start or beginning of the input
$flag = substr($i, 0, 2) === 'on' || strpos($i, strlen($i)-1, 2) === 'on';
// remove on and off from the string, trim whitespace
$search = trim(str_replace(array('on', 'off'), '', $i));
// search for the resulting string in any of the alt arrays
$foundSysKey = false;
foreach ($alts as $sysKey => $alt) {
if (in_array($search, $alt)) {
$foundSysKey = $sysKey;
break;
}
}
// did not find it? continue to the next one
if ($foundSysKey === false) {
echo 'invalid key: '.$search;
continue;
}
// now you have the info we need and can precede as in the previous example
$values[] = array_shift(array_keys($sys, $foundSysKey)).':'.($flag ? 256: 0);
}
I tried saving an updated fiddle but the site seems to have some problems... it did work though.

Split A String at X, then at Y Value

I have the following code:
$Field = $FW->Encrypt("Test");
echo "<pre>";
print_r($Field);
echo "</pre>";
# $IV_Count = strlen($Field['IV']);
# $Key_Count = strlen($Field['Key']);
# $Cipher_Count = strlen($Field['CipheredText']);
foreach ($Field AS $Keys => $Values){
echo $Keys."Count = ".strlen($Values)."<br><br>";
}
The output is as:
Array
(
[CipheredText] => x2nelnArnS1e2MTjOrq+wd9BxT6Ouxksz67yVdynKGI=
[IV] => 16
[Key] => III#TcTf‡eB12T
)
CipheredTextCount = 44
IVCount = 2
KeyCount = 16
The IV/KeyCount is always returning the same value regardless of the input. But the CipheredTextCount changes depending on the input.. For example:
$Field = $FW->Encrypt("This is a longer string");
The foreach loop returns:
CipheredTextCount = 64
IVCount = 2
KeyCount = 16
and now for my question. Lets take the first example with the TextCount of 44
How can I split a string after implode("",$Field); to display as the original array? an example would be:
echo implode("",$Field);
Which outputs:
ijGglH/vysf52J5aoTaDVHy4oavEBK4mZTrAL3lZMTI=16III#TcTf‡eB12T
Based on the results from the strlen?
It is possible to store the count of the first $Cipher_Count in a database for a reference
My current setup involves storing the key and IV in a seperate column away from the ciphered text string.. I need this contained within one field and the script handles the required information to do the following:
Retrieve The long string > Split string to the original array > Push
array to another function > decrypt > return decoded string.
Why not use serialize instead? Then when you get the data out of the database, you can use unserialize to restore it to an array.
$Combined_Field = implode("",$Field);
echo $str1 = substr($Combined_Field, 0, $Cipher_Count)."<br><br>";
echo $str2 = substr($Combined_Field,$Cipher_Count,$IV_Count)."<br><br>";
echo $str3 = substr($Combined_Field, $IV_Count+$Cipher_Count,$Key_Count);
Or use a function:
function Cipher_Split($Cipher, $Cipher_Count, $KeyCount, $IVCount){
return array(
"Ciphered Text" => substr($Cipher,0,$Cipher_Count),
"IV" => substr($Cipher,$Cipher_Count,$IVCount),
"Key" => substr($Cipher,$IVCount+$Cipher_Count,$KeyCount)
);
}

multidimensional array processing

I have a tab delimited text file like this:
"abcdef1" "AB"
"abcdef1" "CD"
"ghijkl3" "AA"
"ghijkl3" "BB"
"ghijkl3" "CC"
For every common ID (e.g. abcdef1), I need to take the two digit code an concatenate it into a multi-value. So, eventually it should look like:
"abcdef1" "AB,CD"
"ghijk13", "AA,BB,CC"
I dont need to create a new output txt file but if i can get the final values in an array that would be great. I am just a week old to php, hence looking for help with this. I was able to get the values from the input txt file into an array, but further processing the array to get the common ID and take the 2 digit code and concatenate is something I'm struggling with. Any help is greatly appreciated
How about:
$values = array();
$handle = fopen($file, 'r');
// get the line as an array of fields
while (($row = fgetcsv($handle, 1000, "\t")) !== false) {
// we haven't seen this ID yet
if (!isset($values[$row[0]])) {
$values[$row[0]] = array();
}
// add the code to the ID's list of codes
$values[$row[0]][] = $row[1];
}
$values will be something like:
Array
(
[abcdef1] => Array
(
[0] => AB
[1] => CD
)
[ghijkl3] => Array
(
[0] => AA
[1] => BB
[2] => CC
)
)
There are a number of steps to the task you want to do. The first step, obviously, is getting the contents of your file. You state that you've already been able to get the contents of the file into an array. You may have done something like this:
// Assuming that $pathToFile has the correct path to your data file
$entireFile = file_get_contents( $pathToFile );
$lines = explode( '\n', $entireFile ); // Replace '\n' with '\r\n' if on Windows
How you get the lines into the array is less important. From here on out I assume that you've managed to fill the $lines array. Once you have this, the rest is fairly simple:
// Create an empty array to store the results in
$results = array();
foreach( $lines as $line ){
// Split the line apart at the tab character
$elements = explode( "\t", $line );
// Check to see if this ID has been seen
if( array_key_exists( $elements[0], $results ){
// If so, append this code to the existing codes for this ID (along with a comma)
$results[ $elements[0] ] .= ',' . $elements[1];
} else {
// If not, this is the first time we've seen this ID, start collecting codes
$results[ $elements[0] ] = $elements[1];
}
}
// Now $results has the array you are hoping for
There are some variations on this -- for example, if you want to get rid of the quote marks around each ID or around each code, you can replace $results[ $elements[0] ] with $results[ trim( $elements[0], '"' ) ] and/or replace $elements[1] with trim( $elements[1], '"' ).

PHP: improving the loop that uses foreach?

I use foreach to loop the array below and then making the order number to be store in the database,
$items_variable = array(
'page_id',
'page_content_1',
'page_content_2',
'page_content_3',
'page_content_4',
...
);
The code only loop 4 items from the array above (but what if I have these page_content_# increased in the future?)
foreach( $items_variable as $item_variable )
{
if (in_array($item_variable, array(
'page_content_1',
'page_content_2',
'page_content_3',
'page_content_4'
)))
{
if($item_variable == 'page_content_1') $order_in_page = 1;
if($item_variable == 'page_content_2') $order_in_page = 2;
if($item_variable == 'page_content_3') $order_in_page = 3;
if($item_variable == 'page_content_4') $order_in_page = 4;
....
}
}
The current method I have above doesn't look good to me especially when it comes to the line like this,
if($item_variable == 'page_content_1') $order_in_page = 1;
I will add more lines like this when I have page_content_# increased in the future and the script will look pretty ugly I suppose.
What if I have another type of data with order number (for instance - code_1, code_2, etc)? Then I have copy the code above and change the item name each time - this looks pretty gloomy isn't!
How can I make it better and dynamic?
Associative array
You can do this:
$items_definitions = array(
'page_content_1' => 1,
'page_content_2' => 2,
'page_content_3' => 3,
'page_content_4' => 4,
'page_content_5' => 5,
);
foreach( $items_variable as $item_variable ){
if( isset( $items_definitions[ $item_variable])){
$order_in_page = $items_definitions[ $item_variable];
}
...
}
Dynamically extracting last part of string
Or do it completely dynamically assuming that it's always page_content_{$order_in_page}, either with regexp as hackartist suggested or use "oldschool method":
$prefix = 'page_content_';
foreach( $items_variable as $item_variable ){
if( strncmp( $item_variable, $pregix, strlen( $prefix))){
continue; // Assume that you don't want to do anything if it doesn't match
}
$page = intval( substr( $item_variable, strlen( $prefix)));
if( !$page){
continue;
}
$order_in_page = $page;
}
I recommend studying examples from intval() documentation :)
Switch statement
Php provides switch which allows you to handle many different cases with relatively small amount of code.
foreach( $items_variable as $item_variable ){
switch( $item_variable){
case 'page_content_1':
$order_in_page = 1;
break;
case 'page_content_2':
$order_in_page = 2;
break;
case 'page_content_3':
$order_in_page = 3;
break;
...
default:
}
}
I'd however do this only if first two options wouldn't work out for you (eg. you need to call different function for each case).
not sure exactly what you want but try this instead of the if statement:
preg_match('/page_content_([0-9]+)/',$item_variable,$matches);
$order_in_page = $matches[1];
I'm not sure I understand your question, but maybe an associative array would be a solution for you. You can use it to match a string to a value:
$order_in_page = array(
'page_content_1' => 1,
'page_content_2' => 2,
'page_content_3' => 3,
'page_content_4' => 4,
'someotherpage' => 5,
'yet_another_page' => 6
);
$o = $order_in_page[$item_variable];
Stuff on the data structure
http://en.wikipedia.org/wiki/Associative_array
PHP Documentation
http://php.net/manual/de/language.types.array.php
Your current array, if you write it out with the explicit keys, looks like the following:
$items_variable = array(
0 => 'page_id',
1 => 'page_content_1',
2 => 'page_content_2',
3 => 'page_content_3',
4 => 'page_content_4',
...
);
Notice that the key number matches completely with the page content number. Thus, you could change the foreach loop to the following:
foreach( $items_variable as $order_in_page => $item_variable )
Now $order_in_page should be stored with the key number, which in your array correlates directly to the page content number. You may need to cast it into an int, although I am not sure of this fact:
$order_in_page = (int) $order_in_page;
If instead, your array looked like the following (without the 'page_id' element):
$items_variable = array(
0 => 'page_content_1',
1 => 'page_content_2',
2 => 'page_content_3',
3 => 'page_content_4',
...
);
Do the same thing as above, but add one to the result:
++$order_in_page;
If casting is needed, cast before the increment.
foreach($items_variable as $item_variable) {
preg_match('/[0-9]*$/',$item_variable , $suffix);
$suffix = $suffix[0];
if ($suffix !== '') {
# code 1
} else {
# code 2
}
}
I'm not sure I understood your question, but you might want to store your data in a multidimensional array, like:
$items_variable = array(
'page_id',
'content' => array(
//content
)
);
Then you could just iterate through each content-array, such as:
foreach($items_variable['content'] as $content) {
//do stuff with the content
}
No need for regex or other stuff.

Categories