PDO prepared statements increment/decrement by bool - mysql

In my POST file, I need to change the order of my items. I basically send a parameter called moveDown which is a bool, to check whether the item is higher or lower. So, I got this to get my parameter:
$moveDown = filter_input(INPUT_POST, 'moveDown', FILTER_VALIDATE_BOOLEAN);
I got another parameter for the item id. This is just a simple filter_input, nothing special.
$itemId = filter_input(INPUT_POST, 'itemId', FILTER_SANITIZE_NUMBER_INT);
Now, I need to use that variable to define whether to increment or decrement the order column. So I tried this:
$changeOrderStmt = $cmsDbh->prepare('UPDATE `items` SET `order` = ? WHERE `id` = ?');
$changeOrderStmt->execute(array('`order` ' . ($moveDown ? '+' : '-') . ' 1', $itemId));
However, now the order column is 0. I really don't want to concatenate the query string and rather use PDO params. Is this possible or not?

Related

Symfony Doctrine: Search in simple_array

I got values stored in my database column field as value1,value2,value3,value4, so a simple_array column.
So i'm using Doctrine to make a search using this:
$searchQuery = $this->getDoctrine()
->getRepository('AppBundle:Ads')
->createQueryBuilder('p')
->andWhere("p.vals <= :value2")
->setParameter('value2', $request->query->get('value2'));
->orderBy("p.creationtime", 'DESC');
So expecting value2 is in the 2nd position of a simple array like value1,value2,value3, how can i ask QueryBuilder to select the second value in the string?
I think this query try to get all the values in p.vals, results are not right, shound select just one.
How can I select eg. the 2nd value in p.vals?
I believe you cannot access nth item of an array column using pure Mysql since the data is serialized, in order to do it I'd create a simple function
public function getItemFromArray(array $array, $index)
{
return isset($array[$index]) ? $array[$index] : null;
}
And if you want to find item with condition use
array_filter()

Prepared statement fetches all the results in db, but not one I ask for

Trying to make my blog secure and learning prepared statements.
Although I set the variable, I still get all the entries from database. $escapedGet is real variable when I print it out. It's obviously a rookie mistake, but I cant seem to find an answer.
I need to get the data where postlink is $escapedGet not all the data.
$escapedGet = mysql_real_escape_string($_GET['article']);
// Create statement object
$stmt = $con->stmt_init();
// Create a prepared statement
if($stmt->prepare("SELECT `title`, `description`, `keywords` FROM `post` WHERE `postlink` = ?")) {
// Bind your variable to replace the ?
$stmt->bind_param('i', $postlink);
// Set your variable
$postlink = $escapedGet;
// Execute query
$stmt->execute();
$stmt->bind_result($articleTitle, $articleDescription, $articleKeywords);
while($stmt->fetch()) {
echo $articleTitle, $articleDescription, $articleKeywords;
}
// Close statement object
$stmt->close();
}
just tryed this: echo $escapedGet;
echo $_Get['artcile']
and got - some_other
thats the same entry that I have saved in database as postlink
tried to shande postlink to id, and then it worked. but why not with postlink tab?
When you are binding your data using 'i' modifier, it gets bound as integer.
Means string will be cast to 0 in the final statement.
But as mysql does type casting, your strings become zeroes in this query:
SELECT title FROM post WHERE postlink = 0;
try it and see - for the textual postlinks you will have all your records returned (as well as a bunch of warnings).
So, bind strings using s modifier, not i

mySQL $REQUEST defaults

mySQL NOOB question:
Table has a column = AgeGroup. It is populated with the following data options: U40, 40-44, 45-49, 50-54, 55-59, 60+.
I have a form which allows the user to select the 'Gender' and 'AgeGroup' they wish to view. This then uses a "WHERE" clause of "SELECT" SQL query. It uses in the following format:
FROM
#__test1
WHERE
EventName = '2011EoSummer' AND
Gender = {$REQUEST:Gender};
if(isset($_REQUEST['Age'])) AND AgeGroup = {$_REQUEST['Age']}
In the form, there is a option to get all ages via "Overall" but there is no data called "Overall" in the AgeGroup column. Overall should default to ALL age groups, but I don't know how this would read in the SQL query.
Example 1 URL: /&Gender=Men&AgeGroup=U40 => would display data in 'U40' 'Men'
Example 2 URL: /&Gender=Men&Age=Overall => would display ALL Age data
If I'm reading this right, when you have "overall" selected you want to return all the age groups (so as not to limit by any age group)?
If so you need to remove the AgeGroup clause in your SQL statment.
<?PHP
$sql = "SELECT * FROM tbl WHERE Gender = {$_REQUEST['gender']}";
if(isset($_REQUEST['age']))
{
$sql.= " AND AgeGroup = {$_REQUEST['age']}"
}
?>
This will default to overall, so you may want to change the logic appropriately, hope I got what you were after, if not ignore it!
Also as a side note $_REQUEST isn't the best to use, if your using a form as your action collector set it to post and use $_POST instead, if you cant use $_GET to pull your data out of the url instead of request.
Edit: Added in brackets to make it easier to read.

Doctrine query returns extra field in result

I have a Doctrine query;
$q = Doctrine_Query::create()->select('s.monthly_volume')
->from('SearchVolume s')
->innerJoin('s.Keywords k')
->where('k.group_id = ?',array($group_id));
I just want it to return the monthly_volume value in the result array. It currently returns monthly_volume and id, I don't want it to return the id in result.
Doctrine automatically adds the primary key field to the results in almost every type of hydration mode.
In a case like this where you want a simple array and only have a single field being selected, the answer is the Single Scalar Hydration mode. Use it like this:
$q = Doctrine_Query::create()->select('s.monthly_volume')
->from('SearchVolume s')
->innerJoin('s.Keywords k')
->where('k.group_id = ?');
$monthly_volumes = $q->execute(array($group_id), Doctrine_Core::HYDRATE_SINGLE_SCALAR);
You should find that $monthly_volumes is a simple one-dimensional array containing only the value(s) you wanted.

Perl Mysql - How to search for specific data based on one "main" match?

User Form Input - City
User Form Input - Venue
User Form Input - Cover
User Form Input - Time
User Form Input - Date
User Form Input - Number1
User Form Input - Number2
(if any are blank they are coverted to '*' on the way in. But could be whatever works.)
my $grabgig = $hookup->prepare(qq{SELECT `VenueNumber`,`Venue`,`CoverCharge`,`SetLength`,`City`,`Owner`,`Date`,`Time`,`Image1`,`Number`
FROM `gigs`
WHERE VenueNumber > ? AND `City` = ? AND `Venue` = ? AND `CoverCharge` = ?
AND Date = ? AND `Number` > ? AND `Number` < ?
AND `Time` LIKE ? LIMIT ?,?});
##########################################
$grabgig->execute('100',$city,$venue,$cover,'*',$number1,$number2,?,'0','6')
or die "Did not execute";
That is a basic example above.
I want to be able to return results based on the City Input.
If more input is present, then narrow down results accordingly.
But the query returns nothing if fields are empty (*).
I tried wildcards and so on then, I experimented with LIKE and NOT LIKE.
This seemingly simple search is driving me nuts.
Can someone help this newbie?
OK, I'm pretty unsure what you mean, BUT, my best undererstanding of what you're trying to do is to query like you do now BUT if a particular field is not populated in the form, to avoid adding that field to the where clause; as opposed to current query which instead does and myField="*".
Correct?
If that's so, you need to build your query, and replacement list, in pieces:
my $sql = qq{SELECT MY_FIELD_LIST_TOO_LAZY_TO_TYPE FROM `gigs` WHERE 2=2};
my #replacement_values = (); # These go into execute() instead of "?"s
if ($city ne "*") {
$sql .= qq[AND city = ?];
push #replacement_values, $city;
}
if ($number1 ne "*") {
$sql .= qq[AND number > ?];
push #replacement_values, $number1;
}
# ... more values processed the same way
my $grabgig = $hookup->prepare($sql);
$grabgig->execute(#replacement_values) or die "Did not execute";
If you want to do it more intelligently (i.e. to generalize), you will have the form fields in a hash; have a config hash mapping the form field name to the DB column name and the operator, and instead do the above as:
my %fields = (
city => ["city" , "="]
,number1 => ["number", ">"]
,number2 => ["number", "<"]
);
my $sql = qq{SELECT MY_FIELD_LIST_TOO_LAZY_TO_TYPE FROM `gigs` WHERE 2=2};
my #replacement_values = (); # These go into execute() instead of "?"s
foreach my $field (keys %form_data) {
next unless exists $fields{$field};
if ($form_data{$field} ne "*") {
$sql .= qq[ AND $fields{$field}->[0] $fields{$field}->[1] ?];
push #replacement_values, $form_data{$field};
}
}
my $grabgig = $hookup->prepare($sql);
$grabgig->execute(#replacement_values) or die "Did not execute";
I am assuming that you want to construct a query where only a few input parameters have valid values and the rest are undefined. If that is indeed what you want, here is what you could do: Construct the query dynamically. Here are the steps you could take assuming you are using CGI.pm and assuming that the where clause is just a series of "this = that" - In your case you have different operators - but the idea is the same.
First construct a "where" string from the CGI query parameter (Sorry untested code):
my $qrystr = '';
foreach ($query->param) {
if (my $val = $query->param($_)) {
$qrystr .= "where $_ = " . $dbh->quote($val) . ' and ';
}
}
$qrystr .= "where 1 = 1";
Now you can just prepare and execute the query : "select * from table $qrystr"
If you want automatic quoting you will have to use bind parameters which is an easy extension of the code above
Update There was a missing "where" in the last true clause "1 = 1" - Sorry, added it now
Sorry, the formatting bar was not appearing so, I rebooted. Now I cannot edit my question or comment.
What I am trying to do is provide a search for the users.
They select a city from a dropdown then some optional data can be entered / selected to narrow the results.
The optional data May or May Not be present in the table, could be a blank field.
I would like the results to show based on the selected criteria of the search in that City.
So, WHERE selected "input city" = "tables city column" look for the other options (ignore that particular criteria if field is empty) and return any matches that exist for that city.
I am then pushing into array in a While for output display.
I guess it would be like a car query. Select make where doors = 2 and color = red and engine = hamsterwheel but, the color field may be empty in the database..