I am trying to use an array to output a form with the following function:
public function createArrayForm($table, $do, $formDesc = '', $id, $array, $markFields = false) {
if (!isset($table) && !isset($do)) {
self::show_error('One or more parameters are missing in ' . __FUNCTION__);
} elseif ($table == 'update' && !isset($id)) {
self::show_error('For this form to be built, and ID must be set. Missing parameter `ID` in ' . __FUNCTION__);
}
if (is_array($array) && $do == 'insert') {
$out .= '<form action="' . $_SERVER['PHP_SELF'] . '?id=' . $id . '&table=' . $table . '" method="post" class="form-horizontal" ' . $formAppend . '>';
$out .= '<div class="form-desc">' . $formDesc . '</div>';
$out .= $markFields ? '<h3>Input Fields</h3>' : '';
foreach ($array as $type => $fieldname) {
if ($type == 'input') {
$out .= generateInputField($fieldname);
}
}
$out .= $markFields ? '<h3>Content Fields</h3>' : '';
foreach ($array as $type => $fieldname) {
if ($type == 'textarea') {
$out .= generateTextarea($fieldname, $cke);
}
}
$out .= $markFields ? '<h3>Images Fields</h3>' : '';
foreach ($array as $type => $fieldname) {
if ($type == 'image') {
$out .= generateImgField($fieldname);
}
}
$out .= form_hidden('user_data', '1');
$out .= form_hidden('id', self::generateID());
$out .= form_close();
return $out;
}
And call:
$arr = array("textarea"=>"project_name", "input"=>"created", "input"=>"last_modified", "input"=>"published");
echo $automate->createArrayForm('projects', 'insert', 'Some form desc', '123', $arr, true);
But it only outputs:
When it should look something like this:
Only one of each, for example input, is returned. Rather than all instances of it. So "input"=>"created", "input"=>"last_modified", "input"=>"published" should make three inputs, but it only returns one.
You're re-using array keys. So
$arr = array("textarea"=>"project_name", "input"=>"created", "input"=>"last_modified", "input"=>"published");
will end up looking like this:
$arr = array("textarea"=>"project_name", "input"=>"published");
Instead, modify your code to something like this:
$arr = array("textarea"=>array("project_name"), "input"=>array("created", "last_modified", "published"));
Then take those individual arrays, and iterate through them.
foreach ($array['input'] as $fieldname) { // etc and so on
In PHP, you cannot have arrays that share keys.
You'll be best creating a simple array, and creating sub-entries, so that you maintain order, but can have more than one input/textarea.
Like so:
$arr = array(
array('type' => 'textarea', 'name' => 'project_name'),
array('type' => 'input', 'name' => 'created'),
array('type' => 'input', 'name' => 'published'),
array('type' => 'input', 'name' => 'last_modified')
)
This would also allow you to add more parameters than type/name.
The problem is that you use the same key for everything in the array.
A possibility would be to exchange values and keys
$arr = array("textarea"=>"project_name", "input"=>"created", "input"=>"last_modified", "input"=>"published");
[...]
foreach ($array as $fieldname => $type) {
if ($type == 'textarea') {
$out .= generateTextarea($fieldname, $cke);
}
}
[...]
Related
I need to convert a PHP array into HTML tag attributes, with spaces and quotes, this is an example:
$array=array(
'attr1'=>'value1',
'id'=>'example',
'name'=>'john',
'class'=>'normal'
);
This is the result I need to achieve:
attr1="value1" id="example" name="john" class="normal"
There is any PHP function to do it?
I am trying these:
http_build_query
array_walk
You can also use this easy one line code, please follwo below code::
$array=array(
'attr1'=>'value1',
'id'=>'example',
'name'=>'john',
'class'=>'normal'
);
$data = str_replace("=", '="', http_build_query($array, null, '" ', PHP_QUERY_RFC3986)).'"';
echo $data;
Output
attr1="value1" id="example" name="john" class="normal"
I use the following function:
function buildAttributes($attributes)
{
if (empty($attributes))
return '';
if (!is_array($attributes))
return $attributes;
$attributePairs = [];
foreach ($attributes as $key => $val)
{
if (is_int($key))
$attributePairs[] = $val;
else
{
$val = htmlspecialchars($val, ENT_QUOTES);
$attributePairs[] = "{$key}=\"{$val}\"";
}
}
return join(' ', $attributePairs);
}
It correctly escapes special html characters and supports boolean attributes (attributes without value). The following input:
[
'name' => 'firstname',
'value' => 'My Name',
'required'
]
Will produce:
name="firstname" value="My Name" required
Use a foreach loop to get the value and key.
$array = array(
'attr1'=>'value1',
'id'=>'example',
'name'=>'john',
'class'=>'normal');
foreach ($array as $key => $value) {
echo $key . '="' . htmlspecialchars($value) . '" ';
}
If you wanted to use a function, you could just make your own such as the following.
$array = array(
'attr1'=>'value1',
'id'=>'example',
'name'=>'john',
'class'=>'normal');
echo buildTag($array);
function buildTag ($array) {
$tag = '';
foreach ($array as $key => $value) {
$tag .= $key . '="' . htmlspecialchars($value) . '" ';
}
return $tag;
}
You could also utilize array_map() in conjunction with array_keys() to build your $key=$value string.
Wrapped in array_filter() to remove empty items and ultimately use implode() to glue your items together.
$array = array(
'attr1' => 'value1',
'id' => 'example',
'name' => 'john',
'class' => 'normal',
'c' => null,
'd' => '',
'e' => '"abc"'
);
$attributes = implode( ' ', array_filter( array_map( function ( $key, $value ) {
return $value ? $key . '="' . htmlspecialchars( $value ) . '"' : false;
}, array_keys( $array ), $array ) ) );
echo "<div " . $attributes . "></div>";
Result:
<div attr1="value1" id="example" name="john" class="normal" e=""abc""></div>
The shortest one-line function to do that would be:
function add_attributes($attributes){
return urldecode(http_build_query(array_map(function($v){ return '"'.((string) $v).'"'; }, $attributes), '', ' '));
}
You can use it like this:
$array=array(
'attr1'=>'value1',
'id'=>'example',
'name'=>'john',
'class'=>'normal'
);
echo '<div '.add_attributes($array).'></div>';
will produce:
<div attr1="value1" id="example" name="john" class="normal"></div>
You can use this function:
public static function arrayToStringTags( $array )
{
$tags = '';
if(!(is_array($array) && !empty($array)))
{
return $tags;
}
foreach($array as $key => $value)
{
$tags .= $key. '="'. $value. '" ';
}
return $tags;
}
First assumption: Assume, we defined a variable (its name is $tmp) in a function(functioin name is 'ExpMenu') for temporary calculating and in end of function we return this variable.
Second assumption: Assume, we call that function recursively for create a navigation menu base on a multidimensional array.
My question is about scope of that variable ($tmp). In every call funtion, will its value overwritten? In other words, by every function call we lose previous value?
For more detail, please review below code:
/// --- { Declaration Block
$content = array(
array(
'level'=>'1',
'order'=>'1',
'text'=>'New Solution WorkFlow',
'is_parent'=>'yes',
'child'=> array(
array(
'level'=>'2',
'order'=>'1',
'text'=>'Define New Solution',
'is_parent'=>'no',
'url'=>'#'
),
array(
'level'=>'2',
'order'=>'2',
'text'=>'View Solutions',
'is_parent'=>'no',
'url'=>'#'
),
array(
'level'=>'2',
'order'=>'3',
'text'=>'View Solutions',
'is_parent'=>'no',
'url'=>'#'
)
)
),
array(
'level'=>'1',
'order'=>'2',
'text'=>'Solution Modify WorkFlow',
'is_parent'=>'yes',
'child'=> array(
array(
'level'=>'2',
'order'=>'1',
'text'=>'Request For Solution Modify',
'is_parent'=>'no',
'url'=>'#'
)
)
),
array(
'level'=>'1',
'order'=>'3',
'text'=>'Solution Close WorkFlow',
'is_parent'=>'yes',
'child'=> array(
array(
'level'=>'2',
'order'=>'1',
'text'=>'Declare For Solution Close',
'is_parent'=>'no',
'url'=>'#'
)
)
)
);
function ExpMenu($item_array ) {
$tmp='';
foreach ($item_array as $item) {
if ($item['is_parent']=='yes') {
$tmp = '<li class="hasChild">' . $item["text"] . '<ul>';
$tmp .= ExpMenu($item['child']);
$tmp .= '</ul></li>';
} else {
$tmp = '<li>';
$tmp .= ''. $item['text'] . '' ;
$tmp .= '</li>';
}
}
return $tmp;
}
/// --- }
$menu='<div><ul>';
$menu .= ExpMenu($content);
$menu.='</ul></div>';
echo $m . '<br />';
It seams by every call function we lose pervious value.
I thank #l0rkaY for her/him solution, But I found another solution that doesn't need add new parameter in my function.
Because $tmp scope is in 'ExpMenu' function and we call recursively function, therefore variable still alive and wasn't terminated.
So, I modify my function a bit:
function ExpMenu($item_array ) {
$tmp='';
foreach ($item_array as $item) {
if ($item['is_parent']=='yes') {
$tmp .= '<li class="hasChild">' . $item["text"] . '<ul>';
$tmp .= ExpMenu($item['child']);
$tmp .= '</ul></li>';
} else {
$tmp .= '<li>';
$tmp .= ''. $item['text'] . '' ;
$tmp .= '</li>';
}
}
return $tmp;
}
I assume your actual problem is, that your function generates only single item with a single child item.
It's because you are overwriting your previous item in your if/else blocks. That's why you only get the last item.
You just need to concatenate them to the existing items.
function ExpMenu($item_array ) {
$tmp='';
foreach ($item_array as $item) {
if ($item['is_parent']=='yes') {
$tmp .= '<li class="hasChild">' . $item["text"] . '<ul>';
$tmp .= ExpMenu($item['child']);
$tmp .= '</ul></li>';
} else {
$tmp .= '<li>';
$tmp .= ''. $item['text'] . '' ;
$tmp .= '</li>';
}
}
return $tmp;
}
I want to update multiple rows in the database with codeigniters update_batch() function.
But the field specified in the where should also be changed.
The following code should make it clear:
$set = array(
array(
'token' => '65787131678754',
'device' => 'none',
'new_token_value' => ''
),
array(
'token' => '75798451315464',
'device' => 'none',
'new_token_value' => ''
)
);
$this->db->update_batch(TBL_NAME, $set, 'token');
Tokens specified in token should be updated with device to 'none' and the token itself should be set to empty string ''.
Is this possible with update_batch() function?
In sql I would write something like
UPDATE TBL_NAME
SET token='', device='none'
WHERE token='65787131678754'
for one update but this is not practicable for multiple, so I want to use the update_batch() function.
I created a helper function mostly identical to the codeigniter batch_update() function.
But with the ability to update the index itself. The new value is defined by index_update_key.
function update_batch($db, $table = '', $set = NULL, $index = NULL, $index_update_key = '') {
if ($table === '' || is_null($set) || is_null($index) || !is_array($set)) {
return FALSE;
}
$sql = 'UPDATE ' . $db->protect_identifiers($table) . ' SET ';
$ids = $when = array();
$cases = '';
//generate the WHEN statements from the set array
foreach ($set as $key => $val) {
$ids[] = $val[$index];
foreach (array_keys($val) as $field) {
if ($field != $index && $field != $index_update_key) {
$when[$field][] = 'WHEN ' . $db->protect_identifiers($index)
. ' = ' . $db->escape($val[$index]) . ' THEN ' . $db->escape($val[$field]);
} elseif ($field == $index) {
//if index should also be updated use the new value specified by index_update_key
$when[$field][] = 'WHEN ' . $db->protect_identifiers($index)
. ' = ' . $db->escape($val[$index]) . ' THEN ' . $db->escape($val[$index_update_key]);
}
}
}
//generate the case statements with the keys and values from the when array
foreach ($when as $k => $v) {
$cases .= "\n" . $db->protect_identifiers($k) . ' = CASE ' . "\n";
foreach ($v as $row) {
$cases .= $row . "\n";
}
$cases .= 'ELSE ' . $k . ' END, ';
}
$sql .= substr($cases, 0, -2) . "\n"; //remove the comma of the last case
$sql .= ' WHERE ' . $index . ' IN (' . implode(',', $ids) . ')';
return $db->query($sql);
}
Now I can do the following
$set = array(
array(
'token' => '657871316787544',
'device' => 'none',
'new_token_value' => ''
),
array(
'token' => '757984513154644',
'device' => 'none',
'new_token_value' => ''
)
);
update_batch($this->db, 'table_name', $set, 'token', 'new_token_value');
and the sql output is
UPDATE `b2c` SET
`token` = CASE
WHEN `token` = '657871316787544' THEN ''
WHEN `token` = '757984513154644' THEN ''
ELSE token END,
`device` = CASE
WHEN `token` = '657871316787544' THEN 'none'
WHEN `token` = '757984513154644' THEN 'none'
ELSE device END
WHERE token IN (657871316787544,757984513154644)
$this->db->where('option1', $option1);<br/>
$this->db->update_batch('table_name', $data, 'option2');
Hi i have this code to output a array list
$Sql1 = "SELECT * FROM tabmp3
WHERE Mp3_Player = 1
";
$Query1 = mysql_query($Sql1, $Conn)or die(mysql_error($Conn));
$musicas = array();
while($Rs1 = mysql_fetch_array($Query1)){
$musicas[] = array( title => $Rs1['Musica_Nome'], autor => "Grupo Fronteiras", mp3 => "http://site/Musicas/".$Rs1["Disco_Id"]."/".$Rs1["Musica_Mp3"] );
}
echo ( json_encode($musicas) );
this output
[{"title":"Alegria do Pov\u00e3o","autor":"Grupo Fronteiras","mp3":"http:\/\/site\/Musicas\/3\/201302140204413c390efdb9957eebd8d85c262f2a4929.mp3"}, {"title":"Bem na moda da fronteira","autor":"Grupo Fronteiras","mp3":"http:\/\/site\/Musicas\/2\/20130214032235fabd12471ffc7790c9204f891919bca8.mp3"}]
i need to remove double quotes from keys and fix the http link to looks like this
[{title:"Alegria do Pov\u00e3o",autor:"Grupo Fronteiras",mp3:"http://site/Musicas/3/201302140204413c390efdb9957eebd8d85c262f2a4929.mp3"},{title:"Bem na moda da fronteira",autor:"Grupo Fronteiras",mp3:"http://site/Musicas/2/20130214032235fabd12471ffc7790c9204f891919bca8.mp3"}]
Thanks
Try this..I know it is not very good way to do it.. I am writing this to show you that you have to make the form that you wanted in your php code only.
$json = json_encode($musicas);
$json = preg_replace('/["]/', '' ,$json);
$json = str_replace(':',':"', $json);
$json = str_replace(',','",',$json);
$json = str_replace('}]','"}]',$json);
echo $json;
By this way you will acheive what you wanted. But please find something good way to do it.
The correct answer should be this, as commented by #AlvaroLouzada
$json = json_encode($musicas);
$json = preg_replace('/"([^"]+)"\s*:\s*/', '$1:', $json);
echo $json ;
I looked a lot for an elegant solution to fix this issue without doing changing things over javascript or just replace quotes via preg_replace (for the case that the values would contain quotes) and end up doing it by myself. even if it's too late, I hope it would help those who are looking for the same solution.
function json_encode_advanced(array $arr, $sequential_keys = false, $quotes = false, $beautiful_json = false) {
$output = "{";
$count = 0;
foreach ($arr as $key => $value) {
if ( isAssoc($arr) || (!isAssoc($arr) && $sequential_keys == true ) ) {
$output .= ($quotes ? '"' : '') . $key . ($quotes ? '"' : '') . ' : ';
}
if (is_array($value)) {
$output .= json_encode_advanced($value, $sequential_keys, $quotes, $beautiful_json);
} else if (is_bool($value)) {
$output .= ($value ? 'true' : 'false');
} else if (is_numeric($value)) {
$output .= $value;
} else {
$output .= ($quotes || $beautiful_json ? '"' : '') . $value . ($quotes || $beautiful_json ? '"' : '');
}
if (++$count < count($arr)) {
$output .= ', ';
}
}
$output .= "}";
return $output;
}
function isAssoc(array $arr) {
if (array() === $arr) return false;
return array_keys($arr) !== range(0, count($arr) - 1);
}
usage:
$array = [
'someField' => '"value"', // double quotes for string if needed
'labelField' => '"label"', // double quotes for string if needed
'boolean' => false,
'numeric' => 5,
'render' => [
'option' => 'function() {
console.log("Hello World!");
console.log(\'Hello World!\');
}',
],
];
echo json_encode_advanced($array);
result:
{
someField : "value",
labelField : "label",
boolean : false,
numeric : 5,
render : {
option : function() {
console.log("Hello World!");
console.log('Hello World!');
}
}
}
Instead of doing echo ( json_encode($musicas) );, do something like this:
$json_string = json_encode($musicas);
$json_string = str_replace('\/', '/', $json_string);
echo $json_string;
I'm not so strong with arrays but I need to determine how to count the number of parents a child array has in order to determine the indenting to display it as an option in a SELECT.
So, if I have this array:
array(
'World'=>array(
'North America'=>array(
'Canada'=>array(
'City'=>'Toronto'
)
)
)
);
How would I go about determining how many parents 'City' has in order to translate that into the number of spaces I want to use as an indent?
Thanks for any help.
EDIT: Let's see if I can explain myself better:
I have this code I'm using to build the OPTIONS list for a SELECT:
function toOptions($array) {
foreach ($array as $key=>$value) {
$html .= "<option value=\"" . $key . "\" >";
$html .= $value['title'];
$html .= "</option>";
if (array_key_exists('children', $value)) {
$html .= toOptions($value['children']);
}
}
return $html;
}
print toOptions($list);
So, I'm trying to determine how to get the number of parents in order to add spaces before the title in this line:
$html .= $value['title'];
Like:
$html .= " " . $value['title'];
But, I'm not sure how to figure out how many spaces to add.
Hopefully this is more clear.
Thanks for any help so far.
$x = array(
'World'=>array(
'North America'=>array(
'Canada'=>array(
'City'=>'Toronto'
)
)
)
);
// This function do something with the key you've found in the array
function visit($name, $depth)
{
echo $name . ' has ' . $depth . ' parents.';
}
// This function visits all the contents aff $array
function find_recursive($array, $depth = 0)
{
if (is_array($array)) {
foreach ($array as $k => $value) {
visit($k, $depth + 1);
find_recursive($array, $depth + 1);
}
}
}
For visiting:
find_recursive($x);
Well. Off the top what you are dealing with is a multi dimensional array.
You could run a count w/ foreach on each level of the array, and use the count number returned +1 for each level the foreach loops through.
I'm not sure if this answers your question, but I am trying to see exactly what it is you are trying to achieve.
As you are already using a recursive function to display that data, you can just extend your function. There is no need to traverse the array more often than one time:
function getWhitespaces($count) {
$result = '';
while($count--) {
$result .= '$nbsp;';
}
return $result;
}
function toOptions($array, $level=0) {
foreach ($array as $key=>$value) {
$html .= "<option value=\"" . $key . "\" >";
$html .= getWhitespaces($level) + $value['title'];
$html .= "</option>";
if (array_key_exists('children', $value)) {
$html .= toOptions($value['children'], $level + 1);
}
}
return $html;
}
print toOptions($list);
Try the following.. Your solution screams for recursion in my mind. Its a bit ugly but it seems to work
$totraverse = array(
'Moon' => array(
'Dark Side' => "Death Valley"
),
'Halley Commet' => "Solar System",
'World' => array(
'North America' => array(
'Canada' => array(
'City' => 'Toronto'
)
), 'South America' => array(
'Argentina' => array(
'City' => 'Toronto'
)
)
)
);
function traverse($totraverse_, $path="", $count=0) {
global $array;
// echo count($totraverse_) . " count\n";
if (!is_array($totraverse_)) {
echo "returning $path and $key\n";
return array($path, $count);
} else {
foreach ($totraverse_ as $key => $val) {
echo "assting $path and $key\n";
$result = traverse($val, $path . "/" . $key, $count + 1);
if($result){
$array[]=$result;
}
}
}
echo false;
}
$array = array();
traverse($totraverse);
foreach($array as $item){
echo "{$item[0]}--->{$item[1]}\n";
}