PHP Function to validate setting

As I said,

First, for the images which weight is less than 2 megabytes, it’s ok to send them as strings.

Second, personally I’d never store big images in database at all, as for the web development it’s just insane.

And third, I already agreed, that for the blobs of more than 2 megs in size separate binding is the only way, so I would usr it, if it ever happens.

I think we’re a little bit off topic now but thanks for helping.

I have stayed well clear of OOP for 7 years because I simply don’t understand it. However given that I want to learn C# in the coming few years I’m going to give it another try. I will write out some OOP PHP and PDO and come back once I have a noddy script.

Keep in mind that you don’t need to know how to write OOP to use it.

True, a basic understanding helps and knowing the syntax is essential, but there are a lot of OOP classes you can use now without needing to fuss much.

I suggest you turn on error reporting and display and give it a try (in your dev environment only please). The error messages will help you to learn what needs to be done.

I am rebuilding my dev box as we speak but I am hoping I’ve got the first part right :stuck_out_tongue:

pdo.inc.php

<?php

// Connect to MySQL
$dsn = 'mysql:dbname=dev; host=127.0.0.1';
$user = 'devuser';
$password = 'devpass';

try {
	$dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
	echo 'Failed to connect to MySQL: ' . $e->getMessage();
}

?>
1 Like

Unfortunately, you didn’t. In this snippet you shouldn’t use try catch, yet you have to set exception mode for PDO. So it rather should be

$dsn = 'mysql:dbname=dev;host=127.0.0.1';
$dbh = new PDO($dsn, $user, $password,[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);

See this is why I’d rather use MySQLi at least I know what I’m doing…

So it literally just …

<?php

// Connect to MySQL
$dsn = 'mysql:dbname=dev;host=127.0.0.1';
$dbh = new PDO($dsn, $user, $password,[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);

?>

pdo.inc.php

<?php
// Connect to MySQL
$dsn = 'mysql:dev=dev;host=127.0.0.1';
$username = 'dev';
$password = 'dev.dev';

$pdo = new PDO($dsn, $username, $password,[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
?>

functions.inc.php

<?php
include_once('pdo.inc.php');

function ValidateFlagValue($pdo, $FlagName, $FlagValue)
{
    $sql  = "SELECT 1 FROM flags WHERE flagname = ? AND ? BETWEEN MIN(flagvalue) AND MAX(flagvalue) LIMIT 1";
    $stmt = $pdo->prepare($sql);
    $stmt->execute([$FlagName, $FlagValue]);
    return $stmt->fetchColumn();
}

function GetFlagDescription($pdo, $FlagName, $FlagValue)
{
    $sql  = "SELECT 1 FROM flags WHERE flagname = ? AND flagvalue = ? LIMIT 1";
    $stmt = $pdo->prepare($sql);
    $stmt->execute([$FlagName, $FlagValue]);
    return $stmt->fetchColumn();
}
?>

test.php

<?php
include_once('functions.inc.php');

if (ValidateFlagValue('intent',2)) {
	echo "flag valid";
} else {
	echo "flag invalid";
}
?>

I’m not understanding this PDO at all :angry:

Why are you passing $pdo into the function because it doesn’t work.

Needs to be $dsn = 'mysql:dbname=dev;host=127.0.0.1';
Don’t replace dbname because that is how you connect to your database. It’s equivalent to procedural mysqli_*'s prepare($db, ..) where $db is the database you want to use.

Also, you should take note that square bracket arrays [] are available only from PHP 5.4 +. So don’t use square bracket arrays [] if you have PHP 5.3. You’ll get an error. Use array(); as an alternative if you have PHP 5.3 and below.

The reason why they are passing the $pdo/db variable is because in PHP, you don’t really want to create a new database connection every time you do a query. It’s easier to re-use the connection then closing it and re-opening it. In a way, it’s kind of like how system admins are with up-time.

You don’t need to. You can still use OOP mysqli_*.

<?php
// Connect to MySQL
$host = '127.0.0.1';
$username = 'dev';
$password = 'dev.dev';
$db = 'dev';

$mysqli = new mysqli($host, $username, $password, $db);
if($mysqli->connect_errno) {

    die('Do not display any errors here. You should NEVER display errors to the user.');

}

$sql = 'SELECT 1 FROM flags WHERE flagname = ? AND ? BETWEEN MIN(flagvalue) AND MAX(flagvalue) LIMIT 1';
$prepare = $mysqli->prepare($sql);
$prepare->bind_param('ss', $flagname, $flagname2);
$prepare->execute();
$prepare->store_result();

if($prepare->num_rows) {

    $prepare->bind_result($first_flag);

    while($prepare->fetch()) {

        print($first_flag);

    }

} else {

    print('No record with that information');

}

Also take note, you should always be using num_rows and rowCount() as it helps prevent white pages (nothing is displayed, no errors, no warning, nothing) and prevents error warning. It is also helps better user experience.

1 Like

I don’t know PDO or OOP :frowning:

<?php

// Connect to MySQL
$dsn = 'mysql:dbname=dev_pof;host=127.0.0.1';
$username = 'dev';
$password = 'dev.dev';

$pdo = new PDO($dsn, $username, $password,[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);

// Function to validate the flag value
function CheckFlagValue($pdo, $FlagName, $FlagValue)
{
    $sql  = "SELECT 1 FROM flags WHERE flagname = ? AND flagvalue = ? LIMIT 1";
    $stmt = $pdo->prepare($sql);
    $stmt->execute([$FlagName, $FlagValue]);
    return $stmt->fetchColumn();
}

// Function to get the flag description
function GetFlagDescription($pdo, $FlagName, $FlagValue)
{
    $sql  = "SELECT flagdescription FROM flags WHERE flagname = ? AND flagvalue = ? LIMIT 1";
    $stmt = $pdo->prepare($sql);
    $stmt->execute([$FlagName, $FlagValue]);
    return $stmt->fetchColumn();
}

echo GetFlagDescription($pdo, 'intent', 9);

?>

The GetFlagDescription function is working and shows the flag description when the flag name and value are passed.

However CheckFlagValue I need this function to return true or false depending on the row count. There doesn’t seem to be a row count function for PDO??

rowCount needs to be rowCount();
It has to be after the ->execute() or it won’t work. Also, it’s best to check if the row actually exists for all your query calls. Let’s say you only have 2 rows of data in your database and someone typed in their address bar ?flag=3. What then? It’ll display a big white blank page and nothing else. If you don’t handle errors the right way, your users will question, “Does this webmaster know what he’s doing because the page shows nothing?”

It’s best to handle errors the proper way so that users don’t keep sending feedbacks about blank pages. This is also a way for hackers to hack your website. If your page crashes after a certain amount of data, they know that those data don’t exist and they can exploit it. So rather than giving them a free pass, you should handle your errors the right and proper way by using num_rows (mysqli_*) and rowCount() (PDO).

Yes, I intend to do that eventually…

Do I need to do this… ?

// Function to validate the flag value
function CheckFlagValue($pdo, $FlagName, $FlagValue)
{
    $sql  = "SELECT 1 FROM flags WHERE flagname = ? AND flagvalue = ? LIMIT 1";
    $stmt = $pdo->prepare($sql);
    $stmt->execute([$FlagName, $FlagValue]);
    if ($stmt->rowCount() == 1) {
    	return true;
    } else {
    	return false;
    }
}

That code can be abbreviated to

return $stmt->rowCount() == 1;

There is never any reason for having an if statement to return true or false - simply return the condition.

2 Likes

This actually works too :smile:

I’m not sure I understand why but it works :stuck_out_tongue:

Can you explain the == 1 part

True. Unless you want to display the data.

== 1, > 0, < 1, and many other ones aren’t necessary. Normally you would find those conditions on a tutorial for noobies. With num_rows and rowCount, if the data exists, it’ll return a 1 which means true. If the data doesn’t exist, it’ll return a 0 which means false. In any case it would be like if(true == true) when you already know it’s already true and will always return the first error checking. False would always be returned in the else statement. That’s being really redundant so it’s not really necessary to repeat one’s self by comparing the condition when the data is returned as true already.

So this is fine if you were to use it in an if statement.

if($prepare->rowCount()) {

or

if($prepare->num_rows) {
1 Like

Now I understand, return $stmt->rowCount() on its own will return 0 or 1 :smile:

Yup and the best part is, if num_rows or rowCount() returns a 1. It’ll automatically return what is in the if statement no matter what. And like I said above, if num_rows or rowCount() returns a 0, it’ll return what is in the else statement.

So it’s not really needed to do something like

if($stmt->rowCount() == 0) when it’s exactly the same as } else {. And same with
if($stmt->rowCount() == 1) when it’s exactly the same thing as if($stmt->rowCount())

^ in a way.

1 Like
  1. There is such a function.
  2. You don’t need it anyway.

Look, you’ve gone astray from the plain and simple working code I gave you already. You don’t need a count actually. To count something is to make yourself aware of how many something you have.

In your case you don’t need it. You need only know whether you have somethng or not. It’s different question. For this you need just select something and see whether anything was returned. As simple as that. Exactly what my code does.

While you should never use rowCount or num_rows to see whether your query returned something or not. Because you already have the selected data iself - no need anything else.

return $stmt->fetchColumn();

See, here you selected one row from the database and fetched it. That’s exactly what you should do when working with database. If it returns a value (1), then it will be returned from function which will be count as TRUE. If no row found, then this code will return FALSE. Exactly what you need. That’s why this function works as intended. No extra code needed, No row count or comparisons required.

While your approach with rowCount is wrong. It makes no sense to select some data but not to fetch it.

you should handle your errors the right and proper way by using num_rows (mysqli_*) and rowCount()

Don’t listen to that guy. He just have no idea what he’s talking about. This function has absolutely nothing to do with whatever error handling at all

The difference being that thsoe return 0 or 1 where comparing it to 1 returns true or false as it would then be the result of the comparison that is returned rather than the value - just as in the original

if(condition) return true else return false
and
return condition

are equivalent in that both return true or false and not the value of part of the condition

How’s this…

<?php

class ScriptControl
{

  private $pdo;
  private $ScriptName;
  
  public function __construct($pdo, $ScriptName)
  {
    $this->pdo = $pdo;
    $this->ScriptName = $ScriptName;
  }

  public function IsEnabled();
  {
    $sql = "SELECT 1 FROM config WHERE config_name = ? AND config_value = 1 LIMIT 1";
		$stmt = $this->pdo->prepare($sql);
		$stmt->execute([$this->ScriptName]);
		return $stmt->fetchColumn();
  }

  public function IsRunnable();
  {
    date_default_timezone_set("Europe/London");
    $time = date("Hi");
    $sql = "SELECT 1 FROM config WHERE config_name = ? AND config_value = ? LIMIT 1";
		$stmt = $this->pdo->prepare($sql);
		$stmt->execute([$this->ScriptName, $this->$time]);
		return $stmt->fetchColumn();
  }
  
}

?>

and…

<?php

include_once('PDO.class.php');
include_once('ScriptControl.class.php');

$ThisScript = new ScriptControl('SendMessage');

if ( (!$ThisScript->isEnabled()) && (!isset($_POST['bypass'])) )
{
    echo "<p>This script is not enabled</p>\n";
    die();
}

if ( (!$ThisScript->isRunable()) && (!isset($_POST['bypass'])) )
{
  echo "<p>This script is not scheduled to run</p>\n";
  die();
}

?>

The IsEnabled will be used by about 10 different scripts, whereas the IsRunnable will only be used by 1 so is it right to put them together in the same class?

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.