Validate against duplicate field from database in oop php - php

I am somewhat new to object oriented programming in php. And currently working on interface project. I have interne_nummer field which is coming from database. And i need to validate this field to check that there should not be duplicate interne_nummer field allowed but not getting idea of how to validate it. I have posted a small code where i want to validate for interne_nummer field as everything else is running fine in my code.
case 'interne_nummer':
{
/* validate against valid interne_nummer */
$this->interne_nummer = trim(strval($value));
break;
}
For example there are some float fields for which i am validating it as follows and its working fine:
case 'schlussrate':
{
/* #todo validate as float*/
try {
$this->{$name} = $this->getFloatValue($value);
} catch (Execption $e) {
$this->{$name} = '';
// Throw Exception to higher Level
throw new Exeption("Field '".$name."': ".$e->getMessage());
}
break;
}
protected function getFloatValue($value) {
if (is_numeric($value)) {
return floatval($value);
}
throw new \Exeption("Value not allowed '".$value."'");
}

You could give a function like this a try:
public function exists($detail, $table, $column, $value) {
$stmt = $this->mysqli->prepare("SELECT `$detail` FROM `$table` WHERE `$column` = ?");
$stmt->bind_param('s', $value);
$stmt->execute();
$stmt->store_result();
if($stmt->num_rows >= 1) {
return true;
} else {
return false;
}
}
So when you call the function it could look like this:
// "SELECT `interne_nummer` FROM `workers` WHERE `interne_nummer` = '$interne_nummer_val'"
if($class->exists('interne_nummer', 'workers', 'interne_nummer', '$interne_nummer_val')) {
echo 'Number exists';
} else {
echo 'Number doesn\'t exists';
}

Related

Check Function without execute it

i'm training SOLID/Architectures and trying to make an INSERT on my code, but its insert four times on DB. There's any error on my logic? I'm following Repositories/Service Pattern.
i think my service is executing two times, but i cant find the reason.
Repositorie Code
public function inserirEstoque($dadosPost)
{
if (empty($dadosPost)) {
return false;
}
$pdo = $this->dbConnection->conectar();
$sql = $pdo->prepare('INSERT INTO estoque (nomeProduto, descriptions, price, quantity)
VALUES (:nome, :descriptions, :price, :quantity)');
$sql->bindValue(':nome', $dadosPost['nomeProduto']);
$sql->bindValue(':descriptions', $dadosPost['descriptions']);
$sql->bindValue(':price', $dadosPost['price']);
$sql->bindValue(':quantity', $dadosPost['quantity']);
$res = $sql->execute();
if($res == false)
{
return false;
}
return $res;
}
Service
public function insertEstoque()
{
$db = new MySQL();
$insert = new EstoqueRepositories($db);
if(!empty($insert->inserirEstoque($_POST))){
return $insert->inserirEstoque($_POST);
} else {
return false;
}
}
Controller
public function insert()
{
$insert = new EstoqueService();
$insert->insertEstoque();
header('Location: ../../index.php');
}
It's executing twice because of this
if(!empty($insert->inserirEstoque($_POST))){
return $insert->inserirEstoque($_POST);
} else {
return false;
}
if you wanna check if the POST data is empty just remove where it inserts the data then it should just insert it 1 time
if(!empty($_POST["whatevername"])){
return $insert->inserirEstoque($_POST);
} else {
return false;
}
As an addition to Reed's answer, if you just want to check the result of a function call before carrying on, assign the result to a variable and use that variable.
$res = $insert->inserirEstoque($_POST)
if(!empty($res)){
return $res;
} else {
return false;
}

method returns false when it should return true

I can't work out why this method keeps returning false. I'm checking the length of a password entered. It is definitely over 5 characters.The name of the input field is correct. But it always throws the exception throw new Exception("Password must contain at least 6 characters.");.
method:
public function checkPassword(){
if(strlen($this->post_data['register_password']) > 5){
}else{
throw new Exception("Password must contain at least 6 characters.");
}
}
calling:
if( isset($_POST['register-submit'])){
$error = '';
$register = new register($_POST, $dbh);
try {
if($register->checkUsername()){
if($register->checkPassword()){
}
}
} catch (Exception $e) {
$error .= '<span style="color:red;">' . $e->getMessage() . '</span>';
}
}
edit: added more of the class
public $post_data = array();
private $dbh;
public function __construct($post_data, PDO $dbh){
$this->error = array();
$this->post_data = array_map('trim', $post_data);
$this->dbh = $dbh;
}
Try putting var_dump($_POST) at the top of the calling code. Make sure you have the right variable name for password. I notice you have register-submit for the submit button and register_password for the password. Did you mix the hyphen (-) with an underscore (_)?
You create the class register, with $_POST, then use $this->post_data to fetch register_password. I doubt that there is something wrong with $this->post_data, add var_dump to debug:
public function checkPassword(){
if(strlen($_POST['register_password']) > 5){
return true;
}else{
// for debug
// var_dump($this->post_data['register_password']);
throw new Exception("Password must contain at least 6 characters.");
}
}
add var_dump to debug the __construct:
public function __construct($post_data, PDO $dbh){
$this->error = array();
$this->post_data = array_map('trim', $post_data);
var_dump($this->post_data);
$this->dbh = $dbh;
}

returning values from one method to another

I don't know why this don't work at all. I maybe wrong with my understanding that is why.
here is the situation.
MVC pattern
form validation stuffs
Here are the codes
public function userExist($data)
{
$string = "SELECT student_number FROM users WHERE student_number = :user";
$sth = $this->db->prepare($string);
$sth->execute(array(
':user' => $data['user']
));
return $sth->rowCount() == 0 ? true : false;
}
public function validate($data) {
$this->userExist($data);
}
What i want is to return a string, that says "user exists", if the userExist method is false ... But this code doesn't work:
if($sth->rowCount() == 0) {
return true;
} else {
return "User Already Exists";
}
This is, how i call them in the controller:
if ($this->model->validate($data) == true) {
$this->model->create($data);
header('Location: '.URL.'users');
} else {
echo $this->model->validate($data);
die();
}
What do you think is the best solution?
First of all, you need to return the value of validate:
public function validate($data) {
$this->userExist($data);
}
But there are some other problems here. You don't need to call $this->model->validate($data) twice in your controller. You could do something like:
$result = false;
$result = $this->model->validate($data);
if ( true === $result {
$this->model->create($data);
header('Location: '.URL.'users');
} else {
die($result);
}

PHP exception and user message

I have a project object.
A user can assign a worker object for it.
99% of the case the project object has all the proper fields set.
In some cases, the project is missing a field.
In order for a worker to be assign to a project the project must have all the required fields setup.
To solve this, I throw exceptions like this: ( don't try to find a pattern here, the real example is more complex )
if ($project->startDate == false ) {
throw new Exception("Missing startDate attribute for project id: $id");
}
if ($project->finishDate == false ) {
throw new Exception("Missing finishDate attribute for project id: $id");
}
if ($project->startDate > $project->finishDate ) {
throw new Exception("Invalid start date for project id: $id");
}
The problem with this is that I need to display a custom message to the user each time. For example if the first error is thrown the user should see: 'Please setup the project start date' and so on.
How can I do this ?
Just define your own exception class and your whole code in a try .. catch:
class FormException extends Exception {
private var $userMessage;
public function __construct($message, $userMessage) {
parent::__construct($message);
$this->userMessage = $userMessage;
}
public function getUserMessage() {return $this->userMessage;}
}
try {
// Whole code goes here, probably a function call
throw new FormException("Missing startDate attribute for project id: $id",
'Please setup the project start date');
} catch (FormException $e) {
echo $e->getUserMessage();
error_log($e->getMessage());
}
By the way, if you want to include variable contents in a string, either use double quotes ("id: $id") or concatenate ('id: ' . $id).
Try this:
try
{
$Message = '';
if ($project->startDate == false ) {
$Message = "Please setup the project start date\n";
throw new Exception("Missing startDate attribute for project id: $id");
}
if ($project->finishDate == false ) {
$Message = "Please setup the project finish date\n";
throw new Exception("Missing finishDate attribute for project id: $id");
}
if ($project->approved == false ) {
$Message = "Please setup the project approved field\n";
throw new Exception("Missing approved attribute for project id: $id");
}
}
catch(Exception $Ex)
{
// Log in some way you like the $Ex-getMessage();
echo nl2br($Message);
}
Inside your project class, create a new method, probably called getErrorMessage.
That function should do the checks (no need to have the concrete way of validation outside of project or create a validation object for project). Then:
if ($message = $project->getErrorMessage())
{
throw new Exception(sprintf('%s (project id: %d)', $message, $id));
}
If you decide to not throw exceptions for design reasons, this still is of use.
You gain more flexibility with a validator object that can naturally provide more detailed information than a single method. So it might be the better thing to do:
class ProjectValidator
{
private $project;
private $errors;
public function __construct($project)
{
$this->project = $project;
}
public function isValid()
{
// run your checks, add errors to the array as appropriate.
$errors = array();
if (!$this->project->startDate)
{
$errors[] = 'Missing startDate attribute';
}
if (!$this->project->finishDate)
{
$errors[] = 'Missing finishDate attribute';
}
if (!$this->project->approved)
{
$errors[] = 'Missing approved attribute';
}
$this->errors = $errors;
return (bool) count($this->errors);
}
public function getErrors()
{
return $this->errors;
}
}
$validator = new ProjectValidator($project);
if (!$validator->isValid())
{
// throw an exception or do whatever you want in case it's not valid
$errors = $validator->getMessages();
$message = sprintf("Project id: %d has the following %d error(s):\n", $id, count($errors));
foreach($errors as $index => $error)
{
$message .= sprintf("%d. %s\n", $index+1, $error);
}
throw new Exception($message);
}

PDO execute problem

I have faced a problem .I want to select all rows by executing this function:
public function executeQuery($query,$fetch_mode=null) {
$rs = null;
if ($stmt = $this->getConnection()->prepare($query)) {
if ($this->executePreparedStatement($stmt, $rs,$fetch_mode)) {
return $rs;
}
} else {
throw new DBError($this->getConnection()->errorInfo());
}
}
private function executePreparedStatement($stmt, & $row = null,$fetch_mode=null) {
$boReturn = false;
if($fetch_mode==null) $fetch_mode=$this->fetch_mode;
if ($stmt->execute()) {
if ($row = $stmt->fetch($fetch_mode)) {
$boReturn = true;
} else {
$boReturn = false;
}
} else {
$boReturn = false;
}
return $boReturn;
}
But when I call it from my index page:
$objDB=new DB();
$objDB->connect();
// executeQuery returns an array
$result=$objDB->executeQuery("SELECT * FROM admin");
var_dump($result);
Only a single row is retrieved instead of all rows.
I also set mode using:
$result=$objDB->executeQuery("SELECT * FROM admin",PDO::FETCH_ASSOC);
But it still does not work.
The fetch method returns only the current row and sets the row pointer to the next row. To read all data in a PHP array you can use fetchAll().
Additionally return-by-reference is no good idea in PHP as it messes with PHP's copy-on-write mechanism and often creates trouble.
So I'd write oyure code something like this:
public function executeQuery($query,$fetch_mode=null) {
if ($stmt = $this->getConnection()->prepare($query)) {
$ret = $this->executePreparedStatement($stmt, $fetch_mode);
return $ret;
}
throw new DBError($this->getConnection()->errorInfo());
}
private function executePreparedStatement($stmt, $fetch_mode=null) {
if($fetch_mode==null) $fetch_mode=$this->fetch_mode;
if ($stmt->execute()) {
if ($rows = $stmt->fetchAll($fetch_mode)) {
return $rows;
}
}
return false;
}

Categories