$resultUpdate = Nemesis::select("*", $table, "id = '{$id}'");
if (!$resultUpdate) {
self::show_error(QUERY_ERROR);
} elseif ($resultUpdate->num_rows > 0) {
$out .= '<div class="form-desc">' . $formDesc . '</div>';
} else {
self::show_error(QUERY_EMPTY);
}
$array = array_values($array);
print_r($array);
$out .= '<form action="' . $_SERVER['PHP_SELF'] . '?id=' . $id . '&table=' . $table . '" method="post" class="form-horizontal" ' . $formAppend . '>';
while ($row = $resultUpdate->fetch_assoc()) {
foreach ($row as $fieldname => $value) {
if (in_array($fieldname, $array)) {
$out .= generateInputField($fieldname, $value);
}
}
foreach ($row as $fieldname => $value) {
if (in_array($fieldname, $array)) {
$out .= generateTextarea($fieldname, $value, $cke);
}
}
foreach ($row as $fieldname => $value) {
if (in_array($fieldname, $array)) {
$out .= generateImgField($fieldname, $value);
}
}
}
$arr = array("last_modified"=>"input", "published"=>"input", "content"=>"textarea");
echo $automate->createArrayForm('projects', 'update', 'Some form desc', '178514825', $arr, true);
Right now all fields are outputting in every foreach when only inputs should output in the generateInputField section for example. I know this is because I need to check if the fieldtype (input, textarea) key matches with one of the values marked as input or textarea for values of the $fieldname. But I am not sure how.
I am pretty sure I have to filter the array so only values with input go into a separate array like arrayInput in which I can use as the second argument in in_array.
If I understand you and your code correctly...
This code
while ($row = $resultUpdate->fetch_assoc()) {
foreach ($row as $fieldname => $value) {
if (in_array($fieldname, $array)) {
will always return true for all your rows thats why you are getting your current output.
Instead you should be doing this:
while ($row = $resultUpdate->fetch_assoc()) {
foreach ($row as $fieldname => $value) {
if ($fieldname == 'input') {
$out .= generateInputField($fieldname, $value);
} elseif($fieldname == 'textarea') {
$out .= generateTextarea($fieldname, $value, $cke);
} elseif ($fieldname == 'img') {
$out .= generateImgField($fieldname, $value);
}
else{ $out = $out;}
}
}
With alot of help from stackers...
/**
* Create Form With Array
*
* Creates a form based on an array. If $do == update, we match fieldnames with values
*
* #param string $table name of database table
* #param string $do whether the form is an insert or update
* #param string $formDesc form description to be echoed
* #param array $array associative array of type (keys), and fieldnames (values)
* #param bool $markFields whether or not to add headers for inputs, textareas .etc during insert
* #param bool $formBrackets whether or not to prepend and append form brackets
* #return $out html form
*
*/
public function createArrayForm($table, $do, $formDesc = '', $id, $array, $markFields = false, $formBrackets = true) {
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)) {
self::show_error('For this form to be built, an array must be given. Missing parameter `array` in ' . __FUNCTION__);
}
$result = array();
// create two dimensional array to preserve keys that
// otherwise would be lost with array_flip
foreach($array as $k => $v) {
if (array_key_exists($v, $result)) {
$result[$v][] = $k;
} else {
$result[$v] = array($k);
}
}
// make sure we do not have any duplicates
$result = super_unique($result);
// we just need the array_values for matching with in_array
// however we do not want to run array_values on null
// so we check to see if the $result is a valid array first
// if not, we just output a blank array so in_array doesn't complain
$arrayInput = is_array($result['input']) ? array_values($result['input']) : array();
$arrayTextarea = is_array($result['textarea']) ? array_values($result['textarea']) : array();
$arrayImages = is_array($result['images']) ? array_values($result['images']) : array();
$out = $formBrackets == true ? '<form action="' . $_SERVER['PHP_SELF'] . '?id=' . $id . '&table=' . $table . '" method="post" class="form-horizontal" ' . $formAppend . '>' : NULL;
if($do == 'insert') {
$out .= isset($formDesc) ? '<div class="form-desc">' . $formDesc . '</div>' : NULL;
$out .= $markFields && in_array('input', $array) ? '<h3>Input Fields</h3>' : NULL;
foreach ($arrayInput as $fieldname) {
$out .= generateInputField($fieldname);
}
$out .= $markFields && in_array('textarea', $array) ? '<h3>Content Fields</h3>' : NULL;
foreach ($arrayTextarea as $fieldname) {
$out .= generateTextarea($fieldname, $cke);
}
$out .= $markFields && in_array('image', $array) ? '<h3>Images Fields</h3>' : NULL;
foreach ($arrayImages as $fieldname) {
$out .= generateImgField($fieldname);
}
} elseif ($do == 'update') {
$resultUpdate = Nemesis::select("*", $table, "id = '{$id}'");
if (!$resultUpdate) {
self::show_error(QUERY_ERROR);
} elseif ($resultUpdate->num_rows > 0) {
$out .= isset($formDesc) ? '<div class="form-desc">' . $formDesc . '</div>' : NULL;
} else {
self::show_error(QUERY_EMPTY);
}
while ($row = $resultUpdate->fetch_assoc()) {
foreach ($row as $fieldname => $value) {
if (in_array($fieldname, $arrayInput)) {
$out .= generateInputField($fieldname, $value);
}
}
foreach ($row as $fieldname => $value) {
if (in_array($fieldname, $arrayTextarea)) {
$out .= generateTextarea($fieldname, $value, $cke);
}
}
foreach ($row as $fieldname => $value) {
if (in_array($fieldname, $arrayImages)) {
$out .= generateImgField($fieldname, $value);
}
}
}
} else {
self::show_error('Missing array or `do` argument in function ' . __FUNCTION__);
}
$out .= form_hidden('user_data', '1');
$out .= form_hidden('id', $do == 'update' ? $id : self::generateID());
$out .= $formBrackets == true ? form_close() : NULL;
return $out;
}
Usage:
$arr = array("last_modified"=>"input", "published"=>"input", "project_content"=>"textarea", "project_content"=>"textarea");
echo $automate->createArrayForm('projects', 'insert', 'Some form desc', '123', $arr, true);
echo $automate->createArrayForm('projects', 'update', 'Some form desc', '178514825', $arr, true);
Related
I need to output the response from the database in XML. So far I have gotten it to output this:
The outermost tag needs to match the name of the action query, it'll either be <courses> or <students>.
Here is my code:
<?php
require_once('./database.php');
if (isset($_GET['format'])) {
$format = filter_var($_GET['format']);
}
if (isset($_GET['action'])) {
$action = filter_var($_GET['action'], FILTER_SANITIZE_STRING);
$tableName = "sk_$action";
}
$query = "SELECT * FROM $tableName";
if (isset($_GET['course'])) {
$course = filter_input(INPUT_GET, 'course');
$query .= " WHERE courseID = :course";
}
function arrayToXml($arr, $i = 1, $flag = false)
{
$sp = "";
for ($j = 0; $j <= $i; $j++) {
$sp .= " ";
}
foreach ($arr as $key => $val) {
echo "$sp<" . $key . ">";
if ($i == 1) echo "\n";
if (is_array($val)) {
if (!$flag) {
echo "\n";
}
arrayToXml($val, $i + 5);
echo "$sp</" . $key . ">\n";
} else {
echo "$val" . "</" . $key . ">\n";
}
}
}
$statement = $db->prepare($query);
$statement->bindValue(':course', $course);
$statement->execute();
$response = $statement->fetchAll(PDO::FETCH_ASSOC);
$statement->closeCursor();
if ($format == 'json') {
echo json_encode($response);
}
if ($format == 'xml') {
arrayToXml($response, 1, true);
}
I'm pretty new to PHP and have never worked with XML. All help is appreciated. Thanks.
function arrayToXml($arr, $collectionTag, $singleTag) {
$collection = new SimpleXMLElement("<$collectionTag/>");
foreach ($arr as $row) {
$element = $root->addChild($singleTag);
foreach ($row as $tag => $value) {
$element->addChild($tag, $value);
}
}
return $collection;
}
$courses = arrayToXml($response, 'courses', 'course');
echo $courses->asXML();
Tested with PHP 7.1.23. Output:
<?xml version="1.0"?>
<courses>
<course><courseID>cs601</courseID><courseName>Web Application Development</courseName></course>
<course><courseId>cs602</courseId><courseName>Server-Side Application Development</courseName></course>
<course><courseId>cs701</courseId><courseName>Rich Internet Application Development</courseName></course>
</courses>
(I added newlines because by default it doesn't add any.)
I've created the following function to print HTML tags in PHP.
function div($attr = [], $child = []) {
$div = "<div";
if (is_array($attr)) {
foreach ($attr as $key => $value) {
$div .= " " . $key . '="' . $value . '"';
}
}
$div .= ">";
if (is_array($child)) {
foreach ($child as $value) {
$div .= $value;
}
}
$div .= "</div>";
return $div;
}
echo div(["class" => "container"], [
div(["class" => "title"], ["Lorem Ipsum"]])
]);
Now, I use this function with multiple tags; div, table, tr, td, etc.
For each tag, I declare the function over and over again with little modification in the body. This seems redundant. I want to create a main function which will return the actual function. For example,
$div = construct("div");
$tr = construct("div");
Of course, PHP is different than JS. In JS, this would work:
function construct(tagName) {
var elm = tagName;
return function(value) {
console.log(elm + ": " + value);
}
}
var div = construct("div");
var tr = construct("tr");
div("test"); // div: test
tr("test"); // tr: test
How should I proceed?
Similar actually as in js:
Just use the first argument of the function to pass the element type as a string.
function construct($elem, $attr = [], $child = []) {
$out = "<".$elem;
if (is_array($attr)) {
foreach ($attr as $key => $value) {
$out .= " " . $key . '="' . $value . '"';
}
}
$out .= ">";
if (is_array($child)) {
foreach ($child as $value) {
$out .= $value;
}
}
$out .= "</".$elem.">";
return $out;
}
echo construct("div",["class" => "container"], [
div(["class" => "title"], ["Lorem Ipsum"]])
]);
You could pass the type of tag through a parameter of the function.
function ConstrucElement($tag, $attr, $body)
{
$output = '<' . $tag;
....
$output .= '</' . $tag . '>';
}
This is how I would solve the problem at hand:
function element($elementName, $attr = [], $child = []) {
$element = "<" . $elementName;
...
return $element;
}
function div($attr = [], $child = []) {
return element("div", $attr, $child);
}
This has the additional benefit of enabling element specific validations etc.: (pseudocode)
function a($attr = [], $child = []) {
if(attr contains no href) return ERROR;
return element("div", $attr, $child);
}
Doing some more digging, I figured out a way to make it work the JS way. The use of use in the examples in PHP: Closure - Manual did the job.
function construct($tag_name = "") {
return function($attr = [], $child = []) use ($tag_name) {
$element = "<$tag_name";
if (is_array($attr)) {
foreach ($attr as $key => $value) {
$element .= " " . $key . '="' . $value . '"';
}
}
$element .= ">";
if (is_string($child)) {
$element .= $child;
}
if (is_array($child)) {
foreach ($child as $value) {
$element .= $value;
}
}
$element .= "</$tag_name>";
return $element;
};
}
$h2 = construct("h2");
$span = construct("span");
$div = construct("div");
$table = construct("table");
$tr = construct("tr");
$td = construct("td");
Using a generic function to print the tags seems like a more practical approach, but not that desirable, because the code gets harder to read. Compare the following blocks.
while ($row = $albums->fetch_assoc()) {
echo $div(["class" => "album"], [
$h2([], [$row["album"] . " (" . $row["year"] . ")"]),
$div(["class" => "album-cover"], [
img(["src" => "covers/" . $row["cover"]]),
]),
$div(["class" => "songs"], [
$table([], [
loop_songs($row["album"]),
]),
]),
]);
}
while ($row = $albums->fetch_assoc()) {
echo construct("div", ["class" => "album"], [
construct("h2", [], [$row["album"] . " (" . $row["year"] . ")"]),
construct("div", ["class" => "album-cover"], [
construct("img", ["src" => "covers/" . $row["cover"]]),
]),
construct("div", ["class" => "songs"], [
construct("table", [], [
loop_songs($row["album"]),
]),
]),
]);
}
First one seems more readable to me.
Here's another approach using __callStatic:
So now you can build your HTML with these:
Build::div(...)
Build::span(...)
Build::table(...)
Like this:
<?php
class Build {
public static function __callStatic($name, $arguments) {
$attr = $arguments[0];
$child = $arguments[1];
$div = "<" . $name;
if (is_array($attr))
foreach ($attr as $key => $value)
$div .= " " . $key . '="' . $value . '"';
$div .= ">";
if (is_array($child))
foreach ($child as $value)
$div .= $value;
$div .= "</" . $name . ">";
return $div;
}
}
echo Build::div(["class" => "container"], [
Build::span(["class" => "title"], ["Lorem Ipsum"])
]);
Output:
<div class="container"><span class="title">Lorem Ipsum</span></div>
i want to create HTML element with PHP functions. in this section i have select function to create select tag. for values i want to check if array is simple my function create simple select otherwise create optgroup for options.
my create select method :
$tag->select( 'myselect',
array(
'0'=>'please choose','1'=>'111','2'=>'222','3'=>'333'
) ,
'2',
array(
'class'=>'myClass','style'=>'width:10%;'
)
);
other use:
$tag->select( 'myselect',
array( 'one'=>
array('0'=>'please choose','1'=>'111','2'=>'222','3'=>'333'),
'two'=>
array('0'=>'please choose','1'=>'111','2'=>'222','3'=>'333')
) ,
'2',
array(
'class'=>'myClass','style'=>'width:10%;'
)
) ;
now in below function i want to check if array into array exist function must be create select group;
public function select( $name, $values, $default='0', $attributs=[]){
$options = [];
$selected = '';
echo count($values);
if ( count($values) == 1){
foreach ($values as $value => $title) {
if ( $value === $default ) $selected="selected='selected'";
$options[] = "<option value = '$value' $selected>" . $title . '</option>'.PHP_EOL ;
$selected = '';
}
}
else{
foreach ($values as $key => $value) {
$options[] = "<optgroup label='$key'>";
foreach ($value as $selectValue => $title) {
$options[] = "<option value = '$selectValue'>" . $title . '</option>'.PHP_EOL ;
}
$options[] = "</optgroup>";
}
}
$selectTag = '<select ' . $this->setAttribute($attributs) . '>'.PHP_EOL;
return $selectTag . implode($options, ' ') . '</select>';
}
this function is not correct. how to resolve that? thanks.
Try this (hopefully helps you)
public function select( $name, $values, $default='0', $attributs=[]){
$options = [];
$selected = '';
echo count($values);
foreach ($values as $key => $value) {
if (!is_array($value)) {
if ( $key === $default ) $selected="selected='selected'";
$options[] = "<option value = '$key' $selected>" . $value . '</option>'.PHP_EOL ;
$selected = '';
}
else {
$options[] = "<optgroup label='$key'>";
foreach ($value as $selectValue => $title) {
$options[] = "<option value = '$selectValue'>" . $title . '</option>'.PHP_EOL ;
}
$options[] = "</optgroup>";
}
}
$selectTag = '<select ' . $this->setAttribute($attributs) . '>'.PHP_EOL;
return $selectTag . implode($options, ' ') . '</select>';
}
I like to sort an associative array into two div's based on a value.
Here's what I have now:
function showDivs($array) {
/*
* sort en group by
*/
$luxury = false;
$no_luxury = false;
$return = '';
while (list($key, $value) = each($array)) {
if ($value["MinimumRate"] < 500) {
if ($no_luxury === false) {
$return .= '<div id="no_luxury" >';
}
$return .= $value['Description'] . " : " . $value["MinimumRate"] . "<br />";
if ($no_luxury === false) {
$return .='</div>';
$no_luxury = true;
}
}
if ($value["MinimumRate"] > 500) {
if ($luxury === false) {
$return .='<div id="luxury" >';
}
$return .= $value['Description'] . " : " . $value["MinimumRate"] . "<br />";
if ($luxury === false) {
$return .='</div>';
$luxury = true;
}
}
}
return $return;
}
My code doesn't work correctly.
The div is being created and closed on the first item only. I think you meant to open it on start and close it in the end. Try this:
function showDivs($array) {
/*
* sort en group by
*/
$luxury = array();
$not_luxury = array();
foreach ($array as $value) {
if ($value["MinimumRate"] > 500) {
$luxury[] = $value;
} else {
$not_luxury[] = $value;
}
}
$return = '<div id="no_luxury" >';
foreach ($luxury as $value) {
$return .= $value['Description'] . " : " . $value["MinimumRate"] . "<br />";
}
$return .= '</div>';
$return .= '<div id="luxury" >';
foreach ($luxury as $value) {
$return .= $value['Description'] . " : " . $value["MinimumRate"] . "<br />";
}
$return .= '</div>';
return $return;
}
If the problem is when MinimumRate = 500, you whould do:
if ($value["MinimumRate"] <= 500) // this is your first 'if' in your code
or
if ($value["MinimumRate"] >= 500) // this is the second 'if' in your code
I have a function which performs a foreach loop on an array from a database.
see foreach ($teamarray AS $key => $value){$teamgo .= $value[1]." ".$value[2]."<br/>";
Problem is, sometimes there may be no data set, which throws an error when the loop hits that field.
How can i catch/suppress this error?
function GetUnsubmitted($coach){
$push .= "<div id=unsubmitted><h2>Check which event/teams you want to process and click submit</h2>";
$push .= "<form action=\"submit.php\" method=POST>";
$result = mysql_query("SELECT * FROM `ptable` WHERE coach = '$_SESSION[username]' AND status = '1' ORDER BY status ASC") or trigger_error(mysql_error());
while($row = mysql_fetch_array($result)){
foreach($row AS $key => $value) { $row[$key] = stripslashes($value); }
$id = $row['id'];
$teampre = $row['team'];
$eventpre = $row['event'];
$statuspre = $row['status'];
$eventarray = DecodeEvent($eventpre);
$event = $eventarray[0];
$cat = $eventarray[1];
$subcat = $eventarray[2];
$division = $eventarray[3];
$type = $eventarray[4];
$teamarray = DecodeTeam($teampre);
$price = GetPrice($type, "nat");
$teamcount = count($teamarray);
$total = $price * $teamcount;
$teamgo = "";
foreach ($teamarray AS $key => $value){
$teamgo .= $value[1]." ".$value[2]."<br/>";
if($statuspre == "1"){
$statuscolor = "#FFCC99";
$statusmsg = "unsubmitted <a href=delsub.php?id=$id onClick=\"return confirm('Are you sure you want to delete this submission?');\"><img src=images/del.png border=0 />";
} elseif($statuspre == "2"){
$statuscolor = "#FFCC66";
$statusmsg = "awaiting confirmation";
} elseif($statuspre == "3"){
$statuscolor = "#66CC66";
$statusmsg = "confirmed";
}
}
$push .= "<div id=submission><div id=event style=\"background-color:$statuscolor;\"><h1>$event</h1><span id=status>$statusmsg</span></div><div id=subinfo><span id=dropdown><img src=images/expand.png border=0></span><h2>$cat >> $subcat >> $division >> $type</h2> <div id=team style=\"display:none;\">$teamgo<br />$price - $total<div id=controls></div></div></div></div>";
$pid .= $id;
$rtotal .= "$total,";
}
$stotal = explode(",", $rtotal);
$gtotal = array_sum($stotal);
$push .= "<div style=\"text-align:right;\"><div id=total>Total - <em>$gtotal</em></div><br><input type=image src=images/paynow.png alt=\"Pay Now\"></form> <a href=submit2.php?$pid&$pidarray><img src=images/mailfax.png width=138px height=41px border=0></a></div></div>";
return $push;
}
If possible id like it to say "no team selected" and stop.
You can write so:
foreach ((array)$teamarray as $key => $value) {
$teamgo .= $value[1] . " " . $value[2] . "<br/>";
//...
}
foreach expects array. So the really correct way is to ensure that you deal with array before try to iterate, like this:
if (is_array($teamarray) && count($teamarray)) {
foreach ((array)$teamarray as $key => $value) {
$teamgo .= $value[1] . " " . $value[2] . "<br/>";
//...
}
}
You also can check is_iterable since PHP 7.1.
if ($array) {
foreach ($array as $k => $v) {
...
}
} else {
echo 'No team selected';
// exit from loop
}
Your exit from loop will be a "return", or a "break n" (n is the levels to break for) or continue... it depends on your logic.
if ($value !== null && count($value) >= 3) {
$teamgo .= $value[1] . $value[2]
}
<insert puzzled smiley here>
foreach($row AS $key => $value) {
if ($value) {
$row[$key] = stripslashes($value);
}
}
And:
foreach ($teamarray AS $key => $value){
if ($value && sizeof($value) > 2) {
$teamgo .= $value[1] . $value[2]
}
}
Is this it?
Just do a test if $teamarray actually is an array:
if (is_array($teamarray)) {
foreach ($teamarray as $key => $value) {
// …
}
}
Or you could do:
$teamarray = isset($teamarray) ? $teamarray : array();
Just prior to the loop in a nice tidy line, and it would ensure that you have the variable set to an empty array which would cause it to skip the foreach().