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.
Related
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.
I'm working on a search-based website, and am trying to pass parameters using SEO-friendly URLs.
Is it possible to pass the following URL and get the URL in CodeIgniter?
http://www.example.com/search/prize/10/13/14.5/size/xl/2xl/color/black/white-grey/
I am able to create the URL, but I want to get the URL values like $prize = array("10","13","14.5"), $size= array("xl","2xl"), and $color = array("black","white-grey").
I tried to use the uri_to_assoc() function, but it didn't work. I get the following output:
[price] => 10,
[13] => 14.5
...
which is wrong.
Note: I tried to use $this->uri->segment(1), etc., but in this case, the segment position is dynamic.
For example, users may search for only prices of $10, so the URL will get changed to:
http://www.example.com/search/prize/10/size/xl/2xl/color/black/white-grey/
Now the segment position of getting the size must be changed. In this case, I want:
$prize = array("10");
$size = array("xl", "2xl");
$color = array("black", "white-grey");
How can I achieve this?
You are using quite the unconventional "friendly URI" format. Normally when passing parameters there is a single identifier and then the parameter e.g. /name/key/name/key/name/key.
When you use the correct format /name/key/name/key/name/key in conjunction with uri_to_assoc(), you would get:
array(
'name' => 'key',
// etc...
)
but using something like /prize/1/2/3/size/s/m/l/color/black/white/grey would yield:
array(
'prize' => 1,
2 => 3,
'size' => 's',
'm' => 'l',
// etc...
)
Which is useless to you.
You will have to fetch all of the segments individually and build your arrays with a foreach:
$segments = $this->uri->segment_array();
$prize = array();
$size = array();
$color = array();
$curKey = '';
foreach ($segments as $seg) {
if (in_array($seg, array('prize', 'size', 'color'))) {
$curKey = $seg; continue;
}
if (!empty($curKey)) ${$curKey}[] = $seg;
}
// use $prize, $size, and $color as you wish
or alternatively using a multi-dimensional array:
$parameters = array(
'prize' => array(),
'size' => array(),
'color' => array(),
);
$segments = $this->uri->segment_array();
$curKey = '';
foreach ($segments as $seg) {
if (in_array($seg, array('prize', 'size', 'color'))) {
$curKey = $seg; continue;
}
if (!empty($curKey)) $parameters[$curKey][] = $seg;
}
Fetch all the segments
Iterate over them, check each for keywords like size, color, etc. (make a whitelist)
If a keyword is found, assume the segment values until the next keyword segment or the end are the values for that specific keyword (so xl and 2xl will denote the size if preceeded with a keyword size, etc.)
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.
For readability and perfomance reasons, I'd like to build up an array with a switch statement instead of if-statements.
Consider the following if-statement:
$size = 2;
$array = array();
if($size >= 1) { array_push($array,'one','foo'); }
if($size >= 2) { array_push($array,'two','bar','barista'); }
if($size >= 3) { array_push($array,'three','zoo','fool','cool','moo'); }
It basically counts up from 1 to $size, it might be more readable and most likely a lot faster with a switch-statment...but how do you construct that ??
$step = 2;
$array = array();
switch($step)
{
case ($step>1): array_push($array,'one','foo');
case ($step>2): array_push($array,'two','bar','barista');
case ($step>3): array_push($array,'three','zoo','fool','cool','moo');
}
I tried leaving out the break, which didn't work - as the manual says:
In a switch statement, the condition is evaluated only once[...].
PHP continues to execute the statements until the end of the switch
block, or the first time it sees a break statement.
Anyway, anyone got an idea how to build up such an array with a switch-statement ??
Surely what you want can be achieved much more easily using
$array=range(1,$size);
Based on further coments and subsequent edits, something like:
$baseArray = $array(array('one'),
array('two','twoA'),
array('three','threeA','threeB'),
array(),
array('five'),
);
$step=2;
$array = array_slice($baseArray,0,$step);
and then flatten $array
Well, a switch statement would look like:
edit: the above doesn't work - let me take a look.
but in this example, you could just do:
$size = 2;
$array = range(1, $size); // Array ( [0] => 1 [1] => 2 )
$valuesIWant = array(1=>'one','two','three','four');
$array = array();
for ($i = $step - 1; $i > 0; $i--) $array[] = $valuesIWant[$i];
$array = array_reverse($array);
So if $step is 2, you get:
Array
(
[0] => one
)
...and if it is 4, you get:
Array
(
[0] => one
[1] => two
[2] => three
)
I want to replace all array values with 0 except work and home.
Input:
$array = ['work', 'homework', 'home', 'sky', 'door']
My coding attempt:
$a = str_replace("work", "0", $array);
Expected output:
['work', 0, 'home', 0, 0]
Also my input data is coming from a user submission and the amount of array elements may be very large.
A bit more elegant and shorter solution.
$aArray = array('work','home','sky','door');
foreach($aArray as &$sValue)
{
if ( $sValue!='work' && $sValue!='home' ) $sValue=0;
}
The & operator is a pointer to the particular original string in the array. (instead of a copy of that string)
You can that way assign a new value to the string in the array. The only thing you may not do is anything that may disturb the order in the array, like unset() or key manipulation.
The resulting array of the example above will be
$aArray = array('work','home', 0, 0)
A loop will perform a series of actions many times. So, for each element in your array, you would check if it is equal to the one you want to change and if it is, change it. Also be sure to put quote marks around your strings
//Setup the array of string
$asting = array('work','home','sky','door')
/**
Loop over the array of strings with a counter $i,
Continue doing this until it hits the last element in the array
which will be at count($asting)
*/
for($i = 0; $i < count($asting);$i++){
//Check if the value at the 'ith' element in the array is the one you want to change
//if it is, set the ith element to 0
if ($asting[$i] == 'work' || $asting[$i] == 'home')
$asting[$i] = 0;
}
Here is some suggested reading:
http://www.php.net/manual/en/language.types.array.php
http://www.php.net/manual/en/language.control-structures.php
But if you are struggling on stuff such as looping, you may want to read some introductory programming material. Which should help you really understand what's going on.
A bit other and much quicker way, but true, need a loop:
//Setup the array of string
$asting = array('bar', 'market', 'work', 'home', 'sky', 'door');
//Setup the array of replacings
$replace = array('home', 'work');
//Loop them through str_replace() replacing with 0 or any other value...
foreach ($replace as $val) $asting = str_replace($val, 0, $asting);
//See what results brings:
print_r ($asting);
Will output:
Array
(
[0] => bar
[1] => market
[2] => 0
[3] => 0
[4] => sky
[5] => door
)
An alternative using array_map:
$original = array('work','home','sky','door');
$mapped = array_map(function($i){
$exclude = array('work','home');
return in_array($i, $exclude) ? 0 : $i;
}, $original);
you may try array_walk function:
function zeros(&$value)
{
if ($value != 'home' && $value != 'work'){$value = 0;}
}
$asting = array('work','home','sky','door','march');
array_walk($asting, 'zeros');
print_r($asting);
You can also give array as a parameter 1 and 2 on str_replace...
Just a small point to the for loop. Many dont realize the second comparing task is done every new iteration. So if it was a case of big array or calculation you could optimize loop a bit by doing:
for ($i = 0, $c = count($asting); $i < $c; $i++) {...}
You may also want to see http://php.net/manual/en/function.array-replace.php for original problem unless the code really is final :)
Try This
$your_array = array('work','home','sky','door');
$rep = array('home', 'work');
foreach($rep as $key=>$val){
$key = array_search($val, $your_array);
$your_array[$key] = 0;
}
print_r($your_array);
There are a few techniques on this page that make zero iterated function calls -- which is good performance-wise. For best maintainability, I recommend separating your list of targeted string as a lookup array. By modifying the original array values by reference, you can swiftly replace whole strings and null coalesce non-targeted values to 0.
Code: (Demo)
$array = ['work', 'homework', 'home', 'sky', 'door'];
$keep = ['work', 'home'];
$lookup = array_combine($keep, $keep);
foreach ($array as &$v) {
$v = $lookup[$v] ?? 0;
}
var_export($array);
Output:
array (
0 => 'work',
1 => 0,
2 => 'home',
3 => 0,
4 => 0,
)
You can very easily, cleanly extend your list of targeted strings by merely extending $keep.
If you don't want a classic loop, you can use the same technique without modifying the original array. (Demo)
var_export(
array_map(fn($v) => $lookup[$v] ?? 0, $array)
);
this my final code
//Setup the array of string
$asting = array('work','home','sky','door','march');
/**
Loop over the array of strings with a counter $i,
Continue doing this until it hits the last element in the array
which will be at count($asting)
*/
for($i = 0; $i < count($asting); $i++) {
//Check if the value at the 'ith' element in the array is the one you want to change
//if it is, set the ith element to 0
if ($asting[$i] == 'work') {
$asting[$i] = 20;
} elseif($asting[$i] == 'home'){
$asting[$i] = 30;
}else{
$asting[$i] = 0;
}
echo $asting[$i]."<br><br>";
$total += $asting[$i];
}
echo $total;