Sanitize user input to avoid XSS attacks Question

I have username and password for login and want to avoid the cross site scripting. I read that using htmlspecialchars() is the way to go but not sure what to do after that. Any ideas?
937 Replies
ZomaTheMasterOfDisaster
current code so far
<?php

function sanitizeLogin(string $username, string $pass): string {
$xssCheckPartOne = htmlspecialchars($username);
$xssCheckPartTwo = htmlspecialchars($pass);

}
<?php

function sanitizeLogin(string $username, string $pass): string {
$xssCheckPartOne = htmlspecialchars($username);
$xssCheckPartTwo = htmlspecialchars($pass);

}
Jochem
Jochem4mo ago
use prepared statements
ZomaTheMasterOfDisaster
how's that work?
Jochem
Jochem4mo ago
https://www.php.net/manual/en/pdo.prepare.php you feed the raw string to PDO and PDO makes sure it's safe for the database no matter what also, you don't need to sanitize the password because you're hashing it anyway (you are hashing it, right?)
ZomaTheMasterOfDisaster
im using the password_hash() function but i know there's an argon option which I dont know how to use is what im doing not a good thing?
Jochem
Jochem4mo ago
yeah, you can use password_hash. Just hash the raw value from the user, and store the hash in the database hashing will guarantee a database safe string, but still use prepared statements to insert things. You should always use prepared statements rather than trying to sanitize your own data
ZomaTheMasterOfDisaster
my goal was sanitize input for errors and report it so user can't proceed if they try to do anything stupid with xss
Jochem
Jochem4mo ago
best security practice is to not notify people doing stupid things with xss basically, you just silently sanitize and use the sanitized input
ZomaTheMasterOfDisaster
hmm so me making a sanitize.php file is kinda a waste?
Jochem
Jochem4mo ago
yeah, honestly anything you do for security, you want to try to hide from the user as much as possible you technically don't even want to tell them if the username or password is the one that's wrong, that lets people try to find usernames by just flooding your login and seeing if it returns "user unknown" or "password incorrect" trust that PHP's standards are good enough to protect you, use prepared statements and password_hash
ZomaTheMasterOfDisaster
see I made this form checker file to use functions from in register and login
<?php

function validateLoginFields($username, $pass) : bool {
if((!$username) || (!$pass))
{
$error = "Please fill in all fields for processing the login";
echo $error;
return false;
}

if(!filter_var($username, FILTER_VALIDATE_EMAIL)) {
$error = "Enter a valid username using your email";
echo $error;
return false;
}

return true;
}

function validateRegisterFields($username, $email, $pass, $validatepassword): bool {
if((!$username) || (!$email) || (!$pass) || (!$validatepassword)) {
$error = "Please leave no fields blank";
echo $error;
return false;
}

if(!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$error = "Enter a valid email address";
echo $error;
return false;
}

if(strlen($pass) > 25 || strlen($pass) < 8) {
$error = "Password must be between 8 to 25 characters";
echo $error;
return false;
}

if(strlen($validatepassword) > 25 || strlen($validatepassword) < 8) {
$error = "Validate Password must be between 8 to 25 characters";
echo $error;
return false;
}

if($pass != $validatepassword) {
$error = "Passwords must match";
echo $error;
return false;
}

return true;
}
<?php

function validateLoginFields($username, $pass) : bool {
if((!$username) || (!$pass))
{
$error = "Please fill in all fields for processing the login";
echo $error;
return false;
}

if(!filter_var($username, FILTER_VALIDATE_EMAIL)) {
$error = "Enter a valid username using your email";
echo $error;
return false;
}

return true;
}

function validateRegisterFields($username, $email, $pass, $validatepassword): bool {
if((!$username) || (!$email) || (!$pass) || (!$validatepassword)) {
$error = "Please leave no fields blank";
echo $error;
return false;
}

if(!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$error = "Enter a valid email address";
echo $error;
return false;
}

if(strlen($pass) > 25 || strlen($pass) < 8) {
$error = "Password must be between 8 to 25 characters";
echo $error;
return false;
}

if(strlen($validatepassword) > 25 || strlen($validatepassword) < 8) {
$error = "Validate Password must be between 8 to 25 characters";
echo $error;
return false;
}

if($pass != $validatepassword) {
$error = "Passwords must match";
echo $error;
return false;
}

return true;
}
now im just trying to make sure xss crap is avoided
Jochem
Jochem4mo ago
see, that's fine. None of that will leak info (though upper character limits for passwords are pointless) Just don't manually try to sanitize your user's inputs, trust PHP. That way, when there's a vulnerability, you just update PHP and that's that
ZomaTheMasterOfDisaster
ok so if I use prepare, how to handle htmlspecialchars?
Jochem
Jochem4mo ago
on display or, alternatively, when you store them in addition to the prepared statements, but only for things you might conceivably display. Never for the password htmlspecialchars won't take care of even the most basic SQL Injection attacks
ZomaTheMasterOfDisaster
what does?
Jochem
Jochem4mo ago
prepared statements they're made to prevent SQL injection htmlspecialchars will help mitigate XSS but yeah, never mess with the user's password, it's just going to cause issues and you shouldn't ever store or display the user's password anyway, not unhashed
ZomaTheMasterOfDisaster
what if they put xss attack in password field?
Jochem
Jochem4mo ago
how would that ever trigger? xss is a worry if the value is displayed to a different user once an attacker has submitted their XSS attack in the password field, your code should hash it as is and that destroys the payload.
ἔρως
ἔρως4mo ago
you're doing some things in a very very wrong way 1- you're sanitizing emails - just validate and gtfo if it doesn't pass as an email, it isn't an email and no sanitization will save it if it is an email, you should accept the input you can sanitize the email after, but it should be safe
Jochem
Jochem4mo ago
(I'd argue you should still sanitize before display though
ἔρως
ἔρως4mo ago
2- you're limiting the maximum length of your password DO NOT DO THAT
ZomaTheMasterOfDisaster
i dumped the email for sign and changed the maxium password
ἔρως
ἔρως4mo ago
set it to 256 characters or something, if you really must 30 characters isn't safe enough, sometimes 3- you're not trimming whitespaces people are dumb and copy stuff, so, trim whitespace
Jochem
Jochem4mo ago
72 bytes is the limit for bcrypt, but there's no reason to limit the password at all
ἔρως
ἔρως4mo ago
PASSWORD_DEFAULT doesn't and the argon2 ones don't as well just bcrypt
ZomaTheMasterOfDisaster
ok i got some stff started
<?php
require __DIR__ . '../../../vendor/autoload.php';
include "../../class/helpers/formcheck.php";
include "../../class/dbhelper/SQLConnection.php";

function postInput($htmlName) {
if(isset($_POST[$htmlName])) {
return $_POST[$htmlName];
}

return null;
}

$username = postInput('username');
$pass = postInput('password');
$validatePass = postInput('validatepassword');

if(isset($_POST['submit'])) {
$hashedpassword = password_hash($pass, PASSWORD_BCRYPT);

if(validateRegisterFields($username, $pass, $validatePass)) {

}
}
<?php
require __DIR__ . '../../../vendor/autoload.php';
include "../../class/helpers/formcheck.php";
include "../../class/dbhelper/SQLConnection.php";

function postInput($htmlName) {
if(isset($_POST[$htmlName])) {
return $_POST[$htmlName];
}

return null;
}

$username = postInput('username');
$pass = postInput('password');
$validatePass = postInput('validatepassword');

if(isset($_POST['submit'])) {
$hashedpassword = password_hash($pass, PASSWORD_BCRYPT);

if(validateRegisterFields($username, $pass, $validatePass)) {

}
}
ἔρως
ἔρως4mo ago
require __DIR__ . '../../../vendor/autoload.php'; <-- this is scary
Jochem
Jochem4mo ago
use PASSWORD_DEFAULT insteaf of specifying a specific algo
ἔρως
ἔρως4mo ago
include "../../class/helpers/formcheck.php";
include "../../class/dbhelper/SQLConnection.php";
include "../../class/helpers/formcheck.php";
include "../../class/dbhelper/SQLConnection.php";
instead of doing this, just use the composer psr4 loader you were using before
ZomaTheMasterOfDisaster
changed
ἔρως
ἔρως4mo ago
you have a bug if(isset($_POST[$htmlName])) <-- this will give you false positives use !empty() instead wait oh boy ... i got what that function does and it's completely useless
ZomaTheMasterOfDisaster
im very rusty at php how i include them?
ἔρως
ἔρως4mo ago
instead of using that function, use ?? null or something
ZomaTheMasterOfDisaster
"MD<insert name here>"
ἔρως
ἔρως4mo ago
use MD/helpers/formcheck capitalization is important you have a loader, so, all you have to do is just use the classes you don't have to include the files, as they are automatically included for you
ZomaTheMasterOfDisaster
php is complaining Undefined function 'validateRegisterFields'.intelephense(P1010)
ἔρως
ἔρως4mo ago
then you did something wrong
ZomaTheMasterOfDisaster
<?php
include '../../../vendor/autoload.php';
include "MD/helpers/formcheck";
include "MD/dbhelper/SQLConnection";

function postInput($htmlName) {
if(isset($_POST[$htmlName])) {
return $_POST[$htmlName];
}

return null;
}

$username = postInput('username');
$pass = postInput('password');
$validatePass = postInput('validatepassword');

if(isset($_POST['submit'])) {
$hashedpassword = password_hash($pass, PASSWORD_DEFAULT);

if(validateRegisterFields($username, $pass, $validatePass)) {

}
}


?>
<?php
include '../../../vendor/autoload.php';
include "MD/helpers/formcheck";
include "MD/dbhelper/SQLConnection";

function postInput($htmlName) {
if(isset($_POST[$htmlName])) {
return $_POST[$htmlName];
}

return null;
}

$username = postInput('username');
$pass = postInput('password');
$validatePass = postInput('validatepassword');

if(isset($_POST['submit'])) {
$hashedpassword = password_hash($pass, PASSWORD_DEFAULT);

if(validateRegisterFields($username, $pass, $validatePass)) {

}
}


?>
ἔρως
ἔρως4mo ago
not include use the psr4 loader does all the work for you
ZomaTheMasterOfDisaster
include '../../../vendor/autoload.php';
use MD/helpers/formcheck;
use MD/dbhelper/SQLConnection;
include '../../../vendor/autoload.php';
use MD/helpers/formcheck;
use MD/dbhelper/SQLConnection;
complains syntax error
ἔρως
ἔρως4mo ago
what does it say? probably wrong slashes
ZomaTheMasterOfDisaster
syntax error, unexpected token "/", expecting "," or ";"
ἔρως
ἔρως4mo ago
yeah, told you the wrong slashes change then for the use
ZomaTheMasterOfDisaster
ah it complains that I setup wrong because I dont have class in formcheck.php
<?php

namespace MD\helpers;

function validateLoginFields($username, $pass) : bool {
if((!$username) || (!$pass))
{
$error = "Please fill in all fields for processing the login";
echo $error;
return false;
}

return true;
}

function validateRegisterFields($username, $pass, $validatepassword): bool {
if((!$username) || (!$pass) || (!$validatepassword)) {
$error = "Please leave no fields blank";
echo $error;
return false;
}

if(strlen($pass) < 8) {
$error = "Password must be 8 characters or more";
echo $error;
return false;
}

if(strlen($validatepassword) < 8) {
$error = "Validate Password must be 8 or more characters";
echo $error;
return false;
}

if($pass != $validatepassword) {
$error = "Passwords must match";
echo $error;
return false;
}

return true;
}
<?php

namespace MD\helpers;

function validateLoginFields($username, $pass) : bool {
if((!$username) || (!$pass))
{
$error = "Please fill in all fields for processing the login";
echo $error;
return false;
}

return true;
}

function validateRegisterFields($username, $pass, $validatepassword): bool {
if((!$username) || (!$pass) || (!$validatepassword)) {
$error = "Please leave no fields blank";
echo $error;
return false;
}

if(strlen($pass) < 8) {
$error = "Password must be 8 characters or more";
echo $error;
return false;
}

if(strlen($validatepassword) < 8) {
$error = "Validate Password must be 8 or more characters";
echo $error;
return false;
}

if($pass != $validatepassword) {
$error = "Passwords must match";
echo $error;
return false;
}

return true;
}
ἔρως
ἔρως4mo ago
then do it make it all into a class make it a generic validation class and make one for sanitization
ZomaTheMasterOfDisaster
<?php

namespace MD\helpers;

class Checker {



function validateLoginFields($username, $pass) : bool {
if((!$username) || (!$pass))
{
$error = "Please fill in all fields for processing the login";
echo $error;
return false;
}

return true;
}

function validateRegisterFields($username, $pass, $validatepassword): bool {
if((!$username) || (!$pass) || (!$validatepassword)) {
$error = "Please leave no fields blank";
echo $error;
return false;
}

if(strlen($pass) < 8) {
$error = "Password must be 8 characters or more";
echo $error;
return false;
}

if(strlen($validatepassword) < 8) {
$error = "Validate Password must be 8 or more characters";
echo $error;
return false;
}

if($pass != $validatepassword) {
$error = "Passwords must match";
echo $error;
return false;
}

return true;
}

}
<?php

namespace MD\helpers;

class Checker {



function validateLoginFields($username, $pass) : bool {
if((!$username) || (!$pass))
{
$error = "Please fill in all fields for processing the login";
echo $error;
return false;
}

return true;
}

function validateRegisterFields($username, $pass, $validatepassword): bool {
if((!$username) || (!$pass) || (!$validatepassword)) {
$error = "Please leave no fields blank";
echo $error;
return false;
}

if(strlen($pass) < 8) {
$error = "Password must be 8 characters or more";
echo $error;
return false;
}

if(strlen($validatepassword) < 8) {
$error = "Validate Password must be 8 or more characters";
echo $error;
return false;
}

if($pass != $validatepassword) {
$error = "Passwords must match";
echo $error;
return false;
}

return true;
}

}
` just complains I dont have a defined type this is getting confusing
ἔρως
ἔρως4mo ago
that's because you're doing too much here's what i would do: 1- make a class to validate strings 2- validate strings 3- get the errors, if there's any now, you do you, but, i would put those 2 functions as 2 static methods in a class
ZomaTheMasterOfDisaster
im just struggling been a while since I had to think this way ive never done oop php just php before oop
ἔρως
ἔρως4mo ago
this isn't even the hardest part but why don't you make a generic class to validate stuff?
ZomaTheMasterOfDisaster
because I never thought about it
ἔρως
ἔρως4mo ago
the idea of classes is to make stuff re-usable and separate responsibilities
ZomaTheMasterOfDisaster
i could make a class have an array of input i guess since there's different fields between both pages
ἔρως
ἔρως4mo ago
or, make something generic then you can validate anything
ZomaTheMasterOfDisaster
yeah im not sure how to do that in php
ἔρως
ἔρως4mo ago
and since it is a custom class for you, you can add specific validations how about a class that you can pass a value, and it validates if the value is something and if that something is what you expect
ZomaTheMasterOfDisaster
class Checker {

public static function validateLoginFields($username, $pass): bool {
if((!$username) || (!$pass))
{
$error = "Please fill in all fields for processing the login";
echo $error;
return false;
}

return true;
}

public static function validateRegisterFields($username, $pass, $validatepassword): bool {
if((!$username) || (!$pass) || (!$validatepassword)) {
$error = "Please leave no fields blank";
echo $error;
return false;
}

if(strlen($pass) < 8) {
$error = "Password must be 8 characters or more";
echo $error;
return false;
}

if(strlen($validatepassword) < 8) {
$error = "Validate Password must be 8 or more characters";
echo $error;
return false;
}

if($pass != $validatepassword) {
$error = "Passwords must match";
echo $error;
return false;
}

return true;
}

}
class Checker {

public static function validateLoginFields($username, $pass): bool {
if((!$username) || (!$pass))
{
$error = "Please fill in all fields for processing the login";
echo $error;
return false;
}

return true;
}

public static function validateRegisterFields($username, $pass, $validatepassword): bool {
if((!$username) || (!$pass) || (!$validatepassword)) {
$error = "Please leave no fields blank";
echo $error;
return false;
}

if(strlen($pass) < 8) {
$error = "Password must be 8 characters or more";
echo $error;
return false;
}

if(strlen($validatepassword) < 8) {
$error = "Validate Password must be 8 or more characters";
echo $error;
return false;
}

if($pass != $validatepassword) {
$error = "Passwords must match";
echo $error;
return false;
}

return true;
}

}
ἔρως
ἔρως4mo ago
that's really not generic at all, but it's a move forward
ZomaTheMasterOfDisaster
how would you do it? i could just split it up into validating things separately
ἔρως
ἔρως4mo ago
a class that has a function that accepts a value and an array of what you want to validate and that array could be like ['email', 'required'] or ['string', 'maxlen' => 50, 'minlen' => 10, 'regex' => '@^[a-z]+$@i'] then the function validates if it is a string, the length, and the regex, or the email and if it exists or just a method for everything, and you use chaining to get you the result something like Validate::post('key')->email()->required()->valid(), and it returns either true or an array with errors
ZomaTheMasterOfDisaster
PHP
PHP Tutorial
PHP sanitize() Input Function
In this tutorial, you'll learn to develop a reusable PHP sanitize() function to sanitize inputs.
ἔρως
ἔρως4mo ago
or just sprinkle that all over that's valid as well but don't use sanitize, use filter_var
ZomaTheMasterOfDisaster
ok im just lost this all I got so far
ἔρως
ἔρως4mo ago
too many decisions, i know
ZomaTheMasterOfDisaster
<?php

namespace MD\helpers;

class Checker {

private $input;
private $validateArray;

public function __construct($input)
{
$this->input = $input;
}



public static function validateLoginFields($username, $pass): bool {
if((!$username) || (!$pass))
{
$error = "Please fill in all fields for processing the login";
echo $error;
return false;
}

return true;
}

public static function validateRegisterFields($username, $pass, $validatepassword): bool {
if((!$username) || (!$pass) || (!$validatepassword)) {
$error = "Please leave no fields blank";
echo $error;
return false;
}

if(strlen($pass) < 8) {
$error = "Password must be 8 characters or more";
echo $error;
return false;
}

if(strlen($validatepassword) < 8) {
$error = "Validate Password must be 8 or more characters";
echo $error;
return false;
}

if($pass != $validatepassword) {
$error = "Passwords must match";
echo $error;
return false;
}

return true;
}

}
<?php

namespace MD\helpers;

class Checker {

private $input;
private $validateArray;

public function __construct($input)
{
$this->input = $input;
}



public static function validateLoginFields($username, $pass): bool {
if((!$username) || (!$pass))
{
$error = "Please fill in all fields for processing the login";
echo $error;
return false;
}

return true;
}

public static function validateRegisterFields($username, $pass, $validatepassword): bool {
if((!$username) || (!$pass) || (!$validatepassword)) {
$error = "Please leave no fields blank";
echo $error;
return false;
}

if(strlen($pass) < 8) {
$error = "Password must be 8 characters or more";
echo $error;
return false;
}

if(strlen($validatepassword) < 8) {
$error = "Validate Password must be 8 or more characters";
echo $error;
return false;
}

if($pass != $validatepassword) {
$error = "Passwords must match";
echo $error;
return false;
}

return true;
}

}
ἔρως
ἔρως4mo ago
it's fine, you can leave as it was and just use it it's not the best, or optimal, but if it works then it works
ZomaTheMasterOfDisaster
well if you want to you can share better code so I can learn
ἔρως
ἔρως4mo ago
i wouldn't say i could write the best, but different i have my style, and i don't think my style is the best for you
ZomaTheMasterOfDisaster
well if your idea is more optimal I should learn it too so next project I can improve i mean php isnt the same as it was in 2012 so im having to relearn it
ἔρως
ἔρως4mo ago
that's alright, i will come up with something
ZomaTheMasterOfDisaster
Thanks Tbh my day is now a mess so any more confusion will get me nowhere
ἔρως
ἔρως4mo ago
i have a simpler idea for you write a class to validate the email, the password and the username (if you have one) should be a lot easier i was thinking too overcomplicated
ZomaTheMasterOfDisaster
a class for each? or just what i already have?
ἔρως
ἔρως4mo ago
no, for all
ZomaTheMasterOfDisaster
i made separate files for each validateusername.php and validatepassword.php
ἔρως
ἔρως4mo ago
class Validate {
static function email($input, $required = true) {
$errors = [];

if(!$input && $required) {
$errors[] = 'Email is required';
}

if($input && !$errors && !filter_var($input, ...)) {
$errors[] = 'Email is invalid';
}

return $errors ?: true;
}

...
}
class Validate {
static function email($input, $required = true) {
$errors = [];

if(!$input && $required) {
$errors[] = 'Email is required';
}

if($input && !$errors && !filter_var($input, ...)) {
$errors[] = 'Email is invalid';
}

return $errors ?: true;
}

...
}
something like this
ZomaTheMasterOfDisaster
I dropped email
ἔρως
ἔρως4mo ago
you get the gist
ZomaTheMasterOfDisaster
2nd if has an error ... says "expression expected"
ἔρως
ἔρως4mo ago
yeah, because it's pseudocode
ZomaTheMasterOfDisaster
since FILTER_SANITIZE_STRING is deprecated what are my options for a username?
ἔρως
ἔρως4mo ago
none, use htmlentities with an encoding or leave it null to use utf8 (default)
ZomaTheMasterOfDisaster
for password what about ENT stuff? ENT_IGNORE? DISALLOWED, ?
ἔρως
ἔρως4mo ago
try it
ZomaTheMasterOfDisaster
i just did whatever i came up with this
<?php

namespace MD\helpers;

class Validate {
static function username($input, $required=true) {
$errors = [];

if(!$input && $required) {
$errors[] = 'Username is required';
}

if($input && !$errors && !filter_var($input, htmlentities($input, ENT_DISALLOWED, "UTF-8"))) {
$errors[] = 'Username is invalid';
}

return $errors ?: true;
}

static function password($input, $required=true) {
$errors = [];
if(!$input && $required) {
$errors[] = 'Password is required';
}

if(strlen($input) < 8) {
$errors[] = 'Password must 8 or more characters';
}
}

static function valdiatePassword($input, $required=true) {
$errors = [];

if(!$input && $required) {
$errors[] = 'Validated Password is required';
}

if(strlen($input) < 8) {
$errors[] = 'Validated Password must be 8 or more characters';
}
}
}
<?php

namespace MD\helpers;

class Validate {
static function username($input, $required=true) {
$errors = [];

if(!$input && $required) {
$errors[] = 'Username is required';
}

if($input && !$errors && !filter_var($input, htmlentities($input, ENT_DISALLOWED, "UTF-8"))) {
$errors[] = 'Username is invalid';
}

return $errors ?: true;
}

static function password($input, $required=true) {
$errors = [];
if(!$input && $required) {
$errors[] = 'Password is required';
}

if(strlen($input) < 8) {
$errors[] = 'Password must 8 or more characters';
}
}

static function valdiatePassword($input, $required=true) {
$errors = [];

if(!$input && $required) {
$errors[] = 'Validated Password is required';
}

if(strlen($input) < 8) {
$errors[] = 'Validated Password must be 8 or more characters';
}
}
}
here's register.php
<?php
include '../../../vendor/autoload.php';
use MD\dbhelper\SQLConnection;
use MD\helpers\Validate;

$username = $_POST['username'];
$pass = $_POST['password'];
$validatePass = $_POST['validatepassword'];
$required = true;

if(isset($_POST['submit'])) {
// check the user input before database connection



}


?>

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Register</title>
</head>
<body>
<main>
<form action="" method="post">
<h1>Sign Up</h1>
<div>

<label for="username">Username:</label>
<input type="text" name="username" id="username">
</div>
<div>

<label for="password">Password:</label>
<input type="password" name="password" id="password">
</div>
<div>

<label for="validatepassword">Validate Password:</label>
<input type="password" name="validatepassword" id="validatepassword">
</div>
<div>
<button type="submit">Register</button>
<footer>Already a member? <a href="../login/login.php">Login Here</a></footer>
</div>
</form>
</main>
</body>
</html>
<?php
include '../../../vendor/autoload.php';
use MD\dbhelper\SQLConnection;
use MD\helpers\Validate;

$username = $_POST['username'];
$pass = $_POST['password'];
$validatePass = $_POST['validatepassword'];
$required = true;

if(isset($_POST['submit'])) {
// check the user input before database connection



}


?>

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Register</title>
</head>
<body>
<main>
<form action="" method="post">
<h1>Sign Up</h1>
<div>

<label for="username">Username:</label>
<input type="text" name="username" id="username">
</div>
<div>

<label for="password">Password:</label>
<input type="password" name="password" id="password">
</div>
<div>

<label for="validatepassword">Validate Password:</label>
<input type="password" name="validatepassword" id="validatepassword">
</div>
<div>
<button type="submit">Register</button>
<footer>Already a member? <a href="../login/login.php">Login Here</a></footer>
</div>
</form>
</main>
</body>
</html>
im thinking the validate class is brought in and since it has two return types... maybe I need two
ZomaTheMasterOfDisaster
updated register.php
ἔρως
ἔρως4mo ago
does this work?
ZomaTheMasterOfDisaster
So tomorrow how should I display these $errors[]
ἔρως
ἔρως4mo ago
that's the fun part: any way you want if you use ajax, send it over ajax if you only have php, make sure the errors are accessible where you render the form
ZomaTheMasterOfDisaster
That's the part I'm not sure about Since it's an array, I'm not sure how to display the proper messages in my html
ZomaTheMasterOfDisaster
GitHub
PHPTodoApp/app/views/register/register.php at main · MD-2016/PHPTod...
practice project to get back into php. Contribute to MD-2016/PHPTodoApp development by creating an account on GitHub.
ZomaTheMasterOfDisaster
That's what I got so far
ἔρως
ἔρως4mo ago
how are you passing the into to the file?
ZomaTheMasterOfDisaster
Well the validation happens when the user hits submit When isset is triggered for submit button
ἔρως
ἔρως4mo ago
does javascript send it? or is it a normal post?
ZomaTheMasterOfDisaster
Normal Post I didn't know how to do Js sending it
ἔρως
ἔρως4mo ago
then, where the form is, just render the messages how you render, varies based on the contents of the errors variable you can output it on the top of the form you can store the errors on an array with the key based on the name, and then for each field you output a message it's, almost literally, "loop and print"
ZomaTheMasterOfDisaster
So an associate array
ἔρως
ἔρως4mo ago
if you want you're asking about something that is very "do what you want" because there's no "right" way to do it just better or worse
ZomaTheMasterOfDisaster
Then for each loop in the html above the fields and top of form
ἔρως
ἔρως4mo ago
something like that, yes
ZomaTheMasterOfDisaster
Ok I'll have to try that tomorrow
ἔρως
ἔρως4mo ago
i can't give you a definitive answer because there isn't one but what you said is a good way to do it it isn't the best because there isn't one you code could use TONS of improvements
ZomaTheMasterOfDisaster
Yeah since I haven't used any js it made me wonder if it was more appropriate for form checking and only having php handle the requests
ἔρως
ἔρως4mo ago
it's fine, both are fine, both work
ZomaTheMasterOfDisaster
Yeah my code is sloppy 😦
ἔρως
ἔρως4mo ago
it's not sloppy just can be a lot better
ZomaTheMasterOfDisaster
What improvements are you suggesting?
ἔρως
ἔρως4mo ago
re-doing everything from line 6 to 30
$username = $_POST['username'];
$pass = $_POST['password'];
$validatePass = $_POST['validatepassword'];
$username = $_POST['username'];
$pass = $_POST['password'];
$validatePass = $_POST['validatepassword'];
^ this doesn't do anything and may actually cause issues because it throws warnings
$validatedUsername = false;
$validatedPassword = false;
$validatedValidPass = false;
$validatedUsername = false;
$validatedPassword = false;
$validatedValidPass = false;
^ you don't need this: if $errors is empty it means a success
$validatedUsername | $errors = Validate::username($username, $required);
$validatedPassword | $errors = Validate::password($pass, $required);
$validatedValidPass | $errors = Validate::valdiatePassword($validatePass, $pass, $required);
$validatedUsername | $errors = Validate::username($username, $required);
$validatedPassword | $errors = Validate::password($pass, $required);
$validatedValidPass | $errors = Validate::valdiatePassword($validatePass, $pass, $required);
^ this is a loop but you're doing it manually
ZomaTheMasterOfDisaster
I wasn't sure how to handle the $errors ?: true situation with this code
ἔρως
ἔρως4mo ago
the what???
ZomaTheMasterOfDisaster
GitHub
PHPTodoApp/app/class/helpers/formcheck.php at main · MD-2016/PHPTod...
practice project to get back into php. Contribute to MD-2016/PHPTodoApp development by creating an account on GitHub.
ἔρως
ἔρως4mo ago
oh, that im just saying that you're doing what a loop does, but you're doing it manually
ZomaTheMasterOfDisaster
How do I do it in a loop since the return was ?:
ἔρως
ἔρως4mo ago
what does that have to do with anything?
ZomaTheMasterOfDisaster
I'm bringing those functions From formcheck
ἔρως
ἔρως4mo ago
what's the problem with ?:?
ZomaTheMasterOfDisaster
That's a ternary return meaning it could be a string or boolean?
ἔρως
ἔρως4mo ago
yes, and? what's confusing about that?
ZomaTheMasterOfDisaster
Never seen it before so I wasn't sure how to handle it with using it in my register page
ἔρως
ἔρως4mo ago
you handle it is pretending it doesn't exist it's an implementation detail of the function just set the correct return types and you're good to go
ZomaTheMasterOfDisaster
So the correct return type is a boolean?
ἔρως
ἔρως4mo ago
no the correct type is an array OR a boolean array|bool 8.x lets you define multiple types
ZomaTheMasterOfDisaster
Ok that's kinda new
ἔρως
ἔρως4mo ago
it's from 8.0
ZomaTheMasterOfDisaster
Yeah I'm reading
ἔρως
ἔρως4mo ago
you were overthinking
ZomaTheMasterOfDisaster
so i deleted the code from line 6 just kept the errors string array and required boolean
ἔρως
ἔρως4mo ago
does it work?
ZomaTheMasterOfDisaster
i havent done anything in if(isset($_POST['submit'])) { // check the user input before database connection // code here for success and start database connection and prepared statement }
ἔρως
ἔρως4mo ago
that's 80% of your work done planning
ZomaTheMasterOfDisaster
yeah just thinking about how to do that loop since I need to check each input, display the proper error message, and call the right functions to validate from the formcheck.php
ἔρως
ἔρως4mo ago
associative arrays help a lot
ZomaTheMasterOfDisaster
maybe an asosciate array with the form element name mapping to the error message? thing is there is more than one for each
ἔρως
ἔρως4mo ago
yup there exist this one amazing thing called "array" where you can just shove stuff into it, automatically, in numeric order
ZomaTheMasterOfDisaster
static function username($input, $required=true) {
$errors = [];

if(empty($input) && $required) {
$errors[] = 'Username is required';
}

if($input && !$errors && !filter_var($input, htmlentities($input, ENT_DISALLOWED, "UTF-8"))) {
$errors[] = 'Username is invalid';
}

return $errors ?: true;
}
static function username($input, $required=true) {
$errors = [];

if(empty($input) && $required) {
$errors[] = 'Username is required';
}

if($input && !$errors && !filter_var($input, htmlentities($input, ENT_DISALLOWED, "UTF-8"))) {
$errors[] = 'Username is invalid';
}

return $errors ?: true;
}
ἔρως
ἔρως4mo ago
yeah, you may have 2 errors that's fine
ZomaTheMasterOfDisaster
but my form name can only map to one of them in an array
ἔρως
ἔρως4mo ago
you know you can put arrays in arrays?
ZomaTheMasterOfDisaster
so a form element name pointing to an array of error messages?
ἔρως
ἔρως4mo ago
im trying really hard not to tell you what to do, but hinting on a way to do it yes
ZomaTheMasterOfDisaster
$inputArray = array("username" => ['Username is required', 'Username is invalid'], "password" => ['Password is required', 'Password must 8 or more characters'], "validatepassword" => ['Validated Password is required', 'Validated Password must be 8 or more characters', 'Passwords dont match']);
$inputArray = array("username" => ['Username is required', 'Username is invalid'], "password" => ['Password is required', 'Password must 8 or more characters'], "validatepassword" => ['Validated Password is required', 'Validated Password must be 8 or more characters', 'Passwords dont match']);
ἔρως
ἔρως4mo ago
that would be thje final result, if there's errors
ZomaTheMasterOfDisaster
im just a little confused on putting this all together I know there's the validation functions I need to call from formcheck.php and they return array | boolean, populate the $errors[] as needed, process the POST stuff with these 3 variables
$required = true;
$errors = [];
$inputArray = array("username" => ['Username is required', 'Username is invalid'], "password" => ['Password is required', 'Password must 8 or more characters'], "validatepassword" => ['Validated Password is required', 'Validated Password must be 8 or more characters', 'Passwords dont match']);
$required = true;
$errors = [];
$inputArray = array("username" => ['Username is required', 'Username is invalid'], "password" => ['Password is required', 'Password must 8 or more characters'], "validatepassword" => ['Validated Password is required', 'Validated Password must be 8 or more characters', 'Passwords dont match']);
ἔρως
ἔρως4mo ago
what's that $inputarray?
ZomaTheMasterOfDisaster
idk i just made it based on previous discussion yes the "final result"
ἔρως
ἔρως4mo ago
why?
ZomaTheMasterOfDisaster
$validateUsername | $errors = Validate::username($_POST['username'], $required);
$validatePass | $errors = Validate::password($_POST['password'], $required);
$validatePassBoth | $errors = Validate::valdiatePassword($_POST['validatepassword'], $_POST['password'], $required);
$validateUsername | $errors = Validate::username($_POST['username'], $required);
$validatePass | $errors = Validate::password($_POST['password'], $required);
$validatePassBoth | $errors = Validate::valdiatePassword($_POST['validatepassword'], $_POST['password'], $required);
sorry just a little lost with this setup
ἔρως
ἔρως4mo ago
im trying to understand how you are lost
ZomaTheMasterOfDisaster
that's the above code I got
ἔρως
ἔρως4mo ago
what are you trying to do? can you describe it to me, step by step? tell me the algorithm
ZomaTheMasterOfDisaster
- user hits submit - validate the username, password, validatepassword fields - check if their good (true) or display an appropriate error message
- stop on errors from processing above input - only authorize connection to database if input passes
ἔρως
ἔρως4mo ago
in a list form, please? im a stupid robot, and you need to explain to me, step by step, what you want the code to do define "user input"
ZomaTheMasterOfDisaster
username, password, validatepassword
ἔρως
ἔρως4mo ago
add it to the list
ZomaTheMasterOfDisaster
updated
ἔρως
ἔρως4mo ago
what stops on errors?
ZomaTheMasterOfDisaster
processing input
ἔρως
ἔρως4mo ago
add it to the list
ZomaTheMasterOfDisaster
well I got the user hitting submit check with if(isset($_POST['submit'))
ἔρως
ἔρως4mo ago
yes, but don't talk about implementation details if you aren't sure of what you're implementing first, know what you're implementing define all steps and how it will be processed then, you write the code
ZomaTheMasterOfDisaster
i pretty much defined all the steps
ἔρως
ἔρως4mo ago
so, if the email is empty, it stops checking that the password is empty too?
ZomaTheMasterOfDisaster
if(isset($_POST['submit'])) {
// if the validation is successful
if($validateUsername && $validatePass && $validatePassBoth)
{

}
else {
// handling errors
}
if(isset($_POST['submit'])) {
// if the validation is successful
if($validateUsername && $validatePass && $validatePassBoth)
{

}
else {
// handling errors
}
ἔρως
ἔρως4mo ago
the list is wrong then it says it stops on errors but it doesnt it validates all inputs and then decides on what it does
ZomaTheMasterOfDisaster
well either this or I do each one individually
ἔρως
ἔρως4mo ago
as you should do you know how to make a flow diagram?
ZomaTheMasterOfDisaster
been a long time since ive done programming logic and design that was like 2009
ἔρως
ἔρως4mo ago
you should make a flow diagram
ZomaTheMasterOfDisaster
if($validateUsername) {

}

if($validatePass) {

}

if($validatePassBoth) {

}
if($validateUsername) {

}

if($validatePass) {

}

if($validatePassBoth) {

}
ἔρως
ἔρως4mo ago
i havent done one since 2009 either
ZomaTheMasterOfDisaster
that means more studying and I need to get into a job by summer or it's over for me
ἔρως
ἔρως4mo ago
i know this sounds like im wasting your time, but you're implementing badly defined features, and you end up with messy undebuggable code that not even a mother would love
ZomaTheMasterOfDisaster
maybe im just not meant to be a programmer
ἔρως
ἔρως4mo ago
open excalidraw and make a flor diagram
ZomaTheMasterOfDisaster
my code never been that great anyway it just worked for school
ἔρως
ἔρως4mo ago
dude, listen to me your code isn't "not good" not because of lack of knowledge you're just waffling about, trying to blindly implement something but you don't have defined what you will implement
ZomaTheMasterOfDisaster
does anyone in this server do that?
ἔρως
ἔρως4mo ago
do what?
ZomaTheMasterOfDisaster
flow diagrams and such most just write code
ἔρως
ἔρως4mo ago
and they write amazing code and never ask for help, right?
ZomaTheMasterOfDisaster
idk cdl and I just burned out I guess
ἔρως
ἔρως4mo ago
you think im not tired?
ZomaTheMasterOfDisaster
idk if they write amazing code 😄
ἔρως
ἔρως4mo ago
ive slept a total of a little above 15 hours these last 3 days
ZomaTheMasterOfDisaster
you should rest then 🙂
ἔρως
ἔρως4mo ago
i've been extremely tired all month ive been working 9-10 hours almost everyday what im telling you to do is to stop stop, organize your head, draw what you are thinking on how it will be implemented, then write the code right now, you're just doing the equivalent of throwing pasta to a wall and see if it sticks so, stop, put your ideas into something visual, then do what you need to do
ZomaTheMasterOfDisaster
i dont like drawing those diagrams and never did them correctly i mostly just listed this stuff here's what I came up with thinking back to what I remember that's everything it should do but the setup is different so it's a bit harder to see the implementation
ἔρως
ἔρως4mo ago
step 5 is useless you don't "check for xss input" you just output what you need by making it into a safe html string
ZomaTheMasterOfDisaster
sorry mom was bugging about adware on youtube talking about "work from home" jobs for companies that dont even hire for those roles im back now
ἔρως
ἔρως4mo ago
it's fine by the way, you forgot the part where you show the errors
ZomaTheMasterOfDisaster
"Report error" is showing the errors
ἔρως
ἔρως4mo ago
how? where's the step where the errors will be shown? will you show the error right after validating? will you show the errors all together at the top of the form? will you show the errors by input?
ZomaTheMasterOfDisaster
updated
ἔρως
ἔρως4mo ago
- display the error message to the user <-- how? where? when?
ἔρως
ἔρως4mo ago
yes, i read the list, but my question is still unanswered which is an important step
ZomaTheMasterOfDisaster
i cant edit it anymore too big for discord
ἔρως
ἔρως4mo ago
it's fine, just say it here
ZomaTheMasterOfDisaster
- display error message from errors array to the user on top of form
ἔρως
ἔρως4mo ago
the classic way implement this for 1 input
ZomaTheMasterOfDisaster
been a long time since ive done logic and design apparently it's killed me not keeping up with it
ἔρως
ἔρως4mo ago
i can see it, which is why i have to force you to re-think about it
ZomaTheMasterOfDisaster
along with data structures and algorithms
ἔρως
ἔρως4mo ago
but, go ahead and implement this for the email input
ZomaTheMasterOfDisaster
i dont use email took that out just username for this small project
ἔρως
ἔρως4mo ago
pick 1 field and validate it username, validate it AND ONLY THAT ONE
ZomaTheMasterOfDisaster
ok I have the idea but we have an issue we have this
$validateUsername | $errors = Validate::username($_POST['username'], $required);
$validateUsername | $errors = Validate::username($_POST['username'], $required);
to start with which is boolean | array
ἔρως
ἔρως4mo ago
okay, and the issue is?
ZomaTheMasterOfDisaster
so that function is going to check for empty and then add the error to $errors
ἔρως
ἔρως4mo ago
no, what it is doing is outputting a boolean or an array
ZomaTheMasterOfDisaster
otherwise return true
<?php

namespace MD\helpers;

class Validate {
static function username($input, $required=true) {
$errors = [];

if(empty($input) && $required) {
$errors[] = 'Username is required';
}

if($input && !$errors && !filter_var($input, htmlentities($input, ENT_DISALLOWED, "UTF-8"))) {
$errors[] = 'Username is invalid';
}

return $errors ?: true;
}

static function password($input, $required=true) {
$errors = [];
if(empty($input) && $required) {
$errors[] = 'Password is required';
}

if(strlen($input) < 8) {
$errors[] = 'Password must 8 or more characters';
}

return $errors ?: true;
}

static function valdiatePassword($input, $pass2, $required=true) {
$errors = [];

if(!$input && $required) {
$errors[] = 'Validated Password is required';
}

if(strlen($input) < 8) {
$errors[] = 'Validated Password must be 8 or more characters';
}

if(strcmp($input, $pass2) != 0) {
$errors[] = 'Passwords dont match';
}

return $errors ?: true;
}
}
<?php

namespace MD\helpers;

class Validate {
static function username($input, $required=true) {
$errors = [];

if(empty($input) && $required) {
$errors[] = 'Username is required';
}

if($input && !$errors && !filter_var($input, htmlentities($input, ENT_DISALLOWED, "UTF-8"))) {
$errors[] = 'Username is invalid';
}

return $errors ?: true;
}

static function password($input, $required=true) {
$errors = [];
if(empty($input) && $required) {
$errors[] = 'Password is required';
}

if(strlen($input) < 8) {
$errors[] = 'Password must 8 or more characters';
}

return $errors ?: true;
}

static function valdiatePassword($input, $pass2, $required=true) {
$errors = [];

if(!$input && $required) {
$errors[] = 'Validated Password is required';
}

if(strlen($input) < 8) {
$errors[] = 'Validated Password must be 8 or more characters';
}

if(strcmp($input, $pass2) != 0) {
$errors[] = 'Passwords dont match';
}

return $errors ?: true;
}
}
ἔρως
ἔρως4mo ago
but, again, what is the issue? you have a boolean, you have an array
ZomaTheMasterOfDisaster
I guess check if the boolean is false?
ἔρως
ἔρως4mo ago
the function outputs true or an array it will never be false
ZomaTheMasterOfDisaster
yeah this is confusing
ἔρως
ἔρως4mo ago
it's not true = no errors, array = errors
ZomaTheMasterOfDisaster
so what am i saying
if($validateUsername) {}
if($validateUsername) {}
or
if(strlen($errors) != 0) {}
if(strlen($errors) != 0) {}
just weird trying to tie this all together
ἔρως
ἔρως4mo ago
i see where the confusion stems from you have 2 return types, and you think you need 2 variables for it but no, you don't
ZomaTheMasterOfDisaster
yes the confusion is how this is going into register.php since formcheck.php handles some of the checking
ἔρως
ἔρως4mo ago
$validateUsername | $errors <-- this is a bitwise or
ZomaTheMasterOfDisaster
the logic makes sense on paper but trying to tie together with the current implemntation details isn't making sense ok but im not seeing how to handle it for each input
ἔρως
ἔρως4mo ago
focus on 1 input
ZomaTheMasterOfDisaster
this is why I understood the code I started with all these "updated changes" made it more confusing I just know older php this new stuff is just making it into Java
ἔρως
ἔρως4mo ago
this has nothing to do with "new" or "old" php you would have to write the same code in 7.x, 5.6 or even 5.3
ZomaTheMasterOfDisaster
the code I started with before we made a lot of changes is what I understood since you said it was "bad" ok so I need to do a bitwise or check in the if?
ἔρως
ἔρως4mo ago
no
ZomaTheMasterOfDisaster
since the return type is bitwise or I wont know what im getting so id have to check for both somehow
ἔρως
ἔρως4mo ago
it's not bitwise you are using bitwise operations on the result value, which after testing, i verified that it doesn't work
ZomaTheMasterOfDisaster
so do I need to change the result on formcheck.php? does this need changed then?
ἔρως
ἔρως4mo ago
you have 2 options: 1- keep as is, and check if it is a boolean or an array 2- change the name of something to indicate that it doesn't have errors, and change the return value to false
ZomaTheMasterOfDisaster
that's the issue was checking if it's a boolean or array that's where im stuck
ἔρως
ἔρως4mo ago
return false then
ZomaTheMasterOfDisaster
because I have to check it for each
ἔρως
ἔρως4mo ago
or just return an empty array and document that it returns an array of errors
ZomaTheMasterOfDisaster
let's just start here
static function username($input, $required=true) {
$errors = [];

if(empty($input) && $required) {
$errors[] = 'Username is required';
}

if($input && !$errors && !filter_var($input, htmlentities($input, ENT_DISALLOWED, "UTF-8"))) {
$errors[] = 'Username is invalid';
}

return $errors ?: true;
}
static function username($input, $required=true) {
$errors = [];

if(empty($input) && $required) {
$errors[] = 'Username is required';
}

if($input && !$errors && !filter_var($input, htmlentities($input, ENT_DISALLOWED, "UTF-8"))) {
$errors[] = 'Username is invalid';
}

return $errors ?: true;
}
so we know the return is array or boolean this means we check for either an empty array or boolean? does php have functions for that?
ἔρως
ἔρως4mo ago
change it to return just the $errors variable it's easier to reason with
ZomaTheMasterOfDisaster
there is an is_array and is_bool functions I can use
if(is_array($validateUsername)) {

}
if(is_array($validateUsername)) {

}
ἔρως
ἔρως4mo ago
just try what i said and lets see how it works
ZomaTheMasterOfDisaster
so what I put is wrong?
ἔρως
ἔρως4mo ago
no im just telling you to simplify
ZomaTheMasterOfDisaster
<?php

namespace MD\helpers;

class Validate {
static function username($input, $required=true) {
$errors = [];

if(empty($input) && $required) {
$errors[] = 'Username is required';
}

if($input && !$errors && !filter_var($input, htmlentities($input, ENT_DISALLOWED, "UTF-8"))) {
$errors[] = 'Username is invalid';
}

return $errors;
}

static function password($input, $required=true) {
$errors = [];
if(empty($input) && $required) {
$errors[] = 'Password is required';
}

if(strlen($input) < 8) {
$errors[] = 'Password must 8 or more characters';
}

return $errors;
}

static function valdiatePassword($input, $pass2, $required=true) {
$errors = [];

if(!$input && $required) {
$errors[] = 'Validated Password is required';
}

if(strlen($input) < 8) {
$errors[] = 'Validated Password must be 8 or more characters';
}

if(strcmp($input, $pass2) != 0) {
$errors[] = 'Passwords dont match';
}

return $errors;
}
}
<?php

namespace MD\helpers;

class Validate {
static function username($input, $required=true) {
$errors = [];

if(empty($input) && $required) {
$errors[] = 'Username is required';
}

if($input && !$errors && !filter_var($input, htmlentities($input, ENT_DISALLOWED, "UTF-8"))) {
$errors[] = 'Username is invalid';
}

return $errors;
}

static function password($input, $required=true) {
$errors = [];
if(empty($input) && $required) {
$errors[] = 'Password is required';
}

if(strlen($input) < 8) {
$errors[] = 'Password must 8 or more characters';
}

return $errors;
}

static function valdiatePassword($input, $pass2, $required=true) {
$errors = [];

if(!$input && $required) {
$errors[] = 'Validated Password is required';
}

if(strlen($input) < 8) {
$errors[] = 'Validated Password must be 8 or more characters';
}

if(strcmp($input, $pass2) != 0) {
$errors[] = 'Passwords dont match';
}

return $errors;
}
}
ἔρως
ἔρως4mo ago
now it only returns an array
ZomaTheMasterOfDisaster
so i would check if the array isnt empty
ἔρως
ἔρως4mo ago
yup if it isn't empty, it has errors
ZomaTheMasterOfDisaster
i can use empty()
ἔρως
ἔρως4mo ago
yes and no you can, but for THIS VERY UNIQUE AND SPECIFIC EXAMPLE, it is overkill
ZomaTheMasterOfDisaster
i guess normal would be for php
if (errors != ''){}
if (errors != ''){}
ἔρως
ἔρως4mo ago
that's checking if the constant error isn't set to an empty string
ZomaTheMasterOfDisaster
ill check if count != 0
ἔρως
ἔρως4mo ago
or just use the variable, alone, in the if
ZomaTheMasterOfDisaster
hmm? if($validateUsername){}
ἔρως
ἔρως4mo ago
yup but, you don't have to do it there just shove it all into an array, with the name of the field as the key
ZomaTheMasterOfDisaster
ok i got the
if(!$validateUsername){}
if(!$validateUsername){}
started so now i need to get the message from the error array and add it to my error array on that page then display it
ἔρως
ἔρως4mo ago
if you do something like this, you can save A TON of work
ZomaTheMasterOfDisaster
ok so I got an errors array already I just need to populate it with the apprioate stuff
ἔρως
ἔρως4mo ago
basically, yes, it's an option
ZomaTheMasterOfDisaster
like this
if(!$validateUsername) {
$errors = ['username' => [$validateUsername]];
}
if(!$validateUsername) {
$errors = ['username' => [$validateUsername]];
}
ἔρως
ἔρως4mo ago
no but it's close
ἔρως
ἔρως4mo ago
it's really close
ZomaTheMasterOfDisaster
$errors = ['username' => $valdiateUsername];
$errors = ['username' => $valdiateUsername];
ἔρως
ἔρως4mo ago
very very very close the variable is useless
ZomaTheMasterOfDisaster
$errors['username'] = $validateUsername
ἔρως
ἔρως4mo ago
go back to the other version skip assigning that weird long ass variable
ZomaTheMasterOfDisaster
idk all i see is this
ZomaTheMasterOfDisaster
PHP
PHP Tutorial
PHP Associative Arrays
In this tutorial, you will learn about PHP associative arrays and how to use them effectively.
ἔρως
ἔρως4mo ago
dude, do literally what i said this time, im telling you what to do
ZomaTheMasterOfDisaster
ok...
$errors = ['username' => ];
$errors = ['username' => ];
ἔρως
ἔρως4mo ago
now, what's missing there?
ZomaTheMasterOfDisaster
the string from the $validateUsername
ἔρως
ἔρως4mo ago
and what supposed string comes from where?
ZomaTheMasterOfDisaster
Validate::username()
ἔρως
ἔρως4mo ago
since you removed the variable, what do you have to do?
ZomaTheMasterOfDisaster
$errors = ['username' => Validate::username($_POST['username'], $required)];
$errors = ['username' => Validate::username($_POST['username'], $required)];
ἔρως
ἔρως4mo ago
very good by the way, are you using vscode?
ZomaTheMasterOfDisaster
so I need to delete that valdiateUsername
ἔρως
ἔρως4mo ago
that's the variable? yes, it's utterly useless
ZomaTheMasterOfDisaster
ok so what do I put in the if
ἔρως
ἔρως4mo ago
install the extension first
ZomaTheMasterOfDisaster
ive had that installed before you mentioned it
ἔρως
ἔρως4mo ago
alright right now, don't think about it show me the full code
ZomaTheMasterOfDisaster
if() {
$errors = ['username' => Validate::username($_POST['username'], $required)];
}
if() {
$errors = ['username' => Validate::username($_POST['username'], $required)];
}
ἔρως
ἔρως4mo ago
what's that if?
ZomaTheMasterOfDisaster
that's what's left removing the $validateUsername
ἔρως
ἔρως4mo ago
okay show me the full code
ZomaTheMasterOfDisaster
wouldn't that be in the html
ἔρως
ἔρως4mo ago
the full php file
ZomaTheMasterOfDisaster
<?php
include '../../../vendor/autoload.php';
use MD\dbhelper\SQLConnection;
use MD\helpers\Validate;

$required = true;
$errors = [];
$validatePass = Validate::password($_POST['password'], $required);
$validatePassBoth = Validate::valdiatePassword($_POST['validatepassword'], $_POST['password'], $required);
/*$inputArray = array("username" => ['Username is required', 'Username is invalid'], "password" => ['Password is required', 'Password must 8 or more characters'], "validatepassword" => ['Validated Password is required', 'Validated Password must be 8 or more characters', 'Passwords dont match']);*/
if(isset($_POST['submit'])) {
// if the validation is successful
if() {
$errors = ['username' => Validate::username($_POST['username'], $required)];

}

}

// deal with printing out errors


}


?>

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Register</title>
</head>
<body>
<main>
<form action="" method="post">
<h1>Sign Up</h1>
<div>

<label for="username">Username:</label>
<input type="text" name="username" id="username">
</div>
<div>

<label for="password">Password:</label>
<input type="password" name="password" id="password">
</div>
<div>

<label for="validatepassword">Validate Password:</label>
<input type="password" name="validatepassword" id="validatepassword">
</div>
<div>
<button type="submit">Register</button>
<footer>Already a member? <a href="../login/login.php">Login Here</a></footer>
</div>
</form>
</main>
</body>
</html>
<?php
include '../../../vendor/autoload.php';
use MD\dbhelper\SQLConnection;
use MD\helpers\Validate;

$required = true;
$errors = [];
$validatePass = Validate::password($_POST['password'], $required);
$validatePassBoth = Validate::valdiatePassword($_POST['validatepassword'], $_POST['password'], $required);
/*$inputArray = array("username" => ['Username is required', 'Username is invalid'], "password" => ['Password is required', 'Password must 8 or more characters'], "validatepassword" => ['Validated Password is required', 'Validated Password must be 8 or more characters', 'Passwords dont match']);*/
if(isset($_POST['submit'])) {
// if the validation is successful
if() {
$errors = ['username' => Validate::username($_POST['username'], $required)];

}

}

// deal with printing out errors


}


?>

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Register</title>
</head>
<body>
<main>
<form action="" method="post">
<h1>Sign Up</h1>
<div>

<label for="username">Username:</label>
<input type="text" name="username" id="username">
</div>
<div>

<label for="password">Password:</label>
<input type="password" name="password" id="password">
</div>
<div>

<label for="validatepassword">Validate Password:</label>
<input type="password" name="validatepassword" id="validatepassword">
</div>
<div>
<button type="submit">Register</button>
<footer>Already a member? <a href="../login/login.php">Login Here</a></footer>
</div>
</form>
</main>
</body>
</html>
`
ἔρως
ἔρως4mo ago
$validatePass = Validate::password($_POST['password'], $required);
$validatePassBoth = Validate::valdiatePassword($_POST['validatepassword'], $_POST['password'], $required);
$validatePass = Validate::password($_POST['password'], $required);
$validatePassBoth = Validate::valdiatePassword($_POST['validatepassword'], $_POST['password'], $required);
^ what are these for? same question ^
ἔρως
ἔρως4mo ago
why are you re-creating the array 3 times, inside of leftover ifs?
ZomaTheMasterOfDisaster
i have no clue im just following the logic of the steps i wrote out
ἔρως
ἔρως4mo ago
but now, think about this you have an array an array can have multiple keys correct?
ZomaTheMasterOfDisaster
yes if associative
ἔρως
ἔρως4mo ago
then why don't you put it all into the same array? without the if
ZomaTheMasterOfDisaster
so do it all in one if?
ἔρως
ἔρως4mo ago
no ifs it's empty for a reason: it's of no use now
ZomaTheMasterOfDisaster
if(isset($_POST['submit'])) {
// if the validation is successful
$errors = ['username' => Validate::username($_POST['username'], $required), 'password' => Validate::password($_POST['password'], $required), 'validatepassword' => Validate::valdiatePassword($_POST['validatepassword'], $_POST['password'], $required)];

// deal with printing out errors


}
if(isset($_POST['submit'])) {
// if the validation is successful
$errors = ['username' => Validate::username($_POST['username'], $required), 'password' => Validate::password($_POST['password'], $required), 'validatepassword' => Validate::valdiatePassword($_POST['validatepassword'], $_POST['password'], $required)];

// deal with printing out errors


}
ἔρως
ἔρως4mo ago
very good now format is properly one array value per line
ZomaTheMasterOfDisaster
// if the validation is successful
$errors = ['username' => Validate::username($_POST['username'], $required),
'password' => Validate::password($_POST['password'], $required),
'validatepassword' => Validate::valdiatePassword($_POST['validatepassword'], $_POST['password'], $required)];

// deal with printing out errors
// if the validation is successful
$errors = ['username' => Validate::username($_POST['username'], $required),
'password' => Validate::password($_POST['password'], $required),
'validatepassword' => Validate::valdiatePassword($_POST['validatepassword'], $_POST['password'], $required)];

// deal with printing out errors
ἔρως
ἔρως4mo ago
fix the indentation
ZomaTheMasterOfDisaster
that doesnt happen on vscode it's discord
ἔρως
ἔρως4mo ago
alright now, you see what you've done?
ZomaTheMasterOfDisaster
yeah no ifs shorted the code but this means my code in the html will need changed normally in java i would've used try catch for some error handling
ἔρως
ἔρως4mo ago
it was wrong in the first place that's an option, but you can only throw 1 exception per field, while each field may have multiple errors
ZomaTheMasterOfDisaster
yeah next up is
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Register</title>
</head>
<body>
<main>
<?php echo '<span>${$errors}</span>'?>
<form action="" method="post">
<h1>Sign Up</h1>
<div>

<label for="username">Username:</label>
<input type="text" name="username" id="username">
</div>
<div>

<label for="password">Password:</label>
<input type="password" name="password" id="password">
</div>
<div>

<label for="validatepassword">Validate Password:</label>
<input type="password" name="validatepassword" id="validatepassword">
</div>
<div>
<button type="submit">Register</button>
<footer>Already a member? <a href="../login/login.php">Login Here</a></footer>
</div>
</form>
</main>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Register</title>
</head>
<body>
<main>
<?php echo '<span>${$errors}</span>'?>
<form action="" method="post">
<h1>Sign Up</h1>
<div>

<label for="username">Username:</label>
<input type="text" name="username" id="username">
</div>
<div>

<label for="password">Password:</label>
<input type="password" name="password" id="password">
</div>
<div>

<label for="validatepassword">Validate Password:</label>
<input type="password" name="validatepassword" id="validatepassword">
</div>
<div>
<button type="submit">Register</button>
<footer>Already a member? <a href="../login/login.php">Login Here</a></footer>
</div>
</form>
</main>
</body>
</html>
ἔρως
ἔρως4mo ago
hold there, buster! you aren't done yet now, you need to do something when it doesn't have any errors, right?
ZomaTheMasterOfDisaster
yeah i guess santize input and pass to database?
ἔρως
ἔρως4mo ago
before you even touch that, how do you know if you have any errors?
ZomaTheMasterOfDisaster
check if (!$errors)
ἔρως
ἔρως4mo ago
but you have 3 values won't it always be a truthy value?
ZomaTheMasterOfDisaster
check if each key has an empty value?
ἔρως
ἔρως4mo ago
and how do you do that in a concise way?
ἔρως
ἔρως4mo ago
how about filtering out the empty arrays? you won't need them, so, toss them out, right?
ZomaTheMasterOfDisaster
or you could use array_key_exists and is_null
ἔρως
ἔρως4mo ago
the key will always exist and will never be null since you return an empty array
ἔρως
ἔρως4mo ago
how about you wrap the array into a call to array_filter?
ZomaTheMasterOfDisaster
ok so i need the array and a callback
ἔρως
ἔρως4mo ago
no, just the array read the notes
ZomaTheMasterOfDisaster
ok default is empty()
ἔρως
ἔρως4mo ago
yup so, just $errors = array_filter([ ... ]) and you're done
ZomaTheMasterOfDisaster
$errors = array_filter($errors);
$errors = array_filter($errors);
since it returns an array
ἔρως
ἔρως4mo ago
or, just save some lines and put it all together that's why functions accept values, instead of just variables but, if you want to be more expressive and explicit, that is perfectly valid
ZomaTheMasterOfDisaster
if(isset($_POST['submit'])) {
// build an error array just in case
$errors = array_filter(['username' => Validate::username($_POST['username'], $required),
'password' => Validate::password($_POST['password'], $required),
'validatepassword' => Validate::valdiatePassword($_POST['validatepassword'], $_POST['password'], $required)]);
}
if(isset($_POST['submit'])) {
// build an error array just in case
$errors = array_filter(['username' => Validate::username($_POST['username'], $required),
'password' => Validate::password($_POST['password'], $required),
'validatepassword' => Validate::valdiatePassword($_POST['validatepassword'], $_POST['password'], $required)]);
}
ἔρως
ἔρως4mo ago
basically, yes now $errors is empty of has something in it
ZomaTheMasterOfDisaster
<?php echo '<span>{$errors}</span>'?>
<?php echo '<span>{$errors}</span>'?>
ἔρως
ἔρως4mo ago
no it's an array you can't convert an array to strings
ZomaTheMasterOfDisaster
so ill need to use a foreach loop
ἔρως
ἔρως4mo ago
yup but you know what would be even smarter?
ἔρως
ἔρως4mo ago
map, but would be better to show the message under the field that generated it
ZomaTheMasterOfDisaster
that's the fun part what "field" shows
ἔρως
ἔρως4mo ago
what do you mean?
ZomaTheMasterOfDisaster
because ill need to see what field is being displayed brb mom is getting frustrated with the tv
ἔρως
ἔρως4mo ago
you have the name of the field as a key this is what i would do i would check if the $errors[<field_name> is empty, then output an <ol>, loop over the errors - an <li></li> per error, then outside the loop just output a final </ol>
ZomaTheMasterOfDisaster
so more than one error?
ἔρως
ἔρως4mo ago
they will be ordered numerically
ZomaTheMasterOfDisaster
ok so I need to use a loop
ἔρως
ἔρως4mo ago
yes
ZomaTheMasterOfDisaster
with ifs inside then?
ἔρως
ἔρως4mo ago
no no ifs
ZomaTheMasterOfDisaster
ok this started
foreach($errors as $errorFound) {

}
foreach($errors as $errorFound) {

}
ἔρως
ἔρως4mo ago
no that's for all errors, not per field
ZomaTheMasterOfDisaster
i see so I need to check if values of a key are empty otherwise loop
ἔρως
ἔρως4mo ago
yup
ZomaTheMasterOfDisaster
so that will be 3 ifs or just one?
ἔρως
ἔρως4mo ago
3 ifs
ZomaTheMasterOfDisaster
if($errors['username']-> "") {}
if($errors['username']-> "") {}
ἔρως
ἔρως4mo ago
no, it's an array, not an object and you can't use empty strings as strings for properties
ἔρως
ἔρως4mo ago
that should be easy
ZomaTheMasterOfDisaster
COUNT_RECURSIVE?
ἔρως
ἔρως4mo ago
no
ἔρως
ἔρως4mo ago
do you want to show all the errors at the top? or on each input?
ZomaTheMasterOfDisaster
just inputs that fail
ἔρως
ἔρως4mo ago
for each input, check if the errors for that name are empty
ZomaTheMasterOfDisaster
if($errors['username'] == '')
if($errors['username'] == '')
ἔρως
ἔρως4mo ago
that works by pure sheer luck
ZomaTheMasterOfDisaster
what is the "proper way"
ἔρως
ἔρως4mo ago
it's not correct, it's not actually working properly empty check if it's not empty
ZomaTheMasterOfDisaster
so
if(!empty($errors['username']))
if(!empty($errors['username']))
ἔρως
ἔρως4mo ago
not empty yes that
ZomaTheMasterOfDisaster
ok so this means $errors has one or more
ἔρως
ἔρως4mo ago
yes
ZomaTheMasterOfDisaster
so i need a loop that says
foreach($errors['username'] as $usernameError) {
// echo span with the error
}
foreach($errors['username'] as $usernameError) {
// echo span with the error
}
ἔρως
ἔρως4mo ago
as $error don't be so verbose you know it's an username error
ZomaTheMasterOfDisaster
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Register</title>
</head>
<body>
<main>
<?php
if(!empty($errors['username'])) {
foreach ($errors as $error) {
echo '<span>{$error}</span>';
}
}

if(!empty($errors['password'])) {
foreach ($errors as $error) {
echo '<span>{$error}</span>';
}

if(!empty($errors['validatepassword'])) {
foreach ($errors as $error) {
echo '<span>{$error}</span>';
}
}
}
?>
<form action="" method="post">
<h1>Sign Up</h1>
<div>

<label for="username">Username:</label>
<input type="text" name="username" id="username">
</div>
<div>

<label for="password">Password:</label>
<input type="password" name="password" id="password">
</div>
<div>

<label for="validatepassword">Validate Password:</label>
<input type="password" name="validatepassword" id="validatepassword">
</div>
<div>
<button type="submit">Register</button>
<footer>Already a member? <a href="../login/login.php">Login Here</a></footer>
</div>
</form>
</main>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Register</title>
</head>
<body>
<main>
<?php
if(!empty($errors['username'])) {
foreach ($errors as $error) {
echo '<span>{$error}</span>';
}
}

if(!empty($errors['password'])) {
foreach ($errors as $error) {
echo '<span>{$error}</span>';
}

if(!empty($errors['validatepassword'])) {
foreach ($errors as $error) {
echo '<span>{$error}</span>';
}
}
}
?>
<form action="" method="post">
<h1>Sign Up</h1>
<div>

<label for="username">Username:</label>
<input type="text" name="username" id="username">
</div>
<div>

<label for="password">Password:</label>
<input type="password" name="password" id="password">
</div>
<div>

<label for="validatepassword">Validate Password:</label>
<input type="password" name="validatepassword" id="validatepassword">
</div>
<div>
<button type="submit">Register</button>
<footer>Already a member? <a href="../login/login.php">Login Here</a></footer>
</div>
</form>
</main>
</body>
</html>
`
ἔρως
ἔρως4mo ago
so close almost there
ZomaTheMasterOfDisaster
i could have it do it inside the form and display each error above the respective field
ἔρως
ἔρως4mo ago
it's prefered to display under, so it doesn't interfeer with the label
ZomaTheMasterOfDisaster
under the textfield?
ἔρως
ἔρως4mo ago
yup
ZomaTheMasterOfDisaster
what's my goof
ἔρως
ἔρως4mo ago
you check for $errors['validatepassword'], then loop for $errors that's the goof
ZomaTheMasterOfDisaster
i made it $error
ἔρως
ἔρως4mo ago
that doesn't fix the goof
ZomaTheMasterOfDisaster
<?php
if(!empty($errors['username'])) {
foreach ($errors as $error) {
echo '<span>{$error}</span>';
}
}

if(!empty($errors['password'])) {
foreach ($errors as $error) {
echo '<span>{$error}</span>';
}
}

if(!empty($errors['validatepassword'])) {
foreach ($errors as $error) {
echo '<span>{$error}</span>';
}
}
?>
<?php
if(!empty($errors['username'])) {
foreach ($errors as $error) {
echo '<span>{$error}</span>';
}
}

if(!empty($errors['password'])) {
foreach ($errors as $error) {
echo '<span>{$error}</span>';
}
}

if(!empty($errors['validatepassword'])) {
foreach ($errors as $error) {
echo '<span>{$error}</span>';
}
}
?>
ἔρως
ἔρως4mo ago
also, spans are inline you will see error 1error 2error 3
ZomaTheMasterOfDisaster
can't have all three named $error
ἔρως
ἔρως4mo ago
and the goof is still there yes you can
ZomaTheMasterOfDisaster
so the issue is with validatepassword
ἔρως
ἔρως4mo ago
no, all of them that one was an example
ZomaTheMasterOfDisaster
oh
<?php
if(!empty($errors['username'])) {
foreach ($errors['username'] as $error) {
echo '<p>{$error}</p>';
}
}

if(!empty($errors['password'])) {
foreach ($errors['password'] as $error) {
echo '<p>{$error}</p>';
}
}

if(!empty($errors['validatepassword'])) {
foreach ($errors['validatepassword'] as $error) {
echo '<p>{$error}</p>';
}
}
?>
<?php
if(!empty($errors['username'])) {
foreach ($errors['username'] as $error) {
echo '<p>{$error}</p>';
}
}

if(!empty($errors['password'])) {
foreach ($errors['password'] as $error) {
echo '<p>{$error}</p>';
}
}

if(!empty($errors['validatepassword'])) {
foreach ($errors['validatepassword'] as $error) {
echo '<p>{$error}</p>';
}
}
?>
ἔρως
ἔρως4mo ago
very good but that will output it at the top
ZomaTheMasterOfDisaster
ill just add php tags under each field and then check?
ἔρως
ἔρως4mo ago
yup
ZomaTheMasterOfDisaster
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Register</title>
</head>
<body>
<main>
<form action="" method="post">
<h1>Sign Up</h1>
<div>
<label for="username">Username:</label>
<input type="text" name="username" id="username">
<?php
if(!empty($errors['username'])) {
foreach ($errors['username'] as $error) {
echo '<p>{$error}</p>';
}
}
?>
</div>
<div>

<label for="password">Password:</label>
<input type="password" name="password" id="password">
<?php
if(!empty($errors['password'])) {
foreach ($errors['password'] as $error) {
echo '<p>{$error}</p>';
}
}
?>
</div>
<div>

<label for="validatepassword">Validate Password:</label>
<input type="password" name="validatepassword" id="validatepassword">
<?php
if(!empty($errors['validatepassword'])) {
foreach ($errors['validatepassword'] as $error) {
echo '<p>{$error}</p>';
}
}
?>
</div>
<div>
<button type="submit">Register</button>
<footer>Already a member? <a href="../login/login.php">Login Here</a></footer>
</div>
</form>
</main>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Register</title>
</head>
<body>
<main>
<form action="" method="post">
<h1>Sign Up</h1>
<div>
<label for="username">Username:</label>
<input type="text" name="username" id="username">
<?php
if(!empty($errors['username'])) {
foreach ($errors['username'] as $error) {
echo '<p>{$error}</p>';
}
}
?>
</div>
<div>

<label for="password">Password:</label>
<input type="password" name="password" id="password">
<?php
if(!empty($errors['password'])) {
foreach ($errors['password'] as $error) {
echo '<p>{$error}</p>';
}
}
?>
</div>
<div>

<label for="validatepassword">Validate Password:</label>
<input type="password" name="validatepassword" id="validatepassword">
<?php
if(!empty($errors['validatepassword'])) {
foreach ($errors['validatepassword'] as $error) {
echo '<p>{$error}</p>';
}
}
?>
</div>
<div>
<button type="submit">Register</button>
<footer>Already a member? <a href="../login/login.php">Login Here</a></footer>
</div>
</form>
</main>
</body>
</html>
ἔρως
ἔρως4mo ago
very good that should be enough to show error messages
ZomaTheMasterOfDisaster
yep I guess next would be sanitizing input then allowing what's good through to database
ἔρως
ἔρως4mo ago
however, that's absolutely horribly unsafe
ἔρως
ἔρως4mo ago
so, ALL error messages have to be made into proper html strings
ZomaTheMasterOfDisaster
well after the unsafe is fixed ill have to call it a night
ἔρως
ἔρως4mo ago
echo '<p>{$error}</p>'; <-- also, this doesn't work single-quotes are NOT the same as double-quotes but, in this case, you should keep the single-quotes, and remove the string interpolation one important thing: echo accepts multiple arguments, like a function
ZomaTheMasterOfDisaster
print better to use?
ἔρως
ἔρως4mo ago
no that's a different tool perfectly valid but way overkill
ZomaTheMasterOfDisaster
ok sometimes it feels like Go is a bit easier than php
ἔρως
ἔρως4mo ago
it's newer
ZomaTheMasterOfDisaster
echo "<p>" . $error . "</p>";
echo "<p>" . $error . "</p>";
ἔρως
ἔρως4mo ago
or echo '<p>', $error, '</p>'; this version makes some things a lot easier to handle
ZomaTheMasterOfDisaster
why's that
ἔρως
ἔρως4mo ago
the arguments are clearly separated
ZomaTheMasterOfDisaster
ive mainly seen . concat in the docs
ἔρως
ἔρως4mo ago
this isn't string concatenation
ZomaTheMasterOfDisaster
yeah i know
ἔρως
ἔρως4mo ago
it's just multiple arguments to the echo construct
ZomaTheMasterOfDisaster
i never seen commas in echo before it's kinda new for me
ἔρως
ἔρως4mo ago
which actually is a tiny tiny tiny tiny tiny tiny micro-optimization since it doesn't have to concatenate before outputting, it's a bit faster
ZomaTheMasterOfDisaster
anything else I need to do before we end?
ἔρως
ἔρως4mo ago
yes you need to sanitize the output messages
ZomaTheMasterOfDisaster
im not handling anything else outside of error checking at this point it's too late htmlentities or htmlspecialchars?
ἔρως
ἔρως4mo ago
i would use both pick one, stick to it but i would pick htmlentities to avoid issues with quotes
ZomaTheMasterOfDisaster
ok so wrap my $error in it
ἔρως
ἔρως4mo ago
yes the default settings should be fine
ZomaTheMasterOfDisaster
utf-8?
ἔρως
ἔρως4mo ago
^ don't touch anything else just the first argument
ZomaTheMasterOfDisaster
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Register</title>
</head>
<body>
<main>
<form action="" method="post">
<h1>Sign Up</h1>
<div>
<label for="username">Username:</label>
<input type="text" name="username" id="username">
<?php
if(!empty($errors['username'])) {
foreach ($errors['username'] as $error) {
echo '<p>', htmlentities($error), '</p>';
}
}
?>
</div>
<div>

<label for="password">Password:</label>
<input type="password" name="password" id="password">
<?php
if(!empty($errors['password'])) {
foreach ($errors['password'] as $error) {
echo '<p>', htmlentities($error), '</p>';
}
}
?>
</div>
<div>

<label for="validatepassword">Validate Password:</label>
<input type="password" name="validatepassword" id="validatepassword">
<?php
if(!empty($errors['validatepassword'])) {
foreach ($errors['validatepassword'] as $error) {
echo '<p>', htmlentities($error), '</p>';
}
}
?>
</div>
<div>
<button type="submit">Register</button>
<footer>Already a member? <a href="../login/login.php">Login Here</a></footer>
</div>
</form>
</main>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Register</title>
</head>
<body>
<main>
<form action="" method="post">
<h1>Sign Up</h1>
<div>
<label for="username">Username:</label>
<input type="text" name="username" id="username">
<?php
if(!empty($errors['username'])) {
foreach ($errors['username'] as $error) {
echo '<p>', htmlentities($error), '</p>';
}
}
?>
</div>
<div>

<label for="password">Password:</label>
<input type="password" name="password" id="password">
<?php
if(!empty($errors['password'])) {
foreach ($errors['password'] as $error) {
echo '<p>', htmlentities($error), '</p>';
}
}
?>
</div>
<div>

<label for="validatepassword">Validate Password:</label>
<input type="password" name="validatepassword" id="validatepassword">
<?php
if(!empty($errors['validatepassword'])) {
foreach ($errors['validatepassword'] as $error) {
echo '<p>', htmlentities($error), '</p>';
}
}
?>
</div>
<div>
<button type="submit">Register</button>
<footer>Already a member? <a href="../login/login.php">Login Here</a></footer>
</div>
</form>
</main>
</body>
</html>
ἔρως
ἔρως4mo ago
yup that should work if it doesn't, it will wait for tomorrow but you understand what's being done?
ZomaTheMasterOfDisaster
with that htmlentities escape any xss code
ἔρως
ἔρως4mo ago
everything yes and no, but yes
ZomaTheMasterOfDisaster
sort of some of it is interesting but i have to see how to do the database stuff next
ἔρως
ἔρως4mo ago
spoiler alert: no sanitization will be done
ZomaTheMasterOfDisaster
we basically made an array that is filtered with proper error messages then displayed them is the breakdown basic
ἔρως
ἔρως4mo ago
yup, that's right and each field is mapped by it's name
ZomaTheMasterOfDisaster
I think I can get this down just wll take some time for it click if I can get that programming logic and design mindset back this will get a lot easier combined with my data structures and algorithms knowledge (if I didnt lose it too)
ἔρως
ἔρως4mo ago
and that means practice
ZomaTheMasterOfDisaster
sadly one job im after they dont mention what tech they're using so it's probably asp.net with C# which means im screwed 😄
ἔρως
ἔρως4mo ago
c# isnt that hard
ZomaTheMasterOfDisaster
as youve seen php is already hard for me going back to C# would be another long road
ἔρως
ἔρως4mo ago
60% of the syntax is the same
ZomaTheMasterOfDisaster
pushed code to github
ἔρως
ἔρως4mo ago
nice
ZomaTheMasterOfDisaster
The logic makes sense I just need to get back into a mindset where I break things down better and use a data structure or proper algorithm
ἔρως
ἔρως4mo ago
that's why i wanted you to make the list
ZomaTheMasterOfDisaster
Yeah might do that again tomorrow too
ἔρως
ἔρως4mo ago
you should rest too
putuardiworks
putuardiworks4mo ago
@MD how the progress now?
putuardiworks
putuardiworks4mo ago
Already solved then?
ZomaTheMasterOfDisaster
I'm currently on writing to the database
putuardiworks
putuardiworks4mo ago
Okay, i'm here just to answer this topic question: Sanitize user input to avoid XSS attacks - Sanitize is more like check the input for required, length, format, etc. - You don't need convert/encode/escape the input using htmlspecialchars() or htmlentities() when saving the input to database. - When saving to database, use prepared statements and parameterized queries. - When displaying the data from database to HTML, then you need to convert/encode/escape the data using htmlspecialchars().
ἔρως
ἔρως4mo ago
sanitizing is the removal of characters or sequences that aren't allowed for a specific format however, it is not validation, as sanitizing a string like a<b>@gmail.com</b> will/should result in a, which obviously isn't a valid email address
putuardiworks
putuardiworks4mo ago
yes, i mistake it for validate
ἔρως
ἔρως4mo ago
it's alright everything else you said is absolutely correct
ZomaTheMasterOfDisaster
this is what im onto next 1. Validate the error checking works     2. If good, then work on writing to database     3. After writing to database, start a session, redirect user to their todo page     4. Check for user logging out whether it be through closing browser or logging out     5. ban access to pages without proper login Process for writing to database     6. Check if database is loaded correctly,         - else add an error variable then display as a html element to the screen     1. if database loads successfully, then             - setup a prepare statement with username, and password             - bind the username, and password as parameters to the update query for user table             - execute the update query to the database which I do know you really shouldn't display a database fail to a user
ἔρως
ἔρως4mo ago
you can't check if a user closed the browser reliably also, users close their browsers and expect some sessions to still work but other than the order being weird, i think you got the right ideas
ZomaTheMasterOfDisaster
JS could check for a browser closer since it's local
ἔρως
ἔρως4mo ago
yes, but the server shouldn't care about it
ZomaTheMasterOfDisaster
but you're right most users want they cookie to continue letting them in for a bit so they dont have to sign
ἔρως
ἔρως4mo ago
seriously, just don't even bother with the closing the server deletes the sessions when they are unused
ἔρως
ἔρως4mo ago
so, don't worry about it
ZomaTheMasterOfDisaster
I added a try catch for database issue
ἔρως
ἔρως4mo ago
good, now you can check if hte database failed
ZomaTheMasterOfDisaster
for now just displays a message of failure to load database just to have something there for the meantime
ἔρως
ἔρως4mo ago
that's all you can do, if the database dies
ZomaTheMasterOfDisaster
right!
ἔρως
ἔρως4mo ago
but you have a plan, so, follow it now way better than no plan, right?
ZomaTheMasterOfDisaster
true right now i got this
<?php
include '../../../vendor/autoload.php';
use MD\dbhelper\SQLConnection;
use MD\helpers\Validate;

$required = true;
$errors = [];
if(isset($_POST['submit'])) {
// build an error array just in case
$errors = array_filter(['username' => Validate::username($_POST['username'], $required),
'password' => Validate::password($_POST['password'], $required),
'validatepassword' => Validate::valdiatePassword($_POST['validatepassword'], $_POST['password'], $required)]);

$addNewUser = (new SQLConnection())->connect();

// check if the database loads
if($addNewUser) {
$username =
} else {
echo "Error with database";
}

}


?>
<?php
include '../../../vendor/autoload.php';
use MD\dbhelper\SQLConnection;
use MD\helpers\Validate;

$required = true;
$errors = [];
if(isset($_POST['submit'])) {
// build an error array just in case
$errors = array_filter(['username' => Validate::username($_POST['username'], $required),
'password' => Validate::password($_POST['password'], $required),
'validatepassword' => Validate::valdiatePassword($_POST['validatepassword'], $_POST['password'], $required)]);

$addNewUser = (new SQLConnection())->connect();

// check if the database loads
if($addNewUser) {
$username =
} else {
echo "Error with database";
}

}


?>
so im thinking if database loads then add the post variables to the username and password local variables then do a prepare statement, bind, then execute
ἔρως
ἔρως4mo ago
how about you have a class that makes it easier for you to do queries and stuff? and you can check if the database loaded in it, and throw the errors you need from that class
ZomaTheMasterOfDisaster
i can add it to my dbhelper
ἔρως
ἔρως4mo ago
oh, right, you have SQLConnection <-- that
ZomaTheMasterOfDisaster
yeah right now it just connects
ἔρως
ἔρως4mo ago
you can add that functionality in the class
ZomaTheMasterOfDisaster
got this so far
<?php

namespace MD\dbhelper;
use MD\dbhelper\config;


class SQLConnection {
/**
* PDO instance
* @var type
*/

private $pdo;

/**
* return pdo connection to sqlite
* @return \PDO
*/
public function connect() {
try{
$this->pdo = new \PDO("sqlite:" . Config::PATH_TO_SQLITE_FILE);
} catch(\PDOException $e) {
//error was caught trying to create database connection.
echo "Error with loading database: " . $e;
}

return $this->pdo;
}

/**
* add user to the database query
* @return boolean
*/
public function addUserQuery($username, $password) {
$successfullyAddedUser = false;

$encryptedPass = password_hash($password, PASSWORD_BCRYPT);

$query = 'INSERT INTO users(username,password) VALUES(:username, :password)';
$stmt = $pdo->prepare($query);

$stmt->execute([
':username' => $username,
':password' => $encryptedPass
]);
}
}
<?php

namespace MD\dbhelper;
use MD\dbhelper\config;


class SQLConnection {
/**
* PDO instance
* @var type
*/

private $pdo;

/**
* return pdo connection to sqlite
* @return \PDO
*/
public function connect() {
try{
$this->pdo = new \PDO("sqlite:" . Config::PATH_TO_SQLITE_FILE);
} catch(\PDOException $e) {
//error was caught trying to create database connection.
echo "Error with loading database: " . $e;
}

return $this->pdo;
}

/**
* add user to the database query
* @return boolean
*/
public function addUserQuery($username, $password) {
$successfullyAddedUser = false;

$encryptedPass = password_hash($password, PASSWORD_BCRYPT);

$query = 'INSERT INTO users(username,password) VALUES(:username, :password)';
$stmt = $pdo->prepare($query);

$stmt->execute([
':username' => $username,
':password' => $encryptedPass
]);
}
}
kinda goofed on that $pdo variable
ἔρως
ἔρως4mo ago
//error was caught trying to create database connection. <-- please, avoid comments like these those do nothing but bloat your code $encryptedPass = password_hash($password, PASSWORD_BCRYPT); <-- DO NOT USE BCRYPT!!! use the default one by the way, test the cost argument, and check which value is best for your server aim for 350ms of delay for an answer, to make it unfeasably slow for brute force attacks to be effective within a lifetime
ZomaTheMasterOfDisaster
public function addUserQuery($username, $password) {
$options = [
'cost' => 10
];

$successfullyAddedUser = false;

$encryptedPass = password_hash($password, PASSWORD_DEFAULT, $options);

$query = 'INSERT INTO users(username,password) VALUES(:username, :password)';
$stmt = $pdo->prepare($query);

$stmt->execute([
':username' => $username,
':password' => $encryptedPass
]);
}
public function addUserQuery($username, $password) {
$options = [
'cost' => 10
];

$successfullyAddedUser = false;

$encryptedPass = password_hash($password, PASSWORD_DEFAULT, $options);

$query = 'INSERT INTO users(username,password) VALUES(:username, :password)';
$stmt = $pdo->prepare($query);

$stmt->execute([
':username' => $username,
':password' => $encryptedPass
]);
}
ten for now since it's local hosted ill test more after I get more of a working setup
ἔρως
ἔρως4mo ago
just go for 11 localhosts usually do well with 11
ZomaTheMasterOfDisaster
it doesn't like this $stmt = $pdo->prepare($query); $pdo being the issue
ἔρως
ἔρως4mo ago
$pdo doesn't exist
ZomaTheMasterOfDisaster
i have it as a private global variable
ἔρως
ἔρως4mo ago
yes, but you're using $pdo how do you access a private variable in php?
ZomaTheMasterOfDisaster
oh this isnt java it is a private global class variable
ἔρως
ἔρως4mo ago
it can't be private and global
ἔρως
ἔρως4mo ago
yup that's it
ZomaTheMasterOfDisaster
yes it is java 😄
/**
* add user to the database query
* @return boolean
*/
public function addUserQuery($username, $password) {
$options = [
'cost' => 11
];

$successfullyAddedUser = false;

$encryptedPass = password_hash($password, PASSWORD_DEFAULT, $options);

$query = 'INSERT INTO users(username,password) VALUES(:username, :password)';
$stmt = $this->pdo->prepare($query);

$stmt->execute([
':username' => $username,
':password' => $encryptedPass
]);
}
/**
* add user to the database query
* @return boolean
*/
public function addUserQuery($username, $password) {
$options = [
'cost' => 11
];

$successfullyAddedUser = false;

$encryptedPass = password_hash($password, PASSWORD_DEFAULT, $options);

$query = 'INSERT INTO users(username,password) VALUES(:username, :password)';
$stmt = $this->pdo->prepare($query);

$stmt->execute([
':username' => $username,
':password' => $encryptedPass
]);
}
ἔρως
ἔρως4mo ago
that's good however, you have a problem
ZomaTheMasterOfDisaster
$query looks odd
ἔρως
ἔρως4mo ago
it looks odd as hell, but it is fine the $options should be in a class constant yes, i said "constant" by the way, use an heredoc with the name SQL, and vscode enables syntax highlighting into it
ZomaTheMasterOfDisaster
this is getting better
class SQLConnection {
/**
* PDO instance
* @var type
*/

private $pdo;

const OPTION_COST = 11;

/**
* return pdo connection to sqlite
* @return \PDO
*/
public function connect() {
try{
$this->pdo = new \PDO("sqlite:" . Config::PATH_TO_SQLITE_FILE);
} catch(\PDOException $e) {

echo "Error with loading database: " . $e;
}

return $this->pdo;
}

/**
* add user to the database query
* @return boolean
*/
public function addUserQuery($username, $password) {



$options = [
'cost' => SQLConnection::OPTION_COST
];

$successfullyAddedUser = false;

$encryptedPass = password_hash($password, PASSWORD_DEFAULT, $options);

$query = 'INSERT INTO users(username,password) VALUES(:username, :password)';
$stmt = $this->pdo->prepare($query);

$stmt->execute([
':username' => $username,
':password' => $encryptedPass
]);
}
}
class SQLConnection {
/**
* PDO instance
* @var type
*/

private $pdo;

const OPTION_COST = 11;

/**
* return pdo connection to sqlite
* @return \PDO
*/
public function connect() {
try{
$this->pdo = new \PDO("sqlite:" . Config::PATH_TO_SQLITE_FILE);
} catch(\PDOException $e) {

echo "Error with loading database: " . $e;
}

return $this->pdo;
}

/**
* add user to the database query
* @return boolean
*/
public function addUserQuery($username, $password) {



$options = [
'cost' => SQLConnection::OPTION_COST
];

$successfullyAddedUser = false;

$encryptedPass = password_hash($password, PASSWORD_DEFAULT, $options);

$query = 'INSERT INTO users(username,password) VALUES(:username, :password)';
$stmt = $this->pdo->prepare($query);

$stmt->execute([
':username' => $username,
':password' => $encryptedPass
]);
}
}
ἔρως
ἔρως4mo ago
no no, the whole array has to be a constant, so you can re-use it you can make it private as well by the way, the function is missing a return type and a type on the arguments
ZomaTheMasterOfDisaster
im getting there
private const OPTIONS = [
'cost' => SQLConnection::OPTION_COST
];
private const OPTIONS = [
'cost' => SQLConnection::OPTION_COST
];
im not seeing key value const examples
ἔρως
ἔρως4mo ago
remove that cost constant put the value into the array
ZomaTheMasterOfDisaster
private const OPTIONS = [SQLConnection::OPTION_COST];
ἔρως
ἔρως4mo ago
no SQLConnection::OPTION_COST <-- you don't need this, just put the value directly oh, btw, you can just use self instead of typing the class name
ZomaTheMasterOfDisaster
const OPTION_COST = 11;

private const OPTIONS = [OPTION_COST];
const OPTION_COST = 11;

private const OPTIONS = [OPTION_COST];
ἔρως
ἔρως4mo ago
no that's not what i said read this message carefully
ZomaTheMasterOfDisaster
ok i put 11
ἔρως
ἔρως4mo ago
show me
ZomaTheMasterOfDisaster
const OPTIONS = [11];
ἔρως
ἔρως4mo ago
you're missing the key the key is mandatory
ZomaTheMasterOfDisaster
got it everything is fixed now still getting used to the newer php syntax but in time
ἔρως
ἔρως4mo ago
that's old syntax, supported in php 5.6
ZomaTheMasterOfDisaster
/**
* add user to the database query
* @return boolean
*/
public function addUserQuery($username, $password) {

$successfullyAddedUser = false;

$encryptedPass = password_hash($password, PASSWORD_DEFAULT, self::ENCRYPTED_COST);

$query = 'INSERT INTO users(username,password) VALUES(:username, :password)';
$stmt = $this->pdo->prepare($query);

$stmt->execute([
':username' => $username,
':password' => $encryptedPass
]);
}
/**
* add user to the database query
* @return boolean
*/
public function addUserQuery($username, $password) {

$successfullyAddedUser = false;

$encryptedPass = password_hash($password, PASSWORD_DEFAULT, self::ENCRYPTED_COST);

$query = 'INSERT INTO users(username,password) VALUES(:username, :password)';
$stmt = $this->pdo->prepare($query);

$stmt->execute([
':username' => $username,
':password' => $encryptedPass
]);
}
ἔρως
ἔρως4mo ago
yes, but options is a very non-specific name i know this will sound nitpicky, because it is but you need to create good habits naming things correctly is very important
ZomaTheMasterOfDisaster
ive had good habits before in time lets focus on task at hand so is qery and stmt ok?
ἔρως
ἔρως4mo ago
yeah, it is okay, but you lack backticks around the identifiers this prevents surprises and syntax errors
ZomaTheMasterOfDisaster
huh i just go by the php page examples
ἔρως
ἔρως4mo ago
// less good:
$query = 'INSERT INTO users(username,password) VALUES(:username, :password)';

// perfect
$query = 'INSERT INTO `users` (`username`, `password`) VALUES(:username, :password)';

// ultimate perfect
$query = <<<'SQL'
INSERT INTO `users` (`username`, `password`)
VALUES (:username, :password)
SQL;
// less good:
$query = 'INSERT INTO users(username,password) VALUES(:username, :password)';

// perfect
$query = 'INSERT INTO `users` (`username`, `password`) VALUES(:username, :password)';

// ultimate perfect
$query = <<<'SQL'
INSERT INTO `users` (`username`, `password`)
VALUES (:username, :password)
SQL;
indentation is also very very important specially if it is tabs: tabs are a must
ZomaTheMasterOfDisaster
true ok so "exec" returns an int for the number of affected rows or 0 if none affected
ἔρως
ἔρως4mo ago
or false in case of an error if you inserted and there were 0 affected rows, or the result is false or there's no inserted id, then it failed
ZomaTheMasterOfDisaster
ill check for the error
ἔρως
ἔρως4mo ago
it shouldn't be too hard
ZomaTheMasterOfDisaster
looks pretty clean
/**
* add user to the database query
* @return boolean
*/
public function addUserQuery($username, $password) {

$successfullyAddedUser = false;

$encryptedPass = password_hash($password, PASSWORD_DEFAULT, self::ENCRYPTION_COST);

$query = 'INSERT INTO `users` (`username`, `password`) VALUES(:username, :password)';
$stmt = $this->pdo->prepare($query);

$stmt->execute([
':username' => $username,
':password' => $encryptedPass
]);

if ($stmt == false) {
return $successfullyAddedUser;
}

return $successfullyAddedUser = true;
}
/**
* add user to the database query
* @return boolean
*/
public function addUserQuery($username, $password) {

$successfullyAddedUser = false;

$encryptedPass = password_hash($password, PASSWORD_DEFAULT, self::ENCRYPTION_COST);

$query = 'INSERT INTO `users` (`username`, `password`) VALUES(:username, :password)';
$stmt = $this->pdo->prepare($query);

$stmt->execute([
':username' => $username,
':password' => $encryptedPass
]);

if ($stmt == false) {
return $successfullyAddedUser;
}

return $successfullyAddedUser = true;
}
ἔρως
ἔρως4mo ago
not yet $successfullyAddedUser = false; <-- this variable is useless
if ($stmt == false) {
return $successfullyAddedUser;
}

return $successfullyAddedUser = true;
if ($stmt == false) {
return $successfullyAddedUser;
}

return $successfullyAddedUser = true;
this doesn't do what you think it does also, you aren't checking this in the proper place anyways if ($stmt == false) <-- if this is true $stmt->execute([ ... ]) <-- this will throw an error because you can't access a falsy value as an object
ZomaTheMasterOfDisaster
hmm ok
ἔρως
ἔρως4mo ago
if ($stmt == false) <-- this is just the same as if (!$stmt) but may be confused with if ($stmt === false) unless you want to check if the value is specifically false, it's best to avoid if ($stmt == false)
ZomaTheMasterOfDisaster
the variable is set to false though but i see
ἔρως
ἔρως4mo ago
if it is set to false, something wrong happened
ZomaTheMasterOfDisaster
public function addUserQuery($username, $password) {

$successfullyAddedUser = false;

$encryptedPass = password_hash($password, PASSWORD_DEFAULT, self::ENCRYPTION_COST);

$query = 'INSERT INTO `users` (`username`, `password`) VALUES(:username, :password)';
$stmt = $this->pdo->prepare($query);

$stmt->execute([
':username' => $username,
':password' => $encryptedPass
]);

if(!$stmt) {
return $successfullyAddedUser;
}

return $successfullyAddedUser = true;
}
public function addUserQuery($username, $password) {

$successfullyAddedUser = false;

$encryptedPass = password_hash($password, PASSWORD_DEFAULT, self::ENCRYPTION_COST);

$query = 'INSERT INTO `users` (`username`, `password`) VALUES(:username, :password)';
$stmt = $this->pdo->prepare($query);

$stmt->execute([
':username' => $username,
':password' => $encryptedPass
]);

if(!$stmt) {
return $successfullyAddedUser;
}

return $successfullyAddedUser = true;
}
ἔρως
ἔρως4mo ago
$successfullyAddedUser <-- remove this, it's absolutely useless it only makes the code more bloated returning the value directly is a lot better than bloating with long variables
ZomaTheMasterOfDisaster
ok so it returns an int or false ill just return the $stmt or could just make it void
ἔρως
ἔρως4mo ago
<?php

class Database {
private PDO $pdo;

private const HASH_ALGO = PASSWORD_DEFAULT;
private const HASH_OPTIONS = [
'cost' => 11,
];

public function __construct() {
$this->pdo = new PDO('...');
}

/**
* Adds a user to the database
*
* @param string $username The username to add
* @param string $password Unhashed password
*
* @return bool|int User ID on success, `false` on error
*/
public function addUserQuery(string $username, string $password): bool|int {
static $query = 'INSERT INTO `users` (`username`, `password`) VALUES(:username, :password)';

/** @var PDOStatement|bool $stmt */
$stmt = $this->pdo->prepare($query);

if(!$stmt) {
return false;
}

/** @var string $hash */
$hash = password_hash($password, self::HASH_ALGO, self::HASH_OPTIONS);

/** @var bool|int $result */
$result = $stmt->execute([
':username' => $username,
':password' => $hash
]);

if(!$result) {
return false;
}

return $this->pdo->lastInsertId();
}
}
<?php

class Database {
private PDO $pdo;

private const HASH_ALGO = PASSWORD_DEFAULT;
private const HASH_OPTIONS = [
'cost' => 11,
];

public function __construct() {
$this->pdo = new PDO('...');
}

/**
* Adds a user to the database
*
* @param string $username The username to add
* @param string $password Unhashed password
*
* @return bool|int User ID on success, `false` on error
*/
public function addUserQuery(string $username, string $password): bool|int {
static $query = 'INSERT INTO `users` (`username`, `password`) VALUES(:username, :password)';

/** @var PDOStatement|bool $stmt */
$stmt = $this->pdo->prepare($query);

if(!$stmt) {
return false;
}

/** @var string $hash */
$hash = password_hash($password, self::HASH_ALGO, self::HASH_OPTIONS);

/** @var bool|int $result */
$result = $stmt->execute([
':username' => $username,
':password' => $hash
]);

if(!$result) {
return false;
}

return $this->pdo->lastInsertId();
}
}
this is how i would write it
ZomaTheMasterOfDisaster
<?php

class Database {
private PDO $pdo;

private const HASH_ALGO = PASSWORD_DEFAULT;
private const HASH_OPTIONS = [
'cost' => 11,
];

public function __construct() {
$this->pdo = new PDO('...');
}

/**
* Adds a user to the database
*
* @param string $username The username to add
* @param string $password Unhashed password
*
* @return bool|int User ID on success, `false` on error
*/
public function addUserQuery(string $username, string $password): bool|int {
static $query = 'INSERT INTO `users` (`username`, `password`) VALUES(:username, :password)';

/** @var PDOStatement|bool $stmt */
$stmt = $this->pdo->prepare($query);

if(!$stmt) {
return false;
}

/** @var string $hash */
$hash = password_hash($password, self::HASH_ALGO, self::HASH_OPTIONS);

/** @var bool|int $result */
$result = $stmt->execute([
':username' => $username,
':password' => $hash
]);

if(!$result) {
return false;
}

return $this->pdo->lastInsertId();
}
}
<?php

class Database {
private PDO $pdo;

private const HASH_ALGO = PASSWORD_DEFAULT;
private const HASH_OPTIONS = [
'cost' => 11,
];

public function __construct() {
$this->pdo = new PDO('...');
}

/**
* Adds a user to the database
*
* @param string $username The username to add
* @param string $password Unhashed password
*
* @return bool|int User ID on success, `false` on error
*/
public function addUserQuery(string $username, string $password): bool|int {
static $query = 'INSERT INTO `users` (`username`, `password`) VALUES(:username, :password)';

/** @var PDOStatement|bool $stmt */
$stmt = $this->pdo->prepare($query);

if(!$stmt) {
return false;
}

/** @var string $hash */
$hash = password_hash($password, self::HASH_ALGO, self::HASH_OPTIONS);

/** @var bool|int $result */
$result = $stmt->execute([
':username' => $username,
':password' => $hash
]);

if(!$result) {
return false;
}

return $this->pdo->lastInsertId();
}
}
fixed it for the highlighting
ἔρως
ἔρως4mo ago
i probably broke the language name but you wanna know something? this function doesn't belong in this class but that's an issue for another time
ZomaTheMasterOfDisaster
which one? addNewUSER
ἔρως
ἔρως4mo ago
yes you should follow the single responsibility principle
ZomaTheMasterOfDisaster
well where should it go
ἔρως
ἔρως4mo ago
on a class to manage users
ZomaTheMasterOfDisaster
I just have a user class in models currently
ἔρως
ἔρως4mo ago
for now, what you have is fine
ZomaTheMasterOfDisaster
yeah id have to remove pdo code because you shouldnt have pdo stuff in models unless you can im still kinda learning the "setup" for php code following their mvc approach
ἔρως
ἔρως4mo ago
yeah, i know what you mean
ZomaTheMasterOfDisaster
code is updated and pushed to github
ἔρως
ἔρως4mo ago
but first, lets make it work
ZomaTheMasterOfDisaster
ok so in register.php i removed the addNewUser stuff just got errors
ἔρως
ἔρως4mo ago
you shouldn't have moved yet you don't have any interfaces to access the database basically, the database class is a closed system
ZomaTheMasterOfDisaster
ok guess that's next making that interface will be last thing i do for night
ἔρως
ἔρως4mo ago
then you will have to make a plan on what the class does
ZomaTheMasterOfDisaster
well I got two models already one for user and one for task
ἔρως
ἔρως4mo ago
that doesn't say what the database class needs to do
ZomaTheMasterOfDisaster
database should only add users, remove users, add tasks, remove tasks, update users, update tasks basically CRUD
ἔρως
ἔρως4mo ago
that's not right the database should only care about database adding users, removing users, adding tasks, removing tanks, updating users, updating tanks ... that's all stuff for the controller
ZomaTheMasterOfDisaster
oh right i forgot about the controller 😄 yeah i need to do a little MVC studying tomorrow then get back to this
ἔρως
ἔρως4mo ago
i think that that's a good idea
ZomaTheMasterOfDisaster
Database should really just connect
ἔρως
ἔρως4mo ago
connect and do query stuff
ZomaTheMasterOfDisaster
so i need a database interface?
ἔρως
ἔρως4mo ago
that class is the "interface"
ZomaTheMasterOfDisaster
wait dont we need a __destruct for database
ἔρως
ἔρως4mo ago
no, it disconnects at the end of the script
ZomaTheMasterOfDisaster
so i guess next then is controllers?
ἔρως
ἔρως4mo ago
that's going to be a big re-write, but yes
ZomaTheMasterOfDisaster
yeah too late for that tonight what am i missing to finish tonight
ἔρως
ἔρως4mo ago
sleep
ZomaTheMasterOfDisaster
oh ok good idea 🙂
ἔρως
ἔρως4mo ago
i like that idea for myself too
ZomaTheMasterOfDisaster
rest well 🙂
ἔρως
ἔρως4mo ago
thank you, i will
ZomaTheMasterOfDisaster
I think i only need one controller because the user is interacting with it i dont think user needs a controller but I could be wrong
ἔρως
ἔρως4mo ago
lots of code will have to interact with the user
ZomaTheMasterOfDisaster
I need to restructure my models
ἔρως
ἔρως4mo ago
go for it then
ZomaTheMasterOfDisaster
yeah I read up on MVC last night models should handle database stuff with the model then controller acts as the api to it im not sure what roles a "user" has where as task is easy it's just CRUD
ἔρως
ἔρως4mo ago
a user can login, be created, deleted, edited, logout, be disabled
ZomaTheMasterOfDisaster
so similar?
ἔρως
ἔρως4mo ago
depends you need to communicate with the database in all those
ZomaTheMasterOfDisaster
so im starting with task because it seems easier
ἔρως
ἔρως4mo ago
go for it just do what sounds better to do first
ZomaTheMasterOfDisaster
so for list tasks
public function list_tasks($user) {
$sql = "SELECT * FROM tasks WHERE "
}
public function list_tasks($user) {
$sql = "SELECT * FROM tasks WHERE "
}
it should be userid = $user since it should be the user's userid
ἔρως
ἔρως4mo ago
that depends on what you have
ZomaTheMasterOfDisaster
just Task.php and User.php for models
CREATE TABLE users (userid INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL, password TEXT NOT NULL);
CREATE TABLE tasks (taskid INTEGER PRIMARY KEY AUTOINCREMENT, userid INTEGER NOT NULL, description TEXT, done BOOLEAN, FOREIGN KEY(userid) REFERENCES users(userid));
CREATE TABLE users (userid INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL, password TEXT NOT NULL);
CREATE TABLE tasks (taskid INTEGER PRIMARY KEY AUTOINCREMENT, userid INTEGER NOT NULL, description TEXT, done BOOLEAN, FOREIGN KEY(userid) REFERENCES users(userid));
ἔρως
ἔρως4mo ago
sounds good to me, i don't see any errors
ZomaTheMasterOfDisaster
<?php

namespace MD\dbhelper;
use MD\dbhelper\config;
use PDOException;

class Database {
/**
* PDO instance
* @var type
*/

private \PDO $pdo;

private const HASH_ALGO = PASSWORD_DEFAULT;

private const ENCRYPTION_COST = ['cost' => 11];

public function __construct()
{
try {
$this->pdo = new \PDO("sqlite:" . Config::PATH_TO_SQLITE_FILE);
} catch(PDOException $e) {
echo "Error with loading database: " . $e;
}

}

public function addUserQuery(string $username, string $password): bool|int {
static $query = 'INSERT INTO `user` (`username`, `password`) VALUES(:username, :password)';

$stmt = $this->pdo->prepare($query);

if(!$stmt) {
return false;
}

$hash = password_hash($password, self::HASH_ALGO, self::ENCRYPTION_COST);

$result = $stmt->exec([
':username' => $username,
':password' => $hash
]);

if(!$result) {
return false;
}

return $this->pdo->lastInsertId();
}
}
<?php

namespace MD\dbhelper;
use MD\dbhelper\config;
use PDOException;

class Database {
/**
* PDO instance
* @var type
*/

private \PDO $pdo;

private const HASH_ALGO = PASSWORD_DEFAULT;

private const ENCRYPTION_COST = ['cost' => 11];

public function __construct()
{
try {
$this->pdo = new \PDO("sqlite:" . Config::PATH_TO_SQLITE_FILE);
} catch(PDOException $e) {
echo "Error with loading database: " . $e;
}

}

public function addUserQuery(string $username, string $password): bool|int {
static $query = 'INSERT INTO `user` (`username`, `password`) VALUES(:username, :password)';

$stmt = $this->pdo->prepare($query);

if(!$stmt) {
return false;
}

$hash = password_hash($password, self::HASH_ALGO, self::ENCRYPTION_COST);

$result = $stmt->exec([
':username' => $username,
':password' => $hash
]);

if(!$result) {
return false;
}

return $this->pdo->lastInsertId();
}
}
so im bringing in the pdo to the model
<?php

namespace MD\models;
use MD\dbhelper\Database;

class Task extends Database
{
public $description;
protected $done;

public function isDone() {
return $this->done;
}

public function done() {
$this->done = true;
}

public function list_tasks($user) {
$con = $this->__construct();
$sql = "SELECT * FROM `tasks` WHERE `userid={$user}`";
$sql_exc = $this->
}
}
<?php

namespace MD\models;
use MD\dbhelper\Database;

class Task extends Database
{
public $description;
protected $done;

public function isDone() {
return $this->done;
}

public function done() {
$this->done = true;
}

public function list_tasks($user) {
$con = $this->__construct();
$sql = "SELECT * FROM `tasks` WHERE `userid={$user}`";
$sql_exc = $this->
}
}
ἔρως
ἔρως4mo ago
NO! GOD NO, PLEASE DON'T stop, now that is bad in many levels the database should be passed to the models via dependency injection $this->__construct(); <-- ABSOLUTELY never do this in php
ZomaTheMasterOfDisaster
removed the "extends Database" and removed the "$con = $this->__construct();"
ἔρως
ἔρως4mo ago
good
ZomaTheMasterOfDisaster
let's do this right since my approach is garbage
ἔρως
ἔρως4mo ago
it's not about it being bad it's about it completely shattering how oop works maybe you could try to implement a trait that gives access to the database, but it is a really bad way too
ZomaTheMasterOfDisaster
guess i poorly designed this then 😄
ἔρως
ἔρως4mo ago
mvc is always hard to design
ZomaTheMasterOfDisaster
I used to be better at it gotta retrain myself
ἔρως
ἔρως4mo ago
you can implement it using attributes, but i think you will have to use class reflection
ZomaTheMasterOfDisaster
so the approach you're suggesting is having the database being brought in as a parameter to the functions then called? if im understanding that right
ἔρως
ἔρως4mo ago
as a parameter of the constructor for the models, yes or all models automatically have a $pdo attribute
ZomaTheMasterOfDisaster
hmm either could work
ἔρως
ἔρως4mo ago
i would go with the 2nd option
ZomaTheMasterOfDisaster
right not my models dont have a constructor
ἔρως
ἔρως4mo ago
they don't need
ZomaTheMasterOfDisaster
make it a private pdo?
ἔρως
ἔρως4mo ago
protected you cant make it private
ZomaTheMasterOfDisaster
ok sorry just the discussion in general made me really mad had to step away a moment right now database class just has the construct for pdo
ἔρως
ἔρως4mo ago
create a model class for your models
ZomaTheMasterOfDisaster
like an abstract class?
ἔρως
ἔρως4mo ago
yes
ZomaTheMasterOfDisaster
just like coreModel?
ἔρως
ἔρως4mo ago
just model
ZomaTheMasterOfDisaster
<?php

namespace MD\models;
use MD\dbhelper\Database;

abstract class Model {

}
<?php

namespace MD\models;
use MD\dbhelper\Database;

abstract class Model {

}
ἔρως
ἔρως4mo ago
yup, something like that
ZomaTheMasterOfDisaster
ok so what are the important parts for this
ἔρως
ἔρως4mo ago
the model needs to store a single instance of whatever you want to use and pass to the models
ZomaTheMasterOfDisaster
probably the database?
ἔρως
ἔρως4mo ago
yup, and other things
ZomaTheMasterOfDisaster
ok so in this case we can bring in the database and use the constructor to create the pdo object and have the other models borrow it as extends to base class mode? model
ἔρως
ἔρως4mo ago
that's the idea, yes
ZomaTheMasterOfDisaster
im kinda surprised i had like a mini flashback to oop topics in college
ἔρως
ἔρως4mo ago
that's how it usually is things will click soon
ZomaTheMasterOfDisaster
<?php

namespace MD\models;
use MD\dbhelper\Database;

abstract class Model {
protected $pdo;

public function __construct() {
$pdo = new Database;


}
}
<?php

namespace MD\models;
use MD\dbhelper\Database;

abstract class Model {
protected $pdo;

public function __construct() {
$pdo = new Database;


}
}
so I rememebered that you can't call functions statically without them being static so I called my database class this way instead of trying to do the construct method since it wasn't static then having to change all that code around here's what I came up with since Database class handles the connection, I have this could this setup the model using it ```php <?php namespace MD\models; use MD\dbhelper\Database; use PDOException; abstract class Model { protected $pdo; public function construct() { $pdo = new Database; try { $pdo->__construct(); } catch(PDOException $e) { echo "Database could not connect: " . $e; } return $pdo; } }``` I remembered in Java that abstract classes were the base for the "Object" class and some of its methods that all classes use then classes just inherit and extend the Object class seems to be weird trying to call prepare not able to access the PDO object from the database class
ἔρως
ἔρως4mo ago
why are you calling the constructor twice?
ZomaTheMasterOfDisaster
Wasn't sure why I can't access the pdo object through the database class
ἔρως
ἔρως4mo ago
yeah, but that's not how oop works the constructor is called automatically, and you shouldn't call it manually
ZomaTheMasterOfDisaster
What should I change
ἔρως
ἔρως4mo ago
never ever ever call a constructor manually, inless it is the constructor of the parent class and even then, you only do it inside the constructor
ZomaTheMasterOfDisaster
I couldn't figure out how to reach the PDO object I thought i had to call the constructor to get to it
ἔρως
ἔρως4mo ago
you call the constructor when you use new
ZomaTheMasterOfDisaster
Yeah but when I do $pdo-> none of the PDO functions pop up
ἔρως
ἔρως4mo ago
because your Database class isn't an instance of PDO
ZomaTheMasterOfDisaster
Hmm So how do I get to pdo since it's used in database class
ἔρως
ἔρως4mo ago
is it publicly accessible?
ZomaTheMasterOfDisaster
Private pdo variable
ἔρως
ἔρως4mo ago
do you have a method to return it?
ZomaTheMasterOfDisaster
I even tried returning it in the constructor It failed
ἔρως
ἔρως4mo ago
constructors' return values are ignored
ZomaTheMasterOfDisaster
GitHub
PHPTodoApp/app/class/dbhelper/SQLConnection.php at main · MD-2016/P...
practice project to get back into php. Contribute to MD-2016/PHPTodoApp development by creating an account on GitHub.
ἔρως
ἔρως4mo ago
i mean, your class only has an empty connect method and a non-public select method you should only see the connectmethod
ZomaTheMasterOfDisaster
Yeah I added those to work on tomorrow since I got too tired and a headache
ἔρως
ἔρως4mo ago
you should rest
ZomaTheMasterOfDisaster
So setup basic database stuff in Database class, then have Model constructor call database then use the methods from database through Model on the User and Task models?
ἔρως
ἔρως4mo ago
basically, yes
ZomaTheMasterOfDisaster
Hey I had a smart moment (:
ἔρως
ἔρως4mo ago
you did you just need somewhere to store your instances of the classes
ZomaTheMasterOfDisaster
Yeah pretty much After those are done I can work on controllers which should basically just pull the model commands then act as the api to the view to display
ἔρως
ἔρως4mo ago
yup and will you write the views in php?
ZomaTheMasterOfDisaster
Hmm Well the login and register both need php code to function and the user page will pull from the database Most likely
ἔρως
ἔρως4mo ago
makes perfect sense, and is the easiest anyways
ZomaTheMasterOfDisaster
I guess if I made an about page or if I had pages for like 404 or something I could make them html Oh! After models and controllers are done, I need to make a router
ἔρως
ἔρως4mo ago
shouldn't the router be first?
ZomaTheMasterOfDisaster
Technically yes I just didn't think about til just now
ἔρως
ἔρως4mo ago
yeah, you should think about it then
ZomaTheMasterOfDisaster
so i removed the code from the construct and put it in the connect() and made the connect static
<?php

namespace MD\dbhelper;
use MD\dbhelper\config;
use PDOException;

class Database {
/**
* PDO instance
* @var type
*/

private \PDO $pdo;

private const HASH_ALGO = PASSWORD_DEFAULT;

private const ENCRYPTION_COST = ['cost' => 11];

public function __construct()
{


}

public static function connect() {
try {
$pdo = new \PDO("sqlite:" . Config::PATH_TO_SQLITE_FILE);
} catch(PDOException $e) {
echo "Error with loading database: " . $e->getMessage();
}

return $pdo;

}

protected static function select($query) {
$pdo = Database::connect();
$sql = "SELECT "
}
/*
public function addUserQuery(string $username, string $password): bool|int {
static $query = 'INSERT INTO `user` (`username`, `password`) VALUES(:username, :password)';

$stmt = $this->pdo->prepare($query);

if(!$stmt) {
return false;
}

$hash = password_hash($password, self::HASH_ALGO, self::ENCRYPTION_COST);

$result = $stmt->exec([
':username' => $username,
':password' => $hash
]);

if(!$result) {
return false;
}

return $this->pdo->lastInsertId();
} */
}
<?php

namespace MD\dbhelper;
use MD\dbhelper\config;
use PDOException;

class Database {
/**
* PDO instance
* @var type
*/

private \PDO $pdo;

private const HASH_ALGO = PASSWORD_DEFAULT;

private const ENCRYPTION_COST = ['cost' => 11];

public function __construct()
{


}

public static function connect() {
try {
$pdo = new \PDO("sqlite:" . Config::PATH_TO_SQLITE_FILE);
} catch(PDOException $e) {
echo "Error with loading database: " . $e->getMessage();
}

return $pdo;

}

protected static function select($query) {
$pdo = Database::connect();
$sql = "SELECT "
}
/*
public function addUserQuery(string $username, string $password): bool|int {
static $query = 'INSERT INTO `user` (`username`, `password`) VALUES(:username, :password)';

$stmt = $this->pdo->prepare($query);

if(!$stmt) {
return false;
}

$hash = password_hash($password, self::HASH_ALGO, self::ENCRYPTION_COST);

$result = $stmt->exec([
':username' => $username,
':password' => $hash
]);

if(!$result) {
return false;
}

return $this->pdo->lastInsertId();
} */
}
ἔρως
ἔρως4mo ago
i have a much better idea for you how about you create the $pdo in the __construct? and store it in a static private variable?
ZomaTheMasterOfDisaster
<?php

namespace MD\dbhelper;
use MD\dbhelper\config;
use PDOException;

class Database {
/**
* PDO instance
* @var type
*/

private static \PDO $pdo;

private const HASH_ALGO = PASSWORD_DEFAULT;

private const ENCRYPTION_COST = ['cost' => 11];

public function __construct()
{
try {
$pdo = new \PDO("sqlite:" . Config::PATH_TO_SQLITE_FILE);
} catch(PDOException $e) {
echo "Error with loading database: " . $e->getMessage();
}

return $pdo;

}



protected static function select($) {
$pdo = Database::connect();
$sql = "SELECT `{$query}` FROM "
}
/*
public function addUserQuery(string $username, string $password): bool|int {
static $query = 'INSERT INTO `user` (`username`, `password`) VALUES(:username, :password)';

$stmt = $this->pdo->prepare($query);

if(!$stmt) {
return false;
}

$hash = password_hash($password, self::HASH_ALGO, self::ENCRYPTION_COST);

$result = $stmt->exec([
':username' => $username,
':password' => $hash
]);

if(!$result) {
return false;
}

return $this->pdo->lastInsertId();
} */
}
<?php

namespace MD\dbhelper;
use MD\dbhelper\config;
use PDOException;

class Database {
/**
* PDO instance
* @var type
*/

private static \PDO $pdo;

private const HASH_ALGO = PASSWORD_DEFAULT;

private const ENCRYPTION_COST = ['cost' => 11];

public function __construct()
{
try {
$pdo = new \PDO("sqlite:" . Config::PATH_TO_SQLITE_FILE);
} catch(PDOException $e) {
echo "Error with loading database: " . $e->getMessage();
}

return $pdo;

}



protected static function select($) {
$pdo = Database::connect();
$sql = "SELECT `{$query}` FROM "
}
/*
public function addUserQuery(string $username, string $password): bool|int {
static $query = 'INSERT INTO `user` (`username`, `password`) VALUES(:username, :password)';

$stmt = $this->pdo->prepare($query);

if(!$stmt) {
return false;
}

$hash = password_hash($password, self::HASH_ALGO, self::ENCRYPTION_COST);

$result = $stmt->exec([
':username' => $username,
':password' => $hash
]);

if(!$result) {
return false;
}

return $this->pdo->lastInsertId();
} */
}
ἔρως
ἔρως4mo ago
if the static private variable is empty, you create a new pdo if it isn't empty, you do nothing don't return from __contruct
ἔρως
ἔρως4mo ago
in the __construct, check if the static variable is empty before you create the pdo object
ZomaTheMasterOfDisaster
if !$pdo?
ἔρως
ἔρως4mo ago
almost that's a local variable, not static
ZomaTheMasterOfDisaster
it has to be instantiated before you can check if it is empty unless you declare it globally first and instantiate it
ἔρως
ἔρως4mo ago
not if you set it to null by default or check with empty
ZomaTheMasterOfDisaster
so i would check if (!empty($pdo))
ἔρως
ἔρως4mo ago
almost that's a local variable you want to access a static variable
ZomaTheMasterOfDisaster
public function __construct()
{

if(empty($pdo)) {
try {
$pdo = new \PDO("sqlite:" . Config::PATH_TO_SQLITE_FILE);

} catch(PDOException $e) {
echo "Error with loading database: " . $e->getMessage();
}

}
}
public function __construct()
{

if(empty($pdo)) {
try {
$pdo = new \PDO("sqlite:" . Config::PATH_TO_SQLITE_FILE);

} catch(PDOException $e) {
echo "Error with loading database: " . $e->getMessage();
}

}
}
ἔρως
ἔρως4mo ago
again local variable it won't work
ZomaTheMasterOfDisaster
mines at top of class class variable
ἔρως
ἔρως4mo ago
if(empty($pdo)) { <-- this is a local variable
ZomaTheMasterOfDisaster
self::
ἔρως
ἔρως4mo ago
yes
ZomaTheMasterOfDisaster
so that $pdo declaration should be self::$pdo =
ἔρως
ἔρως4mo ago
all $pdo inside that class, yes
ZomaTheMasterOfDisaster
public function __construct()
{

if(empty(self::$pdo)) {
try {
self::$pdo = new \PDO("sqlite:" . Config::PATH_TO_SQLITE_FILE);

} catch(PDOException $e) {
echo "Error with loading database: " . $e->getMessage();
}

}
}
public function __construct()
{

if(empty(self::$pdo)) {
try {
self::$pdo = new \PDO("sqlite:" . Config::PATH_TO_SQLITE_FILE);

} catch(PDOException $e) {
echo "Error with loading database: " . $e->getMessage();
}

}
}
ἔρως
ἔρως4mo ago
yup, that's it
ZomaTheMasterOfDisaster
so now there needs to be methods for select, update, create, and delete
ἔρως
ἔρως4mo ago
yeah, you can write your own ones, to make it easier for you to do what you need
ZomaTheMasterOfDisaster
I think I should either take in an array or more variables because ill need to see what is changing
ἔρως
ἔρως4mo ago
you can accept a table, a list of rows and receive a list of values
ZomaTheMasterOfDisaster
you mean the table construct that's mysql i think
ἔρως
ἔρως4mo ago
what table construct?
ἔρως
ἔρως4mo ago
why are you reading about mysql vendor-specific extensions when you're using pdo?
ZomaTheMasterOfDisaster
how you make a table?
ἔρως
ἔρως4mo ago
you write the sql for it like how you did before
ZomaTheMasterOfDisaster
good idea
ἔρως
ἔρως4mo ago
but don't forget the basics, like select, insert, update, delete
ZomaTheMasterOfDisaster
protected function select($field: string, $table: string): {
$sql = "SELECT `{$field}` FROM `{$table}`";
self::$pdo;
$stmt = self::$pdo->prepare($sql);

}
protected function select($field: string, $table: string): {
$sql = "SELECT `{$field}` FROM `{$table}`";
self::$pdo;
$stmt = self::$pdo->prepare($sql);

}
this is a start so far sadly the intellisense must be broke because it isn't picking up on the PDO functions
ἔρως
ἔρως4mo ago
self::$pdo; <-- why this?
ZomaTheMasterOfDisaster
just pdo?
ἔρως
ἔρως4mo ago
no, it's just there, doing nothing
ZomaTheMasterOfDisaster
mistake was having trouble listing the PDO functions I could use sadly they dont show up
ἔρως
ἔρως4mo ago
intelephense is ass it lists ALL THE FUNCTIONS because it's ass but it's the best we have, so you will only see the list of functions if you ... type a letter
ZomaTheMasterOfDisaster
I should make sure the $field is properly handled it could be more than one
ἔρως
ἔρως4mo ago
which means that ...?
ZomaTheMasterOfDisaster
probably need an array or spread operator?
ἔρως
ἔρως4mo ago
an array
ZomaTheMasterOfDisaster
protected function select($field, $table) {
$sql = "SELECT `{$field}` FROM `{$table}`";
$stmt = self::$pdo->prepare($sql);
$stmt_exec = self::$pdo->exec($stmt);

return $stmt_exec;

}

protected function select($field, $table) {
$sql = "SELECT `{$field}` FROM `{$table}`";
$stmt = self::$pdo->prepare($sql);
$stmt_exec = self::$pdo->exec($stmt);

return $stmt_exec;

}

a WHERE in there is possible too
ἔρως
ἔρως4mo ago
you can make it even easier instead of 1 array and a string, you can do 1 string or 1 array 'table' <-- would be equivalent to table.* ['table' => [...]] <-- would be equivalent to selecting each field from that specific table
ZomaTheMasterOfDisaster
protected function select(array $query): string {
$sql = "SELECT `{$query}`";
$stmt = self::$pdo->prepare($sql);
$stmt_exec = self::$pdo->exec($stmt);

return $stmt_exec;

}
protected function select(array $query): string {
$sql = "SELECT `{$query}`";
$stmt = self::$pdo->prepare($sql);
$stmt_exec = self::$pdo->exec($stmt);

return $stmt_exec;

}
ἔρως
ἔρως4mo ago
🤣 no, i wish it was that simple
ZomaTheMasterOfDisaster
😦 well crap
ἔρως
ἔρως4mo ago
😂
ZomaTheMasterOfDisaster
let me guess I need to loop that $sql creation
ἔρως
ἔρως4mo ago
depends on the values you receive
ZomaTheMasterOfDisaster
so what is wrong with that code
ἔρως
ἔρως4mo ago
well, you're trying to use an array as a string
ZomaTheMasterOfDisaster
it should be a string array 😄
ἔρως
ἔρως4mo ago
😂 dreams js does that automatically
ZomaTheMasterOfDisaster
or there's another way
ἔρως
ἔρως4mo ago
there's another way you can generate 2 different queries if it is a string, just the basic select * from table if it is an array, then you have to implode it in a may to make it proper sql table names
ZomaTheMasterOfDisaster
protected function select(): string {
$args = func_get_args();
$sql = "SELECT `{$args}`";
$stmt = self::$pdo->prepare($sql);
$stmt_exec = self::$pdo->exec($stmt);

return $stmt_exec;

}
protected function select(): string {
$args = func_get_args();
$sql = "SELECT `{$args}`";
$stmt = self::$pdo->prepare($sql);
$stmt_exec = self::$pdo->exec($stmt);

return $stmt_exec;

}
ἔρως
ἔρως4mo ago
that's absolutely much worse
ZomaTheMasterOfDisaster
since func_get_args() gets variable number of arguments from the function
ἔρως
ἔρως4mo ago
yes, but that's horrible, trust me just take 1 argument, and accept a string or array also, exec doesn't return a string
ZomaTheMasterOfDisaster
protected function select(string|array $query): string {
if()
}

protected function select(string|array $query): string {
if()
}

ἔρως
ἔρως4mo ago
yup
ZomaTheMasterOfDisaster
what's the type checker in php?
ἔρως
ἔρως4mo ago
php
ZomaTheMasterOfDisaster
i mean function 😄
ἔρως
ἔρως4mo ago
what do you mean?
ZomaTheMasterOfDisaster
like if query is array
ἔρως
ἔρως4mo ago
is_array
ἔρως
ἔρως4mo ago
if you need to check what type something is, just use is_<type>
ZomaTheMasterOfDisaster
protected function select(string|array $query): string {
$type = is_string($query);
if($type) {
$sql = "SELECT * FROM `{$query}`";
$stmt = self::$pdo->prepare($sql);
$stmt_exec = $stmt->exec($stmt);
}
else {

}
}

protected function select(string|array $query): string {
$type = is_string($query);
if($type) {
$sql = "SELECT * FROM `{$query}`";
$stmt = self::$pdo->prepare($sql);
$stmt_exec = $stmt->exec($stmt);
}
else {

}
}

can use implode
ἔρως
ἔρως4mo ago
it's not a matter of "can", but it's a "use implode or build it yourself in a worse way" which is something common in php
ZomaTheMasterOfDisaster
woo
protected function select(string|array $query) {
$type = is_string($query);
if($type) {
$sql = "SELECT * FROM `{$query}`";
$stmt = self::$pdo->prepare($sql);
return $stmt->exec($stmt);
}
else {
$statements = implode(",", $query);
$sql = "SELECT `{$statements}`";
$stmt = self::$pdo->prepare($sql);
return $stmt->exec($stmt);
}
}
protected function select(string|array $query) {
$type = is_string($query);
if($type) {
$sql = "SELECT * FROM `{$query}`";
$stmt = self::$pdo->prepare($sql);
return $stmt->exec($stmt);
}
else {
$statements = implode(",", $query);
$sql = "SELECT `{$statements}`";
$stmt = self::$pdo->prepare($sql);
return $stmt->exec($stmt);
}
}
this means loop to get the statements in the sql hmm so how does this work
ἔρως
ἔρως4mo ago
how about you stop and write a list of what you want the function to do? like how you did before?
ZomaTheMasterOfDisaster
i got it 🙂
protected function select(string|array $query) {
$type = is_string($query);
if(empty($query)) {
echo "Please have select statement";
}
else {
if($type) {
$sql = "SELECT * FROM `{$query}`";
$stmt = self::$pdo->prepare($sql);
return $stmt->exec($stmt);
}
else {
$statements = implode(",", $query);
$sql = "SELECT `{$statements}`";
$stmt = self::$pdo->prepare($sql);
return $stmt->exec($stmt);
}
}
}
protected function select(string|array $query) {
$type = is_string($query);
if(empty($query)) {
echo "Please have select statement";
}
else {
if($type) {
$sql = "SELECT * FROM `{$query}`";
$stmt = self::$pdo->prepare($sql);
return $stmt->exec($stmt);
}
else {
$statements = implode(",", $query);
$sql = "SELECT `{$statements}`";
$stmt = self::$pdo->prepare($sql);
return $stmt->exec($stmt);
}
}
}
ἔρως
ἔρως4mo ago
no, not yet just make the list, trust me
ZomaTheMasterOfDisaster
What the select statement should do

1. user passes in a string or array for the proper query
2. check if the string or array is empty
- print an error message
3. else check if the type is string
- it is string
- select all items from the table being sent as the string
- execute the statment to the database
- return the results as a string
- display it to the user
4. else it is an array
- get all the select query statement variables
- create the sql query for the database
- execute the sql statement
- return the results as a string
- display it to the user
What the select statement should do

1. user passes in a string or array for the proper query
2. check if the string or array is empty
- print an error message
3. else check if the type is string
- it is string
- select all items from the table being sent as the string
- execute the statment to the database
- return the results as a string
- display it to the user
4. else it is an array
- get all the select query statement variables
- create the sql query for the database
- execute the sql statement
- return the results as a string
- display it to the user
ἔρως
ἔρως4mo ago
point 2, the print part that's absolutely horrible don't do that throw an exception point 3, 2nd line is literally impossiible impossible as well as 4
ZomaTheMasterOfDisaster
list didnt help me then
ἔρως
ἔρως4mo ago
yes it did trust me, it always does
ZomaTheMasterOfDisaster
point 2 is fixed
protected function select(string|array $query) {
$type = is_string($query);
if(empty($query)) {
throw new ErrorException("Select statement must not be empty");
}
else {
if($type) {
$sql = "SELECT * FROM `{$query}`";
$stmt = self::$pdo->prepare($sql);
return $stmt->exec($stmt);
}
else {
$statements = implode(",", $query);
$sql = "SELECT `{$statements}`";
$stmt = self::$pdo->prepare($sql);
return $stmt->exec($stmt);
}
}
}

protected function select(string|array $query) {
$type = is_string($query);
if(empty($query)) {
throw new ErrorException("Select statement must not be empty");
}
else {
if($type) {
$sql = "SELECT * FROM `{$query}`";
$stmt = self::$pdo->prepare($sql);
return $stmt->exec($stmt);
}
else {
$statements = implode(",", $query);
$sql = "SELECT `{$statements}`";
$stmt = self::$pdo->prepare($sql);
return $stmt->exec($stmt);
}
}
}

ἔρως
ἔρως4mo ago
why an error exception when an argument count (https://www.php.net/manual/en/class.argumentcounterror.php) would probably more appropriate?
ZomaTheMasterOfDisaster
i was going by this
ZomaTheMasterOfDisaster
remember im not this well versed in php i barely ever used php in life java is probably the only language ive used extensively
ἔρως
ἔρως4mo ago
i know, but im asking this so you stop and think
ZomaTheMasterOfDisaster
okay changed to value error so point 2 is fixed
ἔρως
ἔρως4mo ago
and the other one?
ZomaTheMasterOfDisaster
im not sure
else {
if($type) {
$sql = "SELECT * FROM `{$query}`";
$stmt = self::$pdo->prepare($sql);
return $stmt->exec($stmt);
}
else {
$statements = implode(",", $query);
$sql = "SELECT `{$statements}`";
$stmt = self::$pdo->prepare($sql);
return $stmt->exec($stmt);
}
}
else {
if($type) {
$sql = "SELECT * FROM `{$query}`";
$stmt = self::$pdo->prepare($sql);
return $stmt->exec($stmt);
}
else {
$statements = implode(",", $query);
$sql = "SELECT `{$statements}`";
$stmt = self::$pdo->prepare($sql);
return $stmt->exec($stmt);
}
}
that's this code
ἔρως
ἔρως4mo ago
return an array databases dont return a single string
ἔρως
ἔρως4mo ago
by just fetching or a generator
ἔρως
ἔρως4mo ago
by the way, exec doesn't exist https://www.php.net/manual/en/pdostatement.execute.php <-- it's execute look at the return values as well
ZomaTheMasterOfDisaster
here's some progress
protected function select(string|array $query) {
$type = is_string($query);
if(empty($query)) {
throw new ValueError("Select statement must not be empty");
}
else {
if($type) {
$sql = "SELECT * FROM `{$query}`";
$stmt = self::$pdo->prepare($sql);
$stmt->execute($stmt);
$results = $stmt->fetchAll();
return $results;
}
else {
$statements = implode(",", $query);
$sql = "SELECT `{$statements}`";
$stmt = self::$pdo->prepare($sql);
return $stmt->execute($stmt);
}
}
}
protected function select(string|array $query) {
$type = is_string($query);
if(empty($query)) {
throw new ValueError("Select statement must not be empty");
}
else {
if($type) {
$sql = "SELECT * FROM `{$query}`";
$stmt = self::$pdo->prepare($sql);
$stmt->execute($stmt);
$results = $stmt->fetchAll();
return $results;
}
else {
$statements = implode(",", $query);
$sql = "SELECT `{$statements}`";
$stmt = self::$pdo->prepare($sql);
return $stmt->execute($stmt);
}
}
}
ἔρως
ἔρως4mo ago
it is some progress, but that's still not going to work first, you're nesting too much and your indentation needs serious work, asap fix those 2 things then, worry about making the string type work completely ignore arrays for now
ZomaTheMasterOfDisaster
im not really concerned about indentation that can be fixed after code is working right now this needs to work
ἔρως
ἔρως4mo ago
well, you have to have good habits well indented code is mandatory
ZomaTheMasterOfDisaster
amazon didnt care they were just happy it worked
ἔρως
ἔρως4mo ago
it helps you catch bugs, it helps others to read the code it highlights the conditions a lot more visibly you can quickly glance at the code and understand how many levels deep you're getting into so, please, fix your indentation
ZomaTheMasterOfDisaster
any fast way in vscode i dont wanna do this forever
ἔρως
ἔρως4mo ago
yes: use tabs you can convert the indentation to tabs and it fixes everything for you
ZomaTheMasterOfDisaster
<?php

namespace MD\dbhelper;

use ErrorException;
use Exception;
use MD\dbhelper\config;
use PDOException;
use ValueError;

class Database
{
/**
* PDO instance
* @var type
*/

private static \PDO $pdo;

private const HASH_ALGO = PASSWORD_DEFAULT;

private const ENCRYPTION_COST = ['cost' => 11];

public function __construct()
{

if (empty(self::$pdo)) {
try {
self::$pdo = new \PDO("sqlite:" . Config::PATH_TO_SQLITE_FILE);
} catch (PDOException $e) {
echo "Error with loading database: " . $e->getMessage();
}
}
}

protected function select(string|array $query)
{
$type = is_string($query);
if (empty($type)) {
throw new ValueError("Select statement must not be empty");
}
}




/*
public function addUserQuery(string $username, string $password): bool|int {
static $query = 'INSERT INTO `user` (`username`, `password`) VALUES(:username, :password)';

$stmt = $this->pdo->prepare($query);

if(!$stmt) {
return false;
}

$hash = password_hash($password, self::HASH_ALGO, self::ENCRYPTION_COST);

$result = $stmt->exec([
':username' => $username,
':password' => $hash
]);

if(!$result) {
return false;
}

return $this->pdo->lastInsertId();
} */
}
<?php

namespace MD\dbhelper;

use ErrorException;
use Exception;
use MD\dbhelper\config;
use PDOException;
use ValueError;

class Database
{
/**
* PDO instance
* @var type
*/

private static \PDO $pdo;

private const HASH_ALGO = PASSWORD_DEFAULT;

private const ENCRYPTION_COST = ['cost' => 11];

public function __construct()
{

if (empty(self::$pdo)) {
try {
self::$pdo = new \PDO("sqlite:" . Config::PATH_TO_SQLITE_FILE);
} catch (PDOException $e) {
echo "Error with loading database: " . $e->getMessage();
}
}
}

protected function select(string|array $query)
{
$type = is_string($query);
if (empty($type)) {
throw new ValueError("Select statement must not be empty");
}
}




/*
public function addUserQuery(string $username, string $password): bool|int {
static $query = 'INSERT INTO `user` (`username`, `password`) VALUES(:username, :password)';

$stmt = $this->pdo->prepare($query);

if(!$stmt) {
return false;
}

$hash = password_hash($password, self::HASH_ALGO, self::ENCRYPTION_COST);

$result = $stmt->exec([
':username' => $username,
':password' => $hash
]);

if(!$result) {
return false;
}

return $this->pdo->lastInsertId();
} */
}
better?
ἔρως
ἔρως4mo ago
much better
ZomaTheMasterOfDisaster
ok back to more important matters
ἔρως
ἔρως4mo ago
$type = is_string($query);
if (empty($type)) {
throw new ValueError("Select statement must not be empty");
}
$type = is_string($query);
if (empty($type)) {
throw new ValueError("Select statement must not be empty");
}
^ you have a bug
ἔρως
ἔρως4mo ago
can you show the fixed code?
ZomaTheMasterOfDisaster
$type = is_string($query);
if (empty($query)) {
throw new ValueError("Select statement must not be empty");
}
$type = is_string($query);
if (empty($query)) {
throw new ValueError("Select statement must not be empty");
}
ἔρως
ἔρως4mo ago
yup but delete the $type variable
ZomaTheMasterOfDisaster
ok whenever I tried to use is_string in an if vscode complained it was syntax errored well oddly it didnt this time weird this next
if(is_string($query)) {
$sql = "SELECT * FROM {$query}";
$stmt = self::$pdo->prepare($sql);
$stmt->execute();
$results = $stmt->fetchAll();
return $results;

} else {

}
if(is_string($query)) {
$sql = "SELECT * FROM {$query}";
$stmt = self::$pdo->prepare($sql);
$stmt->execute();
$results = $stmt->fetchAll();
return $results;

} else {

}
ἔρως
ἔρως4mo ago
instead of fetchall, try a generator basically, loop and yield
ἔρως
ἔρως4mo ago
try it, see how it feels for you
ZomaTheMasterOfDisaster
sorry cat was frustrating me generator looks too complicated
ἔρως
ἔρως4mo ago
dude, it's literally a fake array you get the values with a foreach loop you replace the return with yield
ZomaTheMasterOfDisaster
ok so how would this work after my execute
ἔρως
ἔρως4mo ago
while($row = $stmt->fetch()) {
yield $row;
}
while($row = $stmt->fetch()) {
yield $row;
}
that's literally it
ZomaTheMasterOfDisaster
no way their examples are just foreach and for loops lol
ἔρως
ἔρως4mo ago
that's all you need this way, the select method returns a generator and you just use a foreach on it
ZomaTheMasterOfDisaster
protected function select(string|array $query)
{

if (empty($query)) {
throw new ValueError("Select statement must not be empty");
}

if(is_string($query)) {
$sql = "SELECT * FROM {$query}";
$stmt = self::$pdo->prepare($sql);
$stmt->execute();

while($row = $stmt->fetch()) {
yield $row;
}

} else {

}
}
protected function select(string|array $query)
{

if (empty($query)) {
throw new ValueError("Select statement must not be empty");
}

if(is_string($query)) {
$sql = "SELECT * FROM {$query}";
$stmt = self::$pdo->prepare($sql);
$stmt->execute();

while($row = $stmt->fetch()) {
yield $row;
}

} else {

}
}
dinner break
ἔρως
ἔρως4mo ago
looks good to mne me
ZomaTheMasterOfDisaster
what do I do with the yield since we were returning an array?
ἔρως
ἔρως4mo ago
yield yields a value, and waits for you to use the generator to actually give you the value so, imagine you return 500 rows
ZomaTheMasterOfDisaster
so add the value to an array?
ἔρως
ἔρως4mo ago
instead of giving you a massive array of 500 rows, it gives you 1 row at a time and then you do whatever you want you can loop it and show it imediately
ZomaTheMasterOfDisaster
oh since this isn't the right class for it where should it go?
ἔρως
ἔρως4mo ago
i never said it wasn't the right class im just saying that a yield is like a return, but waits for you to use the value instead of an array, it gives a generator
ZomaTheMasterOfDisaster
protected function select(string|array $query)
{

if (empty($query)) {
throw new ValueError("Select statement must not be empty");
}

if(is_string($query)) {
$sql = "SELECT * FROM {$query}";
$stmt = self::$pdo->prepare($sql);
$stmt->execute();

while($row = $stmt->fetch()) {
yield $row;
}

} else {
$sql = "";
$stmt = self::$pdo->prepare($sql);

}
}
protected function select(string|array $query)
{

if (empty($query)) {
throw new ValueError("Select statement must not be empty");
}

if(is_string($query)) {
$sql = "SELECT * FROM {$query}";
$stmt = self::$pdo->prepare($sql);
$stmt->execute();

while($row = $stmt->fetch()) {
yield $row;
}

} else {
$sql = "";
$stmt = self::$pdo->prepare($sql);

}
}
that's what I got so far
ZomaTheMasterOfDisaster
so I can return the yield or function?
ἔρως
ἔρως4mo ago
it's not a return, it's not a function it's a yield
ZomaTheMasterOfDisaster
oh ok so id just call the function to use it? then use a for loop to use it later?
ἔρως
ἔρως4mo ago
check line 13 of the code
ZomaTheMasterOfDisaster
i see it
foreach(xyz() as $value){
echo json_encode($value), PHP_EOL;
}
foreach(xyz() as $value){
echo json_encode($value), PHP_EOL;
}
ἔρως
ἔρως4mo ago
that's extremely useful because it doesn't "return" a value until you iterate the generator so, it will wait until the value is needed
ZomaTheMasterOfDisaster
so far that while loop Id do just what you did
ἔρως
ἔρως4mo ago
yup
ZomaTheMasterOfDisaster
protected function select(string|array $query)
{

if (empty($query)) {
throw new ValueError("Select statement must not be empty");
}

if(is_string($query)) {
$sql = "SELECT * FROM {$query}";
$stmt = self::$pdo->prepare($sql);
$stmt->execute();

while($row = $stmt->fetch()) {
yield $row;
}

foreach()

} else {
$sql = "";
$stmt = self::$pdo->prepare($sql);

}
}
protected function select(string|array $query)
{

if (empty($query)) {
throw new ValueError("Select statement must not be empty");
}

if(is_string($query)) {
$sql = "SELECT * FROM {$query}";
$stmt = self::$pdo->prepare($sql);
$stmt->execute();

while($row = $stmt->fetch()) {
yield $row;
}

foreach()

} else {
$sql = "";
$stmt = self::$pdo->prepare($sql);

}
}
do i say $row as $value?
ἔρως
ἔρως4mo ago
you actually don't do anything else once you yield, the function stops
ZomaTheMasterOfDisaster
ok since i got a meetup with a friend in a few lets aim to finish select for tonight
ἔρως
ἔρως4mo ago
remove the for each, and you have 70% done
ZomaTheMasterOfDisaster
you see where im at currently for the array it's rmeoved removed
ἔρως
ἔρως4mo ago
by the way, instead of calling it $query, i would give it a descriptive name, like $table
ZomaTheMasterOfDisaster
fixed
protected function select(string|array $table)
{

if (empty($table)) {
throw new ValueError("Select statement must not be empty");
}

if(is_string($table)) {
$sql = "SELECT * FROM {$table}";
$stmt = self::$pdo->prepare($sql);
$stmt->execute();

while($row = $stmt->fetch()) {
yield $row;
}

} else {
$sql = "";
$stmt = self::$pdo->prepare($sql);

}
}
protected function select(string|array $table)
{

if (empty($table)) {
throw new ValueError("Select statement must not be empty");
}

if(is_string($table)) {
$sql = "SELECT * FROM {$table}";
$stmt = self::$pdo->prepare($sql);
$stmt->execute();

while($row = $stmt->fetch()) {
yield $row;
}

} else {
$sql = "";
$stmt = self::$pdo->prepare($sql);

}
}
` so we know select is the first word ok so my guess is you would implode the array first then add it to the sql statement? we would implode based on " " space beng the separator
ἔρως
ἔρως4mo ago
backtick, comma, backtick
ZomaTheMasterOfDisaster
else {
$fixedStatement = implode("`,`", $table);
$sql = "SELECT `{$fixedStatement}`";
$stmt = self::$pdo->prepare($sql);
$stmt->execute();
}
else {
$fixedStatement = implode("`,`", $table);
$sql = "SELECT `{$fixedStatement}`";
$stmt = self::$pdo->prepare($sql);
$stmt->execute();
}
ἔρως
ἔρως4mo ago
you have to have backticks on the value as well
ZomaTheMasterOfDisaster
updated then do the generator? updated function
protected function select(string|array $table)
{

if (empty($table)) {
throw new ValueError("Select statement must not be empty");
}

if(is_string($table)) {
$sql = "SELECT * FROM {$table}";
$stmt = self::$pdo->prepare($sql);
$stmt->execute();

while($row = $stmt->fetch()) {
yield $row;
}

} else {
$fixedStatement = implode("`,`", $table);
$sql = "SELECT `{$fixedStatement}`";
$stmt = self::$pdo->prepare($sql);
$stmt->execute();

while($row = $stmt->fetch()) {
yield $row;
}
}
}
protected function select(string|array $table)
{

if (empty($table)) {
throw new ValueError("Select statement must not be empty");
}

if(is_string($table)) {
$sql = "SELECT * FROM {$table}";
$stmt = self::$pdo->prepare($sql);
$stmt->execute();

while($row = $stmt->fetch()) {
yield $row;
}

} else {
$fixedStatement = implode("`,`", $table);
$sql = "SELECT `{$fixedStatement}`";
$stmt = self::$pdo->prepare($sql);
$stmt->execute();

while($row = $stmt->fetch()) {
yield $row;
}
}
}
ἔρως
ἔρως4mo ago
it's still missing something from the array one, but it's fine for now now, move everything that's duplicated out all of it off of the conditions
ZomaTheMasterOfDisaster
$stmt = self::$pdo->prepare($sql);
$stmt->execute();
$stmt = self::$pdo->prepare($sql);
$stmt->execute();
this are duplicated the sql statements are a bit different
ἔρως
ἔρως4mo ago
the loop is duplicated too
ZomaTheMasterOfDisaster
111php
protected function select(string|array $table)
{

$stmt = self::$pdo->prepare($sql);
$stmt->execute();
while($row = $stmt->fetch()) {
yield $row;
}

if (empty($table)) {
throw new ValueError("Select statement must not be empty");
}

if(is_string($table)) {
$sql = "SELECT * FROM {$table}";




} else {
$fixedStatement = implode("`,`", $table);
$sql = "SELECT `{$fixedStatement}`";

}
}
protected function select(string|array $table)
{

$stmt = self::$pdo->prepare($sql);
$stmt->execute();
while($row = $stmt->fetch()) {
yield $row;
}

if (empty($table)) {
throw new ValueError("Select statement must not be empty");
}

if(is_string($table)) {
$sql = "SELECT * FROM {$table}";




} else {
$fixedStatement = implode("`,`", $table);
$sql = "SELECT `{$fixedStatement}`";

}
}
moved out for now
ἔρως
ἔρως4mo ago
to the bottom of the function code is executed from top to bottom
ZomaTheMasterOfDisaster
i just moved it for now i commented it out
ἔρως
ἔρως4mo ago
why did you comment it out?
ZomaTheMasterOfDisaster
so i dont lose it until this part is done then delete it
ἔρως
ἔρως4mo ago
can you send what you have?
ZomaTheMasterOfDisaster
protected function select(string|array $table)
{

/*
$stmt = self::$pdo->prepare($sql);
$stmt->execute();
while($row = $stmt->fetch()) {
yield $row;
}
*/
if (empty($table)) {
throw new ValueError("Select statement must not be empty");
}

if(is_string($table)) {
$sql = "SELECT * FROM {$table}";




} else {
$fixedStatement = implode("`,`", $table);
$sql = "SELECT `{$fixedStatement}`";

}
}
protected function select(string|array $table)
{

/*
$stmt = self::$pdo->prepare($sql);
$stmt->execute();
while($row = $stmt->fetch()) {
yield $row;
}
*/
if (empty($table)) {
throw new ValueError("Select statement must not be empty");
}

if(is_string($table)) {
$sql = "SELECT * FROM {$table}";




} else {
$fixedStatement = implode("`,`", $table);
$sql = "SELECT `{$fixedStatement}`";

}
}
ἔρως
ἔρως4mo ago
why did you comment it out? you just have it in the wrong place that's all
ZomaTheMasterOfDisaster
because i have no clue what were doing so i dont want to lose working code
ἔρως
ἔρως4mo ago
you see where the repeated code is, in this function?
ZomaTheMasterOfDisaster
protected function select(string|array $table)
{



if (empty($table)) {
throw new ValueError("Select statement must not be empty");
}

if(is_string($table)) {
$sql = "SELECT * FROM {$table}";




} else {
$fixedStatement = implode("`,`", $table);
$sql = "SELECT `{$fixedStatement}`";

}

$stmt = self::$pdo->prepare($sql);
$stmt->execute();
while($row = $stmt->fetch()) {
yield $row;
}
}
protected function select(string|array $table)
{



if (empty($table)) {
throw new ValueError("Select statement must not be empty");
}

if(is_string($table)) {
$sql = "SELECT * FROM {$table}";




} else {
$fixedStatement = implode("`,`", $table);
$sql = "SELECT `{$fixedStatement}`";

}

$stmt = self::$pdo->prepare($sql);
$stmt->execute();
while($row = $stmt->fetch()) {
yield $row;
}
}
ἔρως
ἔρως4mo ago
there you go now fix up the spacing
ZomaTheMasterOfDisaster
protected function select(string|array $table)
{
if (empty($table)) {
throw new ValueError("Select statement must not be empty");
}

if (is_string($table)) {
$sql = "SELECT * FROM {$table}";
} else {
$fixedStatement = implode("`,`", $table);
$sql = "SELECT `{$fixedStatement}`";
}

$stmt = self::$pdo->prepare($sql);
$stmt->execute();
while ($row = $stmt->fetch()) {
yield $row;
}
}
protected function select(string|array $table)
{
if (empty($table)) {
throw new ValueError("Select statement must not be empty");
}

if (is_string($table)) {
$sql = "SELECT * FROM {$table}";
} else {
$fixedStatement = implode("`,`", $table);
$sql = "SELECT `{$fixedStatement}`";
}

$stmt = self::$pdo->prepare($sql);
$stmt->execute();
while ($row = $stmt->fetch()) {
yield $row;
}
}
ἔρως
ἔρως4mo ago
much better
ZomaTheMasterOfDisaster
whats next
ἔρως
ἔρως4mo ago
rest
ZomaTheMasterOfDisaster
it's not done though array feels like it's not done
ἔρως
ἔρως4mo ago
it isn't i just don't a good way for it
ZomaTheMasterOfDisaster
tomorrow ill tackle it next then my goal for weekend is at least have database and model done and start on controllers
ἔρως
ἔρως4mo ago
you can finish the other methods too, later on
ZomaTheMasterOfDisaster
im gonna have to start working at a faster pace finish things sooner my turtle speed means no jobs for me
ἔρως
ἔρως4mo ago
everybody learns at their own speed i learn super quick, doing multiple things at the same time not everybody is like that
ZomaTheMasterOfDisaster
im gonna have to get there because no one will hire me with this pace
ἔρως
ἔρως4mo ago
you will get there
ZomaTheMasterOfDisaster
hope so is there a solution to the array thing
ἔρως
ἔρως4mo ago
yes there are 2 solutions: 1- ['table', ['col1', 'col2', ... 'colx']] 2- ['table' => ['col1', 'col2', ... 'colx']]
ZomaTheMasterOfDisaster
oh neat! 🙂
ἔρως
ἔρως4mo ago
you pick how it will work
ZomaTheMasterOfDisaster
ok ok so back to the array
ἔρως
ἔρως4mo ago
yes, which option will you choose?
ZomaTheMasterOfDisaster
both are good but maybe which ever is a bit easier
ἔρως
ἔρως4mo ago
the 1st one
ZomaTheMasterOfDisaster
so I have the word SELECT already so I know it will be "column(s)" then FROM then either WHERE or not ok let's do it
ἔρως
ἔρως4mo ago
yup, the 2nd one is columns and you know what to do with it
ZomaTheMasterOfDisaster
protected function select(string|array $table)
{
if (empty($table)) {
throw new ValueError("Select statement must not be empty");
}

if (is_string($table)) {
$sql = "SELECT * FROM {$table}";
} else {
$fixedStatement = implode("`,`", $table);
$sql = "SELECT `{$fixedStatement}`";
}

$stmt = self::$pdo->prepare($sql);
$stmt->execute();
while ($row = $stmt->fetch()) {
yield $row;
}
}
protected function select(string|array $table)
{
if (empty($table)) {
throw new ValueError("Select statement must not be empty");
}

if (is_string($table)) {
$sql = "SELECT * FROM {$table}";
} else {
$fixedStatement = implode("`,`", $table);
$sql = "SELECT `{$fixedStatement}`";
}

$stmt = self::$pdo->prepare($sql);
$stmt->execute();
while ($row = $stmt->fetch()) {
yield $row;
}
}
here's our starting point
ἔρως
ἔρως4mo ago
on the else is where you generate the sql for the array
ZomaTheMasterOfDisaster
yes I have it somewhat started
ἔρως
ἔρως4mo ago
yup, you do
ZomaTheMasterOfDisaster
so what is missing here im guessing SQL statement is wrong
ἔρως
ἔρως4mo ago
it's missing the table and the variable is wrong
ZomaTheMasterOfDisaster
else {
$table = implode("`,`", $table);
$sql = "SELECT `{$table}`";

}
else {
$table = implode("`,`", $table);
$sql = "SELECT `{$table}`";

}
ἔρως
ἔρως4mo ago
almost there
ZomaTheMasterOfDisaster
only other way off top of my head is to have table be broken up into $statements, and $parameters
ἔρως
ἔρως4mo ago
that naming doesn't make sense, but i know what you mean
ZomaTheMasterOfDisaster
let's try an example say we get SELECT description FROM tasks WHERE userid=2; using w3schools run editor we get this
SELECT`,`description`,`FROM`,`tasks`,`WHERE`,`userid`,`=`,`2`,`;
SELECT`,`description`,`FROM`,`tasks`,`WHERE`,`userid`,`=`,`2`,`;
using example code...
<?php
$arr = array('SELECT','description', 'FROM', 'tasks', 'WHERE', 'userid', '=', '2', ';');
echo implode("`,`",$arr);
?>
<?php
$arr = array('SELECT','description', 'FROM', 'tasks', 'WHERE', 'userid', '=', '2', ';');
echo implode("`,`",$arr);
?>
ἔρως
ἔρως4mo ago
what do you have in mind for when you call the function?
ZomaTheMasterOfDisaster
it should come out SELECT description FROM tasks WHERE userid=2;` at least that's the goal unfortunately discord doesn't handle it correctly because of how they handle backticks but you get the idea so this $table = implode(",", $table);` is incorrect
ἔρως
ἔρως4mo ago
i get the idea and it is incorrect, yes but im trying to understand what you think that it will look like to do a select from this
ZomaTheMasterOfDisaster
they bring in an array of the commands words then implode it then create the query, prepare it then execute
ἔρως
ἔρως4mo ago
write in code or pseudocode
ZomaTheMasterOfDisaster
if you just use the space you get the right idea
<?php
$arr = array('SELECT','description', 'FROM', 'tasks', 'WHERE', 'userid', '=', '2', ';');
echo implode(" ",$arr);
?>
<?php
$arr = array('SELECT','description', 'FROM', 'tasks', 'WHERE', 'userid', '=', '2', ';');
echo implode(" ",$arr);
?>
then you add the backticks and comma after
ἔρως
ἔρως4mo ago
imagine this you have to use the select method write, in pseudocode, how you would you call it (wrong or right, doesn't matter) and how you would process the result imagine it's just a list of ids from the users
ZomaTheMasterOfDisaster
just a general select works like this must have keywords SELECT, FROM, and possibly where
ἔρως
ἔρως4mo ago
that's not what i asked
ZomaTheMasterOfDisaster
well that approach isnt working for me i need to understand how select actually works
ἔρως
ἔρως4mo ago
im trying to understand how you think that the function is meant to work
ZomaTheMasterOfDisaster
there are two must have keywords and one optional then check for one or more columns and report an error if 0 are present, then you check for a table name after from being present or more than one then you check for WHERE clause and if there is then check the condition otherwise either an error or no WHERE clause was needed so implode takes in an array and returns a string so then you check the string out unless you wanna loop through the array then implode you can use str_contains to check for must needed words like SELECT and FROM then WHERE is optional after that you can check the inner workings where you look at the columns and such
ἔρως
ἔρως4mo ago
can you put all that into code or pseudo-code?
ZomaTheMasterOfDisaster
here's a start
private function queryCheck(array $queryAsArray) {
for($i = 0; $i < count($queryAsArray); $i++) {
if(str_contains($queryAsArray[$i], "SELECT")) {
return true;
}

if(str_contains($queryAsArray[$i], "FROM")) {
return true;
}
}
}
private function queryCheck(array $queryAsArray) {
for($i = 0; $i < count($queryAsArray); $i++) {
if(str_contains($queryAsArray[$i], "SELECT")) {
return true;
}

if(str_contains($queryAsArray[$i], "FROM")) {
return true;
}
}
}
but since there's a precise order they need to be in
ἔρως
ἔρως4mo ago
what's that function for?
ZomaTheMasterOfDisaster
if($queryAsArray[0] == "SELECT") {
return true;
}
if($queryAsArray[0] == "SELECT") {
return true;
}
ἔρως
ἔρως4mo ago
yeah, but why?
ZomaTheMasterOfDisaster
private function queryFormatter(array $queryAsArray) {

if($queryAsArray[0] == "SELECT") {
return true;
}

// then check for columns


// check for FROM

// check tables

// check if WHERE is there

// complete query with semicolon

// create final string

// return correct string


}
private function queryFormatter(array $queryAsArray) {

if($queryAsArray[0] == "SELECT") {
return true;
}

// then check for columns


// check for FROM

// check tables

// check if WHERE is there

// complete query with semicolon

// create final string

// return correct string


}
here's the correct logic thing is there could extremely high number of columns (to the point of out of memory for the database)
ἔρως
ἔρως4mo ago
so, i want to use your class to get data from the database now, what do i do?
ZomaTheMasterOfDisaster
no clue im just spinning my wheels now it should be check for a connection, use the appropirate query method, then execute it
ἔρως
ἔρως4mo ago
yes, so, i want to use the select method now what?
ZomaTheMasterOfDisaster
it should create a proper string then pass it into an sql statement then prepare it then execute it then yield the result for the caller
ἔρως
ἔρως4mo ago
which arguments do i pass to the function?
ZomaTheMasterOfDisaster
key ones is SELECT, FROM with WHERE being optional
ἔρως
ἔρως4mo ago
how would it look like in code?
ZomaTheMasterOfDisaster
well SELECT should be first element so
if($table[0] == "SELECT") {...}
if($table[0] == "SELECT") {...}
then columns after could be a ton so that's another array imploding it with comma separators then check FROM then array for tables implode them with comma as separator then check if the keyword WHERE is after them if not then it's done otherwise you check for the clause after the keyword WHERE and if it has something = something or whatever it could be you would technically loop through the array until you reach the word FROM when checking columns
ἔρως
ἔρως4mo ago
i want to use your class to get a list of users' names and ids. how do i implement your class and the select method, in pseudo-code?
ZomaTheMasterOfDisaster
idk im just implementing select from scratch
ἔρως
ἔρως4mo ago
but that's what you need to think about you will use it you're writting it how do you want it to work?
ZomaTheMasterOfDisaster
private function selectQueryFormatter(array $queryAsArray) : string|bool {

if($queryAsArray[0] == "SELECT") {
$columns = array();
// then check for columns
for($i = 0; $i < count($queryAsArray); $i++) {
if($queryAsArray[$i] == "FROM") {
break;
}
array_push($queryAsArray[$i]);
}


$columns = implode(",",$columns);



// check for FROM
} else {
return false;
}



// check for FROM

// check tables

// check if WHERE is there

// complete query with semicolon

// create final string

// return correct string


}
private function selectQueryFormatter(array $queryAsArray) : string|bool {

if($queryAsArray[0] == "SELECT") {
$columns = array();
// then check for columns
for($i = 0; $i < count($queryAsArray); $i++) {
if($queryAsArray[$i] == "FROM") {
break;
}
array_push($queryAsArray[$i]);
}


$columns = implode(",",$columns);



// check for FROM
} else {
return false;
}



// check for FROM

// check tables

// check if WHERE is there

// complete query with semicolon

// create final string

// return correct string


}
that is a start so far
ἔρως
ἔρως4mo ago
so, you want to pass the query bits, one by one?
ZomaTheMasterOfDisaster
if you think about it if you're building a correct select query you need to check for SELECT first, then grab all the columns and parse them into something correctly formatted, then check for the FROM keyword then grab all the tables and format them, then check for the optional where keyword and if it exists then check for the conditions after odds are im blowing this out of proportion but im thinking in terms of "how do you make this from scratch"
ἔρως
ἔρως4mo ago
im thinking of "i want to use this thing that md wrote. wth do i need to do to get my data?"
ZomaTheMasterOfDisaster
at this point idk i there's if there's an easier way I dont see it
ἔρως
ἔρως4mo ago
there's no easier or harder way there's what you want
ZomaTheMasterOfDisaster
well do you see an easy solution to this? it feels like im basically recreating the SELECT method from scratch which feels a bit too much for this scale of project
ἔρως
ἔρως4mo ago
you're creating something, and im not sure what
ZomaTheMasterOfDisaster
idk either might just quit
ἔρως
ἔρως4mo ago
or just think about it do you want to write the queries manually all the time?
ZomaTheMasterOfDisaster
not really but people can feed you the wrong info and cause trouble
ἔρως
ἔρως4mo ago
how about you take the existing function and change it to take the name of the table and a list of columns?
ZomaTheMasterOfDisaster
ok?
protected function select(string|array $table)
{
if (empty($table)) {
throw new ValueError("Select statement must not be empty");
}

if (is_string($table)) {
$sql = "SELECT * FROM {$table}";
} else {

}

$stmt = self::$pdo->prepare($sql);
$stmt->execute();
while ($row = $stmt->fetch()) {
yield $row;
}
}
protected function select(string|array $table)
{
if (empty($table)) {
throw new ValueError("Select statement must not be empty");
}

if (is_string($table)) {
$sql = "SELECT * FROM {$table}";
} else {

}

$stmt = self::$pdo->prepare($sql);
$stmt->execute();
while ($row = $stmt->fetch()) {
yield $row;
}
}
how does this work exactly
ἔρως
ἔρως4mo ago
$sql->select('users') that's it
ZomaTheMasterOfDisaster
no way
ἔρως
ἔρως4mo ago
that's what you currently have
ZomaTheMasterOfDisaster
protected function select(string|array $table)
{
if (empty($table)) {
throw new ValueError("Select statement must not be empty");
}

if (is_string($table)) {
$sql = "SELECT * FROM {$table}";
} else {
$sql->select('users');
}

$stmt = self::$pdo->prepare($sql);
$stmt->execute();
while ($row = $stmt->fetch()) {
yield $row;
}
}
protected function select(string|array $table)
{
if (empty($table)) {
throw new ValueError("Select statement must not be empty");
}

if (is_string($table)) {
$sql = "SELECT * FROM {$table}";
} else {
$sql->select('users');
}

$stmt = self::$pdo->prepare($sql);
$stmt->execute();
while ($row = $stmt->fetch()) {
yield $row;
}
}
ἔρως
ἔρως4mo ago
no! that's what you use to run that function
ZomaTheMasterOfDisaster
sorry epic im just not following on this problem can you explain what im not seeing i feel im doing way too much and this is just a todo app not a SQL ORM let's break the problem down
ἔρως
ἔρως4mo ago
if (is_string($table)) {
$sql = "SELECT * FROM {$table}";
} else {
$sql->select('users');
}
if (is_string($table)) {
$sql = "SELECT * FROM {$table}";
} else {
$sql->select('users');
}
you don't need the if if you only receive a string from this and the columns are the next argument
ZomaTheMasterOfDisaster
ok now we have this
protected function select(string|array $table)
{
if (empty($table)) {
throw new ValueError("Select statement must not be empty");
}

$sql = "SELECT * FROM {$table}";
$sql->select('users');

$stmt = self::$pdo->prepare($sql);
$stmt->execute();
while ($row = $stmt->fetch()) {
yield $row;
}
}
protected function select(string|array $table)
{
if (empty($table)) {
throw new ValueError("Select statement must not be empty");
}

$sql = "SELECT * FROM {$table}";
$sql->select('users');

$stmt = self::$pdo->prepare($sql);
$stmt->execute();
while ($row = $stmt->fetch()) {
yield $row;
}
}
ἔρως
ἔρως4mo ago
$sql = "SELECT * FROM {$table}"; <-- just this
ZomaTheMasterOfDisaster
ok got it
ἔρως
ἔρως4mo ago
now, the columns
ZomaTheMasterOfDisaster
so we would use a loop to check the columns til you hit the word FROM?
ἔρως
ἔρως4mo ago
no! you take an array with the name of the columns
ZomaTheMasterOfDisaster
how would you do that?
ἔρως
ἔρως4mo ago
an implode
ZomaTheMasterOfDisaster
so $columnNames = implode(" ", $table); ?
ἔρως
ἔρως4mo ago
it has to be proper sql
ZomaTheMasterOfDisaster
so just comma?
ἔρως
ἔρως4mo ago
comma and backticks
ZomaTheMasterOfDisaster
backticks surrounding the comma? wait
$columnNames = implode("``,", $table);
$columnNames = implode("``,", $table);
ἔρως
ἔρως4mo ago
no, the backticks have to be around the column names
ZomaTheMasterOfDisaster
$columnNames = implode("``", $table);
$columnNames = implode("``", $table);
at least that does this
SELECT``description``FROM``tasks``WHERE``userid``=``2``;
SELECT``description``FROM``tasks``WHERE``userid``=``2``;
ἔρως
ἔρως4mo ago
backtick, comma, backtick
ZomaTheMasterOfDisaster
got it
SELECT`,`description`,`FROM`,`tasks`,`WHERE`,`userid`,`=`,`2`,`;
SELECT`,`description`,`FROM`,`tasks`,`WHERE`,`userid`,`=`,`2`,`;
example of what it produces using $columnNames = implode(",", $table);
ἔρως
ἔρως4mo ago
almost there
ZomaTheMasterOfDisaster
what's next yes backticks are there just discord problem
ἔρως
ἔρως4mo ago
next, you need to implement that into the function
ZomaTheMasterOfDisaster
implement what? removing things and formatting it? friend wants to game may have to do this tomorrow
ἔρως
ἔρως4mo ago
receiving the columns
ZomaTheMasterOfDisaster
What if I just do something like this
public function query($sql, $params=[]) {
$stmt = self::$pdo->prepare($sql);
$stmt->execute($params);
return $stmt;
}
public function query($sql, $params=[]) {
$stmt = self::$pdo->prepare($sql);
$stmt->execute($params);
return $stmt;
}
Make a generic setup then have the other specific ones call on it i came up with this on my own
protected function select($columns, $table, $optionalWhere="", $optionalWhereClause="", $params=[]) {
$sql = "SELECT {$columns} FROM {$table}";
if($optionalWhere == "WHERE") {
$sql = $sql . $optionalWhere . $optionalWhereClause;
}

$stmt = self::$pdo->prepare($sql);
if(empty($params)) {
$stmt->execute();
} else {
$stmt->execute($params);
}

while($row = $stmt->fetch()) {
yield $row;
}
}
protected function select($columns, $table, $optionalWhere="", $optionalWhereClause="", $params=[]) {
$sql = "SELECT {$columns} FROM {$table}";
if($optionalWhere == "WHERE") {
$sql = $sql . $optionalWhere . $optionalWhereClause;
}

$stmt = self::$pdo->prepare($sql);
if(empty($params)) {
$stmt->execute();
} else {
$stmt->execute($params);
}

while($row = $stmt->fetch()) {
yield $row;
}
}
here's all ive done so far
public function query($sql, $params=[]) {
$stmt = self::$pdo->prepare($sql);
$stmt->execute($params);
return $stmt;
}

protected function selectAll($table, $params=[]) {
$sql = "SELECT * FROM `{$table}`";
$stmt = $this->query($sql, $params);

while($row = $stmt->fetch()) {
yield $row;
}
}
public function query($sql, $params=[]) {
$stmt = self::$pdo->prepare($sql);
$stmt->execute($params);
return $stmt;
}

protected function selectAll($table, $params=[]) {
$sql = "SELECT * FROM `{$table}`";
$stmt = $this->query($sql, $params);

while($row = $stmt->fetch()) {
yield $row;
}
}
protected function update($columnsAndValues, $table, $condition, $params) {
$sql = "UPDATE `{$table}` SET `{$columnsAndValues}` WHERE `{$condition}`;";

$stmt = self::$pdo->prepare($sql);

$stmt->bindParam($params);

if($stmt->execute()) {
echo "{$table} is successfully updated!";
} else {
throw new Exception("Failed to update {$table}");
}
}

protected function delete($table, $condition, $params) {
$sql = "DELETE FROM {$table} WHERE {$condition}";
$stmt = self::$pdo->prepare($sql);
$stmt->bindParam($params);

if($stmt->execute()) {
echo "record(s) was deleted successfully";
} else {
throw new Exception("Record(s) has failed to delete");
}
}
protected function update($columnsAndValues, $table, $condition, $params) {
$sql = "UPDATE `{$table}` SET `{$columnsAndValues}` WHERE `{$condition}`;";

$stmt = self::$pdo->prepare($sql);

$stmt->bindParam($params);

if($stmt->execute()) {
echo "{$table} is successfully updated!";
} else {
throw new Exception("Failed to update {$table}");
}
}

protected function delete($table, $condition, $params) {
$sql = "DELETE FROM {$table} WHERE {$condition}";
$stmt = self::$pdo->prepare($sql);
$stmt->bindParam($params);

if($stmt->execute()) {
echo "record(s) was deleted successfully";
} else {
throw new Exception("Record(s) has failed to delete");
}
}
ἔρως
ἔρως4mo ago
as long as it works for you, but $optionalWhere="", in the select is absolutely useless
ZomaTheMasterOfDisaster
Right now setting up for testing isn't working I may have to build a router
ἔρως
ἔρως4mo ago
you do need one
ZomaTheMasterOfDisaster
Whenever I run it nothing happens I even tried running a smaller scale todo app and all that happens is phpinfo displays in my console
ἔρως
ἔρως4mo ago
because you need a router
ZomaTheMasterOfDisaster
I'll check Google
ἔρως
ἔρως4mo ago
if you want to use an already built one, you can use klein but there's more modern ones in packagist
ἔρως
ἔρως4mo ago
it makes things a lot easier
ZomaTheMasterOfDisaster
what's a good setup for apache to use php?
ἔρως
ἔρως4mo ago
linux - any linux
ZomaTheMasterOfDisaster
well yes 🙂 but configuration side for it to work
ἔρως
ἔρως4mo ago
the defauls work perfectly fine
ZomaTheMasterOfDisaster
creating a virtual host is one thing i know of well see on nix I have to setup the config for it to work likewise docker
ἔρως
ἔρως4mo ago
yeah, that's something i don't know how to help you wish i usually install debian, apache and php then it's ready
ZomaTheMasterOfDisaster
yeah sadly i dont have that option
ἔρως
ἔρως4mo ago
it's the easiest you can try docker and just use the bitnami image
ZomaTheMasterOfDisaster
bitnami? the vmware images
ἔρως
ἔρως4mo ago
no, the docker images
ZomaTheMasterOfDisaster
yeah which ones?
ἔρως
ἔρως4mo ago
there's php, apache and mariadb
ZomaTheMasterOfDisaster
ok so bitnami php, and apache for my project wait they use fpm php so apache doesnt
ἔρως
ἔρως4mo ago
apache can use fpm or modphp
ZomaTheMasterOfDisaster
oh cool
ἔρως
ἔρως4mo ago
i prefer modphp because it's easier
ZomaTheMasterOfDisaster
Modphp
ἔρως
ἔρως4mo ago
yes, it's a module for apache that runs php for you
ZomaTheMasterOfDisaster
gonna try getting apache working first so i can see it working then going move back to main todo app I GOT IT TO WORK!!!! apache is working!
ZomaTheMasterOfDisaster
test 1 worked and now we got the first error Fatal error: Uncaught Error: Class "MD\controller\TodoController" not found in /var/www/html/app/view/todos/index.php:5 Stack trace: #0 {main} thrown in /var/www/html/app/view/todos/index.php on line 5 so does namespaces only work with the composer autloader? @ἔρως I noticed that namespaces can be used with importing but it doesn't seem very concrete issues with "finding files" come up often guessing the layers to it aren't very big so mainly stuff in same folder