I'm attempting to replace a chunk of code that has hard-coded field names with one that gets the field names dynamically from the query and have it mostly working but only up to a point, then I get an error. This is the code that I am trying to replace with a foreach loop of field names which creates the WHERE clause:
if (strlen($Where) == 0 ) $Where .= " WHERE (";
$Where .= "(" . $StorageArea . ")";
if (strlen($Where) > 0 ) $Where .= " AND ";
$Where .= " (" . $StorageArea . ")";
if (strlen($Location))
$Where .= " OR (". $Location .")";
if (strlen($Size))
$Where .= " OR (". $Size .")";
if (strlen($Winery))
$Where .= " OR (". $Winery .")";
if (strlen($Brand))
$Where .= " OR (". $Brand .")";
if (strlen($Appellation))
$Where .= " OR (". $Appellation .")";
if (strlen($ReleaseYear))
$Where .= " OR (". $ReleaseYear .")";
if (strlen($Varietal))
$Where .= " OR (". $Varietal .")";
if (strlen($Status))
$Where .= " OR (". $Status .")";
if (strlen($CountryName))
$Where .= " OR (". $CountryName .")";
$Where .= " ) ";
Unless there is a typo that I've missed, I don't see the problem here in this (so far untested) foreach loop so can can anyone please advise? TO keep it simply and to avoid lots of if else it uses both single line conditionals and more conventional if elseif statements using : and endif rather than { and }. Is there some limitation of this type of conditional? I had always thought that they were directly interchangeable but apparently not.
$i = 1;
$len = count(array_keys($queryField));
foreach (array_keys($queryField) as $row) :
$i++:
if ($row === 'ID') continue;
if ($i == 1) :
if (strlen($Where) == 1) $Where .= " WHERE (";
$Where .= " (" . $$row . ") ";
if (strlen($Where) > 1) $Where .= " AND ";
elseif ($i > 1 && $i != $len) :
if (strlen($$row)) $Where .= " OR (". $$row .")";
elseif ($i == $len) :
if (strlen($$row)) $Where .= " OR (". $$row .")";
$Where .= ")";
endif;
endforeach;
The error is Parse error: syntax error, unexpected ':' which it is giving on the elseif ($i > 1 && $i != $len) : line. I'm not sure yet if this will even do what I want but I can't try it until I get it working.
$queryField is a query with results as below and the function grabs the field names from it
Array
(
[ID] => 3
[StorageArea] => CAB-1
[Size] =>
[Winery] => Name
[Brand] => Fanciful Name
[Appellation] =>
[ReleaseYear] => 2008
[Varietal] => Cuvée
[Status] => Library
[CountryName] =>
)
Thanks to the comments and answer received to get the above working, I realized it does not do what I had expected so I rethought it and came up with something completely different that does work. Since it's not exactly an answer, I am posting it here as a quasi-answer and the fun part was in trying to know how many times the inner foreach was looped. There are other sections to this too for All Keywords or Exact Phrase but this bit is very similar to those so no need to post all of them. $Where is being declared earlier in the function from which this code was extracted so it's not shown here.
For my basic question about mixing conditional types, apparently mixing if and endif with single line conditionals isn't possible and that { and } are recommended for non-HTML-based programming but I really wanted to keep everything the same so for this version, all are single-line conditionals within the foreach loops so no errors.
$keywords = explode(" ", trim($keyword));
// Get number of passes for inner loop
// Subtract one because ID column is not being used
$len = ((count(array_keys($queryField))-1) * count($keywords));
$i = - (count($keywords)); // Subtract number of keywords
if (strlen($keyword)) :
// Any Keywords
foreach ($keywords as $keyword) :
$keyword = str_replace("'", "''", trim($keyword));
foreach (array_keys($queryField) as $column) :
$i++;
if ($column === 'ID') continue;
if (strlen($Where) == 0) $Where .= " WHERE (";
if ($i != $len) $Where .= "(`$column` LIKE '%" . $keyword . "%') OR ";
if ($i == $len) $Where .= "(`$column` LIKE '%" . $keyword . "%') ";
endforeach;
endforeach;
endif;
There are a few typos there but most of all for this to work you'd have to break up your code like so:
<?php
$i = 1;
$len = count(array_keys($queryField));
?>
<?php
foreach (array_keys($queryField) as $row) :
$i++;
if ($row === 'ID') continue;
?>
<?php
if ($i == 1) :
if (strlen($Where) == 1) $Where .= " WHERE (";
$Where .= " (" . $$row . ") ";
if (strlen($Where) > 1) $Where .= " AND ";
?>
<?php
elseif ($i > 1 && $i != $len) :
if (strlen($$row)) $Where .= " OR (". $$row .")";
?>
<?php
elseif ($i == $len) :
if (strlen($$row)) $Where .= " OR (". $$row .")";
$Where .= ")";
?>
<?php
endif;
endforeach;
?>
Unfortunately it's not possible to mix conditional statements as shown in your code.
If this code isn't supposed to be used in an HTML template i suggest sticking to {} brackets:
$i = 1;
$len = count(array_keys($queryField));
foreach (array_keys($queryField) as $row) {
$i++;
if ($row === 'ID') continue;
if ($i == 1) {
if (strlen($Where) == 1) $Where .= " WHERE (";
$Where .= " (" . $$row . ") ";
if (strlen($Where) > 1) $Where .= " AND ";
}
elseif ($i > 1 && $i != $len)
if (strlen($$row)) $Where .= " OR (". $$row .")";
elseif ($i == $len) {
if (strlen($$row)) $Where .= " OR (". $$row .")";
$Where .= ")";
}
}
Related
I've caught a snag with a set up that I'm hoping to achieve in my php code. This code pulls the categories that listings are grouped in to and displays it in the screen as such:
Featured in Home Cooking, Fresh Fruits, Dinner, Quick Meals
What I'm hoping to achieve is this:
Featured in Home Cooking, Fresh Fruits, Dinner and Quick Meals Collections
If you take notice, the and before the word Quick Meals and the Collections after it are the changes I need made. I'm just starting to learn php, and I can't make this adjustment without breaking it. Here is what I'm working with:
Many thanks if you are able to save me from this. I'd imagine it's nothing too difficult.
$permalink = get_permalink( $id );
$seo = get_the_title()." - offers: ";
$Category_links = ' Featured in ';
$term_list_category = wp_get_post_terms(get_the_ID(), 'listings_categories', array("fields" => "ids"));
$i = 0;
$count = count($term_list_category);
if ( $count > 0 ){
foreach ( $term_list_category as $term_category ) {
$thisCat = get_term_by( 'id', $term_category, 'listings_categories');
$url = '<a class="listing-links" href="/listings/'.$thisCat->{'slug'}.'/'.'" title="'.$thisCat->{'name'}.' - Food listings " >'.$thisCat->{'name'}.'</a>';
$i ++;
$seo .= " " . $thisCat->{'name'} . "";
$Category_links .= " " . $url . "";
if ($count > 1 && $count !== $i) {$Category_links .= ", "; $seo .= ", "; }
}
}
Below this line ---> $Category_links .= " " . $url . "";
Change the code to...
if($count-1 == $i){
$Category_links .= " and "; $seo .= ", ";
}elseif($count > 1 && $count !== $i){
$Category_links .= ", "; $seo .= ", ";
}
}
$Category_links .= " Collections";
}
Basically you are checking to see if you are at the next to last element in the array ($count-1) and inserting an " and " instead of a ", "
Then outside the loop you can add $Category_links .= " Collections"; to add to the end of the output.
I would prefer simple array manipulation for string output;
Basic
//example of assigning those categories
$cats = array('Cat 1', 'Cat 2', 'Cat 3', 'Cat 4');
$ccats = count($cats);
foreach($cats as $i => $cat)
{
//apply slug as needed here
$cats[$i] = '' . $cat . '';
if($i < ($ccats-1))
{
$cats[$i] .= ',';
}
}
array_splice($cats, ($ccats-1), 0, array('and'));
$cats[] = ' Collections';
echo implode($cats, ' ');
Implementation (untested)
$cats = wp_get_post_terms(get_the_ID(), 'listings_categories', array("fields" => "ids"));
$ccats = count($cats);
$vcats = array();
foreach($cats as $i => $cat)
{
//apply slug & name as needed here
$vcats[$i] = '<a class="listing-links" href="/listing/' . $cat->slug . '" title="' . $cat->name . '">' . $cat->name . '</a>';
if($i < ($ccats-1))
{
$vcats[$i] .= ',';
}
}
array_splice($vcats, ($ccats-1), 0, array('and'));
echo 'Featured in ' . implode($vcats, ' ') . ' Collections';
Hope this helps
I am trying to make a query having multiple select boxes, User can select one or multiple values from the drop down menu, But its not working it works only if user select one select box if user tries to select two or more select box values it is not able to display the where clause properly. I saw this code in another web site but not able to pick it properly, If some one can help in understanding or simplifying...
if ($office != '') {
$where = ($where == '') ? 'WHERE ' : 'AND ';
$where .= "adpno = '$office'";
}
if ($sector!= '') {
$where = ($where == '') ? 'WHERE ' : 'AND ';
$where .= "sector= '$sector'";
}
if ($subsector!= '') {
$where = ($where == '') ? 'WHERE ' : 'AND ';
$where .= "subsector= '$subsector'";
}
mysql_query('SELECT * FROM sometable ' . $where);
Make sure to add a space before and after AND and WHERE!
In your code when more than one condition is used, the query is probably built as: SELECT * FROM sometable WHERE subsector=3AND sector=5 (note the lack of space before AND).
In your code sample, there is a space only after AND/WHERE. Note that MySQL ignores whitespaces in the query, so don't worry if it ends up with a double space sometimes. Just make sure to have at least one space, separating all elements of the query.
EDIT: Also, make sure that each if concatenates to the previous WHERE clause instead of overwriting it. So:
if ($office != '') {
$where .= ($where == '') ? ' WHERE ' : ' AND ';
$where .= "adpno = '$office'";
}
if ($sector!= '') {
$where .= ($where == '') ? ' WHERE ' : ' AND ';
$where .= "sector= '$sector'";
}
if ($subsector!= '') {
$where .= ($where == '') ? ' WHERE ' : ' AND ';
$where .= "subsector= '$subsector'";
}
mysql_query('SELECT * FROM sometable ' . $where);
I'd try something like this:
$conditions = '';
if ($tmp = #$_GET['office'])
$conditions .= ($conditions != '' ? ' AND ' : '') . 'office = \'' . mysql_escape_string($tmp) . '\'';
if ($tmp = #$_GET['sector'])
$conditions .= ($conditions != '' ? ' AND ' : '') . 'sector = \'' . mysql_escape_string($tmp) . '\'';
// ...
mysql_query('SELECT * FROM sometable' . ($conditions != '' ? ' WHERE ' . $conditions : '') . 'M');
If you've got more than just two or three fields, a foreach loop might be better suited:
$conditions = '';
$fields = array('office', 'sector', 'subsector', /*...*/);
foreach ($fields as $field)
if ($tmp = #$_GET[$field])
$conditions .= ($conditions != '' ? ' AND ' : '') . $field . ' = \'' . mysql_escape_string($tmp) . '\'';
mysql_query('SELECT * FROM sometable' . ($conditions != '' ? ' WHERE ' . $conditions : '') . 'M');
You could even simplify code a bit by always having at least one condition (untested, but should work):
$conditions = 'TRUE';
$fields = array('office', 'sector', 'subsector', /*...*/);
foreach ($fields as $field)
if ($tmp = #$_GET[$field])
$conditions .= ' AND ' . $field . ' = \'' . mysql_escape_string($tmp) . '\'';
mysql_query('SELECT * FROM sometable WHERE ' . $conditions . ';'));
$fields = array('sector' , 'subsector' , 'office');
$query = '';
foreach($fields as $field)
{
if($query != '')
$query .= ' AND ';
if( $input[$field] != '')
$query .= $field ." = '". $input[$field] ."'";
}
I would recommend you to use mysqli or pdo instead of mysql.
$input is an array of the input values after you've made "security checks",
for instance: mysql_escape_string and htmlspecialchars
I try to call a model from one of my Joomla controller but that doesn't seem to work.
class TieraerzteControllerDatatable extends JControllerLegacy
{
/**
* display task
*
* #return void
*/
function display($cachable = false)
{
// set default view if not set
$input = JFactory::getApplication()->input;
$model = $this->getModel('datatable');
$model->getTableData('grumpi_tieraerzte', 'id', array('id','name','strasse','telefon','fax'));
die();
}
}
In my model I placed a var_dump but it is not accessed. How can I debug my model call in controller?
I try to access the models return with the following url /administrator/index.php?option=com_tieraerzte&task=datatable.display&{arguments for the model}
trying to debug my codes piece by piece seems like the model is accessed and this code is causing the problem
// Paging
$sLimit = "";
if (isset(JRequest::getVar('iDisplayStart')) && JRequest::getVar('iDisplayLength') != '-1')
{
$sLimit = "LIMIT " . intval(JRequest::getVar('iDisplayStart')) . ", " . intval(JRequest::getVar('iDisplayLength'));
}
The whole method:
public function getTableData($table, $index_column, $columns)
{
$db = JFactory::getDbo();
$query = $db->getQuery(true);
// Paging
$sLimit = "";
if (isset(JRequest::getVar('iDisplayStart')) && JRequest::getVar('iDisplayLength') != '-1')
{
$sLimit = "LIMIT " . intval(JRequest::getVar('iDisplayStart')) . ", " . intval(JRequest::getVar('iDisplayLength'));
}
// Ordering
$sOrder = "";
if (isset(JRequest::getVar('iSortCol_0')))
{
$sOrder = "ORDER BY ";
for ($i = 0; $i < intval(JRequest::getVar('iSortingCols')); $i++)
{
if (JRequest::getVar('bSortable_' . intval(JRequest::getVar('iSortCol_' . $i))) == "true")
{
$sortDir = (strcasecmp(JRequest::getVar('sSortDir_' . $i), 'ASC') == 0) ? 'ASC' : 'DESC';
$sOrder .= "`" . $columns[intval(JRequest::getVar('iSortCol_' . $i))] . "` " . $sortDir . ", ";
}
}
$sOrder = substr_replace($sOrder, "", -1);
if ($sOrder == "ORDER BY") {
$sOrder = "";
}
}
/*
* Filtering
* NOTE this does not match the built-in DataTables filtering which does it
* word by word on any field. It's possible to do here, but concerned about efficiency
* on very large tables, and MySQL's regex functionality is very limited
*/
$sWhere = "";
if (isset(JRequest::getVar('sSearch')) && JRequest::getVar('sSearch') != "")
{
$like = '%' . JRequest::getVar('sSearch') . '%';
$sWhere = "WHERE (";
for ($i = 0; $i < count($columns); $i++)
{
if (isset(JRequest::getVar('bSearchable_' . $i)) && JRequest::getVar('bSearchable_' . $i) == "true")
{
$sWhere .= "`" . $columns[$i] . "` LIKE '" . $like . "' OR ";
}
}
$sWhere = substr_replace($sWhere, "", -3);
$sWhere .= ')';
}
// Individual column filtering
for ($i = 0; $i < count($columns); $i++)
{
if (isset(JRequest::getVar('bSearchable_' . $i)) && JRequest::getVar('bSearchable_' . $i) == "true" && JRequest::getVar('sSearch_' . $i) != '')
{
if ($sWhere == "")
{
$sWhere = "WHERE ";
} else {
$sWhere .= " AND ";
}
$sWhere .= "`" . $columns[$i] . "` LIKE ? " . $i . " ";
}
}
// SQL queries get data to display
$sQuery = "SELECT SQL_CALC_FOUND_ROWS `" . str_replace(" , ", " ", implode("`, `", $columns)) . "` FROM `" . $table . "` " . $sWhere . " " . $sOrder . " " . $sLimit;
$statement = $this->_db->prepare($sQuery);
// Bind parameters
if (isset(JRequest::getVar('sSearch')) && JRequest::getVar('sSearch') != "")
{
$statement->bind_param('s', $like);
}
for ($i = 0; $i < count($columns); $i++)
{
if (isset(JRequest::getVar('bSearchable_' . $i)) && JRequest::getVar('bSearchable_' . $i) == "true" && JRequest::getVar('sSearch_' . $i) != '')
{
$statement->bind_param('s' . $i, '%' . $_GET['sSearch_' . $i] . '%');
}
}
$db->setQuery($sQuery);
$res = $db->loadObjectList();
$rResult = array();
foreach ($res as $row)
{
$rResult[] = $row;
}
$iFilteredTotal = current($db->setQuery('SELECT FOUND_ROWS()')->loadResultArray());
// Get total number of rows in table
$sQuery = "SELECT COUNT(`" . $index_column . "`) FROM `" . $table . "`";
$iTotal = current($db->setQuery($sQuery));
// Output
$output = array(
"sEcho" => intval($_GET['sEcho']),
"iTotalRecords" => $iTotal,
"iTotalDisplayRecords" => $iFilteredTotal,
"aaData" => array()
);
// Return array of values
foreach ($rResult as $aRow)
{
$row = array();
array_push($row, '<input type="checkbox" id="someCheckbox" name="someCheckbox" />');
for ($i = 0; $i < count($columns); $i++)
{
//var_dump($aRow->$columns[$i]);
if ($columns[$i] != '')
{
$row[] = $aRow->$columns[$i];
}
}
array_push($row, '
<div class="btn-group" id="status">
<input type="button" class="btn b1" value="On">
<input type="button" class="btn b0 btn-danger" value="Off">
</div>
');
array_push($row, '
<div class="clearfix">
<div class="label label-important" style="padding:6px 9px; margin-right:5px"><span class="icon-trash"></span></div>
<div class="label label-success" style="padding:6px 9px"><span class="icon-cog"></span></div>
</div>
');
$output['aaData'][] = $row;
}
echo json_encode($output);
}
Make sure $model inside the controller is not null. If it's not null, than the problem is somewhere in the model's method called.
if $model is null, somehow the model you are calling is not loaded. Temporary try just to include the file with require_once JPATH_COMPONENT . '/models/datatable.php'
Using an html FORM let's convert $core in 100 and $mhz in 1000
emag and koyos are table rows
So if $core is set $parameters['emag'] = "$core"; is emag=100else it is null
AND and WHERE are dinamically setted to appear, so the problem is that I collect all data of variables in $parameters[] and foreach() them.
With my code I am get exactly what $core is. This is the code:
if (!empty($core)) {
$parameters['emag'] = "$core";
}
if (!empty($mhz)) {
$parameters['koyos'] = $mhz;
}
$sql = "SELECT * FROM $tbl_name WHERE 1=1 ";
if (!empty($parameters)) {
foreach ($parameters as $k => $v) {
$sql .= " AND " . $k . "='" . $v . "'";
}
}
$sql .= " ORDER BY emag, performanta_cpu_core DESC, performanta_cpu DESC LIMIT $start, $limit";
And it is results just rows with emag=100, but I have need all numbers equals or little than 100 not just 100
Your query conditions, based on the data you've provided, are:
WHERE 1=1 AND emag = '100' AND koyos = '1000'
And so obviously will only show rows where emag = 100. If you want to show all those up to 100 then change = to <= when the table name is emag:
foreach ($parameters as $k => $v) {
if ($k == 'emag')
{
$sql .= " AND " . $k . "<='" . $v . "'";
}
else
{
$sql .= " AND " . $k . "='" . $v . "'";
}
}
Try this:
foreach ($parameters as $k => $v) {
if ($k == 'emag') {
$sql .= " AND " . $k . "<='" . $v . "'";
continue;
}
$sql .= " AND " . $k . "='" . $v . "'";
}
Trying to loop through a querystring in php but only getting last value. What should I be doing to get all values?
example:
querystring = ?style=ranch&style=barn&style=colonial
php:
$sqlStyle = "SELECT DISTINCT COUNT(*) as count FROM houses_single ";
$i = 1;
foreach ($_GET as $key => $value) {
if ($i == 1){
$sqlStyle .= "where ";
}else{
$sqlStyle .= " and ";
}
$sqlStyle .= $key . " like '%" . $value ."%'";
$i++;
}
echo $sqlStyle;
Result:
SELECT DISTINCT COUNT(*) as count FROM houses_single Where Houses like '%colonial%'
The query parameter "style" is an array in this case and must be identified by square brackets - if not, the last key=value pair will overwrite the others.
?style[]=ranch&style[]=barn&style[]=colonial
$_GET['style'] is an array then you can loop over by using foreach:
foreach ($_GET['style'] as $value) {
// ...
}
if 'style' is not the only parameter you want to add, you can use a is_array() check in the foreach loop:
foreach ($_GET as $key => $value) {
if ($i == 1){
$sqlStyle .= "where ";
}else{
$sqlStyle .= " and ";
}
if(is_array($value)) {
$sec = array();
foreach($value as $second_level) {
$sec[] = $key . " LIKE '%" . $second_level."%'";
}
$sqlStyle .= implode(' AND ', $sec);
}
else {
$sqlStyle .= $key . " LIKE '%" . $value ."%'";
}
$i++;
}
echo $sqlStyle;
alternative without foreach:
<?php
$statement = "SELECT DISTINCT COUNT(*) as count FROM `houses_single`";
if(is_array($_GET)) {
$statement .= ' WHERE';
// create copy to keep the $_GET array
$add_where = $_GET;
array_walk(function($elem,$key){
is_array($elem) {
return implode(' AND ', array_map(function($sec) using ($key) {
return "$key LIKE '%$sec%'";
}, $elem);
}
else {
return "$key LIKE '%$elem%'";
}
},$add_where);
$statement .= implode(' AND ', $add_where);
}
(codes are untested)
Sidenode about safety: I hope you won't use this code snippet you provided in productive environment without any escaping of the parameters.