I want to check if The string has 16 characters, contains digits, contains letters, and does not have any special characters. I already did it on javascript but users still cheating and some are adding < script > tags in the user input, so I need to convert it to PHP for server-side verification. But I am very confused, I am new to PHP regex, What is wrong with my code? How to combine all of these regexes into one line as I am very confused about too many AND Logical operators, Thanks:
<?php
function create($referrer=null){
if(strlen($referrer) == 16 and (!empty(preg_match('/\d /g', $referrer))) and (!empty(preg_match('/[a-zA-Z]/g', $referrer)) and empty(preg_match('/[!@#$%^&*()_ \-=\[\]{};\':"\\|,.<>\/?] /', $referrer)))){
echo 'The string has 16 characters, contains digits, contains letters, and does not have any special characters.';
}
}
create("kdsygdbg7j6f5ps2");
?>
CodePudding user response:
You could use one regex for this
But for the sake of the explanation I have explained it with the example below.
One regex:
var_dump(preg_match('/^[a-zA-Z0-9]{16}$/', 'oaiwejfio12321wejfewiojiowea')); //0, too long
var_dump(preg_match('/^[a-zA-Z0-9]{16}$/', '**(#&($#@')); //0, invalid chars
var_dump(preg_match('/^[a-zA-Z0-9]{16}$/', '1234567891234567')); //1, correct
Preg_match
The following information is useful to know about preg_match:
preg_match() returns 1 if the
pattern
matches givensubject
, 0 if it does not, orfalse
on failure.
Your usage of !empty
You use !empty in your code, this makes it a bit unreadable. preg_match returns 1 or 0, so it is better to compare it to those values. But !empty can actually work, please look at the following results:
var_dump(!empty(1)); //true
var_dump(!empty(0)); //false
Regex with preg_match explanation
1. !empty(preg_match('/\d /g', $referrer))
I have replaced this with the following: preg_match('/[0-9]/', $referrer) === 1
, since g is an unknown modifier. Have a look at the class ShouldContainDigits
in the code example at the bottom.
2. empty(preg_match('/[a-zA-Z]/g', $referrer))
I have replaced this with the following: preg_match('/[a-zA-Z]/', $value) === 1
, since g is an unknown modifier. Have a look at the class ShouldContainLetters
in the code example at the bottom.
3. empty(preg_match('/[!@#$%^&*()_ \-=\[\]{};\':"\\|,.<>\/?] /', $referrer))
I have replaced this with the following: (preg_match('/[!@#$%^&*()_ \-=\[\]{};\':"\\|,.<>\/?] /', $referrer) === 0)
. Have a look at the class ShouldNotContainSpecialChars
in the code example at the bottom.
Complete code example
I have refactored the example to make it more clear what each regex should be doing. Add the following code to test.php
and run php test.php
:
<?php
final class Result
{
private $errors = [];
public function __construct() {}
public function withError(string $error) : Result
{
$result = clone $this;
$result->errors[] = $error;
return $result;
}
public function getErrors() : array
{
return $this->errors;
}
public function isValid() : bool
{
return empty($this->errors);
}
}
interface ValidatorStrategy
{
public function isValid(string $value) : bool;
public function getError() : string;
}
final class ShouldBe16CharsInLength implements ValidatorStrategy
{
public function isValid(string $value) : bool
{
return strlen($value) === 16;
}
public function getError() : string
{
return "The string does not have 16 chars";
}
}
final class ShouldContainDigits implements ValidatorStrategy
{
public function isValid(string $value) : bool
{
return preg_match('/[0-9]/', $value) === 1;
}
public function getError() : string
{
return "The string does not contain digits";
}
}
final class ShouldContainLetters implements ValidatorStrategy
{
public function isValid(string $value) : bool
{
return preg_match('/[a-zA-Z]/', $value) === 1;
}
public function getError() : string
{
return "The string does not contain letters";
}
}
final class ShouldNotContainSpecialChars implements ValidatorStrategy
{
public function isValid(string $value) : bool
{
return (preg_match('/[!@#$%^&*()_ \-=\[\]{};\':"\\|,.<>\/?] /', $value) === 0);
}
public function getError() : string
{
return "The string does contain special chars";
}
}
final class Validator
{
private $strategies;
public function __construct(array $strategies)
{
$this->strategies = $strategies;
}
public function validate(string $value) : Result
{
$result = new Result();
foreach($this->strategies as $strategy) {
if(!$strategy->isValid($value)) {
$result = $result->withError($strategy->getError());
}
}
return $result;
}
}
$validator = new Validator([
new ShouldBe16CharsInLength(),
new ShouldContainDigits(),
new ShouldContainLetters(),
new ShouldNotContainSpecialChars()
]);
/**
* Test with string kdsygdbg7j6f5ps2
* array(2) {
["errors"]=>
array(0) {
}
["isValid"]=>
bool(true)
}
*/
$result = $validator->validate("kdsygdbg7j6f5ps2");
var_dump(['errors'=>$result->getErrors(), 'isValid'=>$result->isValid()]);
#
/**
* Test with string &(*&@(
* Result: array(2) {
["errors"]=>
array(4) {
[0]=>
string(33) "The string does not have 16 chars"
[1]=>
string(34) "The string does not contain digits"
[2]=>
string(35) "The string does not contain letters"
[3]=>
string(37) "The string does contain special chars"
}
["isValid"]=>
bool(false)
}
*/
$result = $validator->validate("&(*&@(");
var_dump(['errors'=>$result->getErrors(), 'isValid'=>$result->isValid()]);
Your code
I have changed your code to:
function create($referrer=null){
if(preg_match('/^[a-zA-Z0-9]{16}$/', $referrer) === 1){
echo $referrer . ': The string has 16 characters, contains digits, contains letters, and does not have any special characters.';
}
}
Test:
create("kdsygdbg7j6f5ps2"); //kdsygdbg7j6f5ps2: The string has 16 characters, contains digits, contains letters, and does not have any special characters.
create("&(*&@("); //... nothing
CodePudding user response:
The RegEx you are looking for is ^[[:alnum:]]{16}$
that is using:
^
beginning of the string[:alnum:]
is equivalent to a-zA-Z0-9{16}
matches exactly 16 characters$
end of the string
Here is the code with sample testing strings:
<?php
function create($referrer=null){
if((!empty(preg_match('/^[[:alnum:]]{16}$/', $referrer)))){
echo PHP_EOL.'The string '.$referrer .' has 16 characters, contains digits, contains letters, and does not have any special characters.';
}
else{
echo PHP_EOL.'The string '. $referrer .' does not match criteria.';
}
}
$array = [
'a1b2c3D4E5F6G7H8'
,'a1btooshort'
,'a1b2c3D4E5F6G7H8toolong'
,'!@#$%^&*()_ -=['
,']{};\':"\|,.<>/?'
,"a1b2c3D4\nE5F67H8"
];
foreach ($array as $key => $value) {
create($value);
}
CodePudding user response:
You can try with preg_match
I did and it worked for me.
function create($referrer=null){
$uppercase = preg_match('@[A-Z]@', $referrer);
$lowercase = preg_match('@[a-z]@', $referrer);
$number = preg_match('@[0-9]@', $referrer);
if (!$uppercase) {
echo 'Please input atleast one uppercase letter. Try again';
} elseif (!$lowercase) {
echo 'Please input atleast one lower case letter. Try again';
} elseif (!$number) {
echo 'Please input atleast one number. Try again';
} elseif (strlen($newpassword) < 8) {
echo 'Your password must be not less than 8 characters. Try again';
}
}