there is two ways or more i can make that function
one why is using more returns and return every time i do not need continue with the function and another way is using
more ifs,else ifs, elses,
function getCountOfWhatEverMethodType1
{
$return = false;
// ----
if($user->isLogged)
{
if(getDBOBlaBla->equal(1))
{
$return = 2;
}
else if(getDBOBlaBla->equal(2))
{
$return = 3;
}
else
{
$return = 1;
}
}
// ----
return $return;
}
function getCountOfWhatEverMethodType2
{
if(!$user->isLogged)
{
return false;
}
$return = 1;
// ----
if(getDBOBlaBla->equal(1))
{
$return = 2;
}
else if(getDBOBlaBla->equal(2))
{
$return = 3;
}
// ----
return $return;
}
with one i should use and why?
If you want to return something, usually the better option is to return something when the condition is met.
I would do it this way:
function getCountOfWhatEverMethodType3()
{
if(!$user->isLogged)
{
return false;
}
// ----
if(getDBOBlaBla->equal(1))
{
return 2;
}
if(getDBOBlaBla->equal(2))
{
return 3;
}
return 1;
}
For me this style is better for 2 reasons:
You can remove some if/else statments so you can code faster and there's less code in case you need to modify or analyze that
You don't create temporary variables because you don't need them.
In fact each person has it's own coding preferences in such statements and if all work you can use any of them. But even look at your previous code - you made some mistakes (used null that was unnecessary) and using the above version it would be harder to do such mistake
Related
I am developing a Register/Login system with validation. Registering system is working well. For example, when I register the same email twice, the following message appears:
Email already registered!
However, when I log-in with the same e-mail and password, an error occurs. The following message appears as a validation error:
Email not registered!
Even if the email is registered in DB.
Code for e-mail validation:
<?php
public function validateEmail($par)
{
if (filter_var($par, FILTER_VALIDATE_EMAIL)) {
return true;
} else {
$this->setErro("Invalid Email!");
return false;
}
}
public function validateIssetEmail($email, $action = null)
{
$b = $this->cadastro->getIssetEmail($email);
if ($action == null) {
if ($b > 0) {
$this->setErro("Email already registered!");
return false;
} else {
return true;
}
} else {
if ($b > 0) {
return true;
} else {
$this->setErro("Email not registered!");
return false;
}
}
}
Code for login controller:
<?php
$validate = new Classes\ClassValidate();
$validate->validateFields($_POST);
$validate->validateEmail($email);
$validate->validateIssetEmail($email,"login");
$validate->validateStrongSenha($senha);
$validate->validateSenha($email,$senha);
var_dump($validate->getErro());
Code for class login:
<?php
namespace Models;
class ClassLogin extends ClassCrud
{
# Returns user data
public function getDataUser($email)
{
$b = $this->selectDB(
"*",
"users",
"where email=?",
array(
$email
)
);
$f = $b->fetch(\PDO::FETCH_ASSOC);
$r = $b->rowCount();
return $arrData = [
"data" => $f,
"rows" => $r
];
}
}
My getIssetEmail method exists on Register code only.
# Check directly at the bank if the email is registered
public function getIssetEmail($email)
{
$b = $this->selectDB(
"*",
"users",
"where email=?",
[
$email
]
);
return $r = $b->rowCount(); // returns the amount of rows in the search
}
And ClassPassword
<?php
namespace Classes;
use Models\ClassLogin;
class ClassPassword
{
private $db;
public function __construct()
{
$this->db = new ClassLogin();
}
# Create password's hash to save in DB
public function passwordHash($senha)
{
return password_hash($senha, PASSWORD_DEFAULT);
}
# Verify if password's hash is correct
public function verifyHash($email, $senha)
{
$hashDb = $this->db->getDataUser($email);
return password_verify($senha, $hashDb["data"]["senha"]);
}
}
This is not an answer but hopefully it will help in debugging.
First, I'm going to change your code. This is 100% a style choice but I personally think it is easier to follow. If you have an if statement that always returns, you don't technically need an else. Once again, this is a style choice and you don't have to follow it.
Second, if you can, try adding logging into your workflow, it will save you so much time debugging. It isn't always an option, especially for legacy code bases, but it is awesome when you can inspect complex code. In this example, I"m just making a couple of helper methods that dump stuff but normally I'd use something like Monolog to write to a stream that I can tail, and I can easily turn it off in production. When logging, sometimes it helps to avoid identical messages so that you can easily find the exact line number you are on, too.
So with those changes, try running this code inside of your class:
private function logMessage($message)
{
echo $message . PHP_EOL;
}
private function logVariable($variable)
{
var_dump($variable);
}
public function validateIssetEmail($email, $action = null)
{
$this->logVariable($email);
$this->logVariable($action);
$b = $this->cadastro->getIssetEmail($email);
$this->logVariable($b);
if ($action === null) {
$this->logMessage('Action was null');
if ($b > 0) {
$this->logMessage('B is greater than zero');
$this->setErro("Email already registered!");
return false;
}
$this->logMessage('B was not greater than zero');
return true;
}
$this->logMessage('Action was not null');
if ($b > 0) {
$this->logMessage('B is greater than zero');
return true;
}
$this->logMessage('B was not greater than zero');
$this->setErro("Email not registered!");
return false;
}
This should log in human-readable form every step. You should be able to walk through this and identify where your bug is. For instance, in the comments above you said that a variable was 0 in a block that was guarded by a check that guarantees that that shouldn't happen.
This is the wrong part i guess you assigned login as action so you can call cadastro class inside of the function
$cadastro = new Cadastro();
$b = $cadastro->getIssetEmail($email);
if ($action == null) {
if ($b > 0) {
$this->setErro("Email already registered!");
return false;
} else {
return true;
}
} else {
if ($b > 0) {
return true;
} else {
$this->setErro("Email not registered!");
return false;
}
}
I have inherited an application that is not doing what it's supposed to do. I have isolated the problem to the database not being properly attached. The programmer wrote this function that seemingly is suppose to evaluate whether the database is attached, calling the "attachPaymentDatabase()" function to attach it if it's not.
function attachPaymentDatabaseIfNotDoneAlready()
{
global $db;
global $hasPaymentDatabaseAttached;
// Determine if we have attached the payment tables, and if not, add them.
$hasPaymentDatabaseAttached = false;
try {
// this new way should work the best-- looking for PAY.
$alldb = queryall($db, "PRAGMA database_list;");
for ($i = 0; $i < count($alldb); $i++)
{
$alldb[$i] = array_change_key_case($alldb[$i], CASE_LOWER);
if (strtolower($alldb[$i]['name']) == 'pay')
{
debugEmail("condition 1 worked.");
$hasPaymentDatabaseAttached = true;
break;
}
}
// if its name changed this will also work
if (!$hasPaymentDatabaseAttached)
{
$r = #$db->querySingle("SELECT * FROM PAY_PARAMETER;");
$hasPaymentDatabaseAttached = true;
debugEmail("condition 2 worked.");
}
}
catch(Exception $e)
{
}
if (!$hasPaymentDatabaseAttached)
{
debugEmail("nothing worked.");
attachPaymentDatabase();
}
}
I have written a debugEmail() function that emails me a defined message with a timestamp as used above. When executing the code from the application, I can see that "condition 2 worked." is being called one second before "nothing worked.".
I don't understand how this can be. If debugEmail("condition 2 worked."); is executing, then so should too $hasPaymentDatabaseAttached = true; in which case this should not execute:
if (!$hasPaymentDatabaseAttached)
{
debugEmail("nothing worked.");
attachPaymentDatabase();
}
But it clearly is.
What is going on here?!?!?!?
No it shouldn't, because $hasPaymentDatabaseAttached is set to true in the first condition. In still nonsense at all, but it works as described.
I have one not understood point In MVC pattern. Please help understood.
for example we have table for cars in database, we want obtain and print results from table, but if results are not found (0 rows), in this case print: "We dont have results"
this is models.php
class modesl {
function getCars () {
$res = $this->db->query("SELECT names FROM cars");
if ($res->num_rows == 0) {
return "We dont have results";
}
else {
return $res;
}
}
}
this is views.php
class views {
function loadHTML ($resultFromCars) {
require 'carspage.php';
}
}
this is carspage.php
<html>
<body>
<?php
if (is_object($resultFromCars)) {
while ($row = $resultFromCars->fetch_assoc()) {
echo $row['names']."<br>";
}
}
else {
echo $resultFromCars;
}
?>
</body>
</html>
this is controllers.php
class controllers {
function generatePage () {
$model = new models();
$resultFromCars = $model->getCars();
$view = new views();
$view->loadHTML($resultFromCars);
}
}
This works, but as I know, many php code in view, (that is condition if (is_object) { } else { } ) is not right MVC. tell please for this concret case, what must be change in my architecture (lol), for obtain right MVC concept?
I like the answer provided by Havelock.
I would adjust this even further, by making sure your model already returns the data in an array format (or false, if nothing is found). Therefore, the logic for extracting data from resultset stays in the model, where it really should be.
Your view becomes even simpler then:
<?php
if (!empty($results)) {
foreach ($results as $row) {
echo $row['name'] . "<br />";
}
} else {
echo "Eh, Nothing found...";
}
You seem to have done a good job, just one small thing to improve. As the model is a wrapper for data only, so you should return only data (and no strings, containing error/exception messages). In the case there's no data to return, then return FALSE, as it's done in PHP.
class CarModel {
function getCars () {
$res = $this->db->query("SELECT names FROM cars");
if ($res->num_rows == 0) {
return FALSE; // if that happens, the function will stop execution here, so no "else" is needed
}
return $res;
}
}
And in your view
<?php
if ($resultFromCars === FALSE && !empty($resultFromCars)) {
echo "We don't have results";
}
else { // now you know it's not FALSE, so it must be an object, no need to check whether it is one
while ($row = $resultFromCars->fetch_assoc()) {
echo $row['names']."<br>";
}
}
?>
I have a series of functions that I'd like to run. At the end of each function, it either sets a variable TRUE or FALSE. What I'd like to do is break the series if the variable sets to TRUE.
For example. I have the following:
$done = false;
step1(); // Sets $done to false
step2(); // Sets $done to false
step3(); // Sets $done to true
step4(); // Because step3() set $done to true, I wan't step4() to NOT run.
Of course if step3() returns false, I'd like to keep going and run step4().
I know I'll need to use a while, switch, and/or a break. I'm just unclear on how to set this up.
Much appreciated.
It's not much clear to me, but if your functions return booleans, you can try:
step1() || step2() || step3() || step4();
The operator || only evaluate the second operand if the first is false.
it can be done by using a simple if statement if you want.
$done = false;
$done = step1(); // each function returns true or false
if (!$done)
{
$done = step2();
}
if (!$done)
{
$done = step3();
}
if (!$done)
{
$done = step4();
}
correct me if there is any mistakes.
$done = false;
function step1($done){
if($done===false){
//proceed step 2
}
else{
return;
}
}
function step2($done){
if($done===false){
//proceed step 3
}
else{
return;
}
}
function step3($done){
if($done===false){
//proceed step 4
}
else{
return;
}
}
function step4($done){
if($done===false){
//finish
}
else{
return;
}
}
Your question is not very straight forward, probably similar to the form you have so far.
You could create an array with callbacks of your functions and consume them while $done is false and there are still functions to consume:
$doFunctions = ['step1', 'step2', ... , 'stepN'];
$done = false;
while (!$done && $doFunctions)
{
$function = array_shift($doFunctions);
call_user_func($function);
}
As this shows, no switch and no break needed, because you have a simple condition here.
Another alternative would be to "make" the functions return something by wrapping it inside a closure and keep the $done as a reference (context), then return it:
$done = false;
$call = function ($function) use (&$done) {
$function();
return $done;
}
$call('step1')
|| $call('step2')
|| $call('step3')
|| $call('step4')
;
It depends a bit of what you actually need to achieve.
So perhaps my question was misunderstood, but after a while I realized that a try/catch block with exceptions was exactly what I was after. Here is roughly what I ended up doing.
First I set up my functions to throw exceptions on errors.
function step1() {
// do awesome stuff
if ($errorInStep1) {
throw new Exception('There was an error in step 1.');
}
}
function step2() {
// do awesome stuff
if ($errorInStep2) {
throw new Exception('There was an error in step 2.');
}
}
function step3() {
// do awesome stuff
if ($errorInStep3) {
throw new Exception('There was an error in step 3.');
}
}
function step4() {
// do awesome stuff
if ($errorInStep4) {
throw new Exception('There was an error in step 4.');
}
}
So now if there is an error in each of the functions, the script will throw an exception.
Then I wrap those functions in a try/catch block. The script will try to go through each statement, and if something throws and exception...it will stop right there. Perfect.
try {
step1();
step2();
step3();
step4();
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}
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;
}