I have a scenario where I want to create a user using Object Oriented PHP8, I have my users.php page where I have the form and this issue seems to be that I do not think the method from my object form ($objForm) are being passed in correctly to my object validation ($objValidation):
<?php
use A\B\App\Session;
use A\B\App\Login;
use A\B\App\User;
use A\B\App\Form;
use A\B\App\Validation;
require_once("../../vendor/autoload.php");
$session = new Session();
if(!$session->isLogged()) {
Login::redirectTo("login");
}
$objForm = new Form();
// passing in the object to validation
$objValidation = new Validation($objForm);
$objUser = new User();
if($objForm->isPost("name")) {
$objValidation->expected = ["name"];
$objValidation->required = ["name"];
$objValidation->special = ["email" => "email"];
$objValidation->postFormat = ["password" => "password"];
$email = $objForm->getPost("email");
$existingUser = $objUser->getUserByEmail($email);
if($existingUser) {
$objValidation->addToErrors("user_exists");
}
if($objValidation->isValid()) {
echo "good";
} else {
echo "bad";
}
}
?>
<form action="" method="post">
<p>
<input type="text" name="name" placeholder="User name" required="">
</p>
<?php echo $objValidation->validate('user_exists'); ?>
<p>
<input type="email" name="email" placeholder="User email" required="">
</p>
<p>
<input type="password" name="password" placeholder="Password" required="">
</p>
<p>
<input type="submit" name="" value="Add user">
</p>
</form>
I am simply trying to echo out a yes or no to see if it passes this point so I am not actually calling a method to create a user yet since the code is failing before.
below are my 2 classes:
<?php
declare(strict_types = 1);
namespace A\B\App;
class Form
{
public function isPost(string $field): bool
{
if(!empty($field)) {
if(isset($_POST[$field])) {
return true;
}
return false;
} else {
if(!empty($_POST)) {
return true;
}
return false;
}
}
public function getPost(string $field)
{
if(!empty($field)) {
return $this->isPost($field) ? strip_tags($_POST[$field]) : null;
}
}
public function getPostArray(array $field): array
{
$out = [];
if($this->isPost()) {
foreach($_POST as $key => $value) {
if(!empty($field)) {
if(in_array($key, $expected)) {
$out[$key] = strip_tags($value);
}
} else {
$out[$key] = strip_tags($value);
}
}
}
return $out;
}
}
and here is the validation class:
<?php
declare(strict_types = 1);
namespace A\B\App;
class Validation
{
private array $error = [];
public array $message = ["user_exists" => "This user exists in the Db"];
public array $expected = [];
public array $required = [];
public array $post = [];
private $objForm;
public array $test = [];
public array $postRemove = [];
public array $postFormat = [];
public array $special = [];
public function __construct(Form $form)
{
$this->objForm = $form;
}
public function process()
{
if($this->objForm->isPost() && !empty($this->required)) {
$this->post = $this->objForm->getPostArray($this->expected);
if(!empty($this->post)) {
foreach($this->post as $key => $value) {
$this->check($key, $value);
}
}
}
}
public function check($key, $value)
{
if(!empty($this->special) && array_key_exists($key, $this->special)) {
$this->checkSpecial($key, $value);
} else {
if(in_array($key, $this->required) && empty($value)) {
$this->addToErrors($key);
}
}
}
public function checkSpecial($key, $value)
{
switch($this->special[$key]) {
case 'email':
if(!$this->isEmail($value)) {
$this->addToErrors($key);
}
break;
}
}
public function isEmail($email)
{
if(!empty($email)) {
$result = filter_var($email, FILTER_VALIDATE_EMAIL);
return !$result ? false : true;
}
return false;
}
public function isValid()
{
$this->process();
if(empty($this->errors) && !empty($this->post)) {
// remove unwanted fields
if(!empty($this->postRemove)) {
foreach($this->postRemove as $value) {
unset($this->post[$value]);
}
}
// format required fields
if(!empty($this->postFormat)) {
foreach($this->postFormat as $key => $value) {
$this->format($key, $value);
}
}
return true;
}
return false;
}
public function format($key, $value)
{
switch($value) {
case 'password':
$this->post[$key] = Login::passwordEncrypt($this->post[$key]);
break;
}
}
public function addToErrors($key)
{
$this->errors[] = $key;
}
public function validate($key)
{
if(!empty($this->errors) && in_array($key, $this->errors)) {
return $this->wrapWarn($this->message[$key]);
}
}
public function wrapWarn($mess)
{
if(!empty($mess)) {
return "<span class=\"warn\" >{$mess}</span>";
}
}
}
I have tested other dummy functions from validations.php and form.php and both work so the issue is definitely between the communication with these 2 classes. The process method is not recognizing or not getting values from the $this->objForm->isPost()
call. Here is the error message I get where its telling me no value is being passed in:
Fatal error: Uncaught ArgumentCountError: Too few arguments to function A\B\App\Form::isPost(), 0 passed in /Applications/MAMP/htdocs/project/src/App/Validation.php on line 41 and exactly 1 expected in /Applications/MAMP/htdocs/project/src/App/Form.php:10 Stack trace: #0 /Applications/MAMP/htdocs/project/src/App/Validation.php(41): A\B\App\Form->isPost() #1 /Applications/MAMP/htdocs/project/src/App/Validation.php(94): A\B\App\Validation->process() #2 /Applications/MAMP/htdocs/project/src/Pages/users.php(36): A\B\App\Validation->isValid() #3 {main} thrown in /Applications/MAMP/htdocs/project/src/App/Form.php on line 10
Note: I have not been applying type declarations/hints to everything yet because of being stuck.
In order to not change too much the codebase (change all the references of the method), you should change the signature of the isPost()
function in this way:
public function isPost(string $field = ""): bool