DEV Community

loading...

Laravel validation rules — file exists, MAC address & equals value.

mattkingshott profile image Matt Kingshott 👨🏻‍💻 Originally published at itnext.io on ・4 min read

Image courtesy of Unsplash

Laravel validation rules — File exists, MAC addresses & is equal to a value

In this new series, we’ll be exploring the concept of custom validation rules in Laravel and how they can assist you. I’m posting an article each day with a new rule you can use in your projects. The rules are also part of a package.

In this post, we’ll be creating a rule which confirms a user has specified a path to a file that exists, a rule to confirm that a supplied MAC address is valid, and we’ll look at a rule that verifies the user has supplied an accepted value.

If you’re new to this topic, check out the first article in the series.

Promotion

I’ve recently released Pulse — a friendly, affordable server and site monitoring service designed specifically for developers. It includes all the usual hardware monitors, custom service monitors, alerting via various notification channels, logs, as well as full API support. Take a look… https://pulse.alphametric.co

Server and Site Monitoring with Pulse

Rule #1 — Mac Addresses

Let’s begin by writing the logic necessary to ensure that the user has provided a valid MAC address. Per the conventions, the following must be true:

  1. Six octets (upper or lowercase) must be provided.
  2. An octet must consist of either a numeric digit or an A-F letter.
  3. Each octet must be separated by colons or dashes.

The easiest way to enforce these requirements is with a regular expression:

public function passes($attribute, $value)
{
    return preg\_match(
        "/^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/", $value
    );
}
Enter fullscreen mode Exit fullscreen mode

Next, we’ll need to write an error message to respond with when the user has supplied a value which is not a valid MAC address:

public function message()
{
    return 'The :attribute must be a valid MAC address;
}
Enter fullscreen mode Exit fullscreen mode

As before, we’ll write a quick unit test to confirm that the rule works correctly and rejects values that are not MAC addresses:

/\*\* @test \*/
public function the\_mac\_address\_rule\_can\_be\_validated()
{
    $rule = ['address' => [new MacAddress]];

    $this->assertTrue(validator(['address' => '3D:F2:C9:A6:B3:4F'], $rule)->passes());

    $this->assertTrue(validator(['address' => '3D-F2-C9-A6-B3-4F'], $rule)->passes());

    $this->assertFalse(validator(['address' => '00:00:00:00:00:00:00'], $rule)->passes());
}
Enter fullscreen mode Exit fullscreen mode

Rule #2 — File Exists

Next, we’ll allow a user to supply a path to a file and verify that the file does indeed exist. To do this, we’ll need to accept two parameters:

  1. The disk the file should exist on. This disk should be configured using the filesystems.php file in your application configuration.
  2. The path to the file itself.

We’ll then make use of the Storage facade to perform the check, while also performing some initial sanitisation of the user input to eliminate any extra slashes in the file path:

public function passes($attribute, $value)
{
    $path = rtrim($this->parameters[1] ?? '', '/');
    $file = ltrim($value, '/');

    return Storage::disk($this->parameters[0])
                  ->exists("$path/$file");
}
Enter fullscreen mode Exit fullscreen mode

As before, we’ll need to write an error message to respond with:

public function message()
{
    return 'The file specified for :attribute does not exist';
}
Enter fullscreen mode Exit fullscreen mode

And finally, include a unit test:

/\*\* @test \*/
public function the\_file\_exists\_rule\_can\_be\_validated()
{
    $rule = ['file' => [new FileExists('local', '/')]];

    $this->assertTrue(validator(['file' => 'real.txt'], $rule)->passes());

    $this->assertFalse(validator(['file' => 'fake.txt'], $rule)->passes());
}
Enter fullscreen mode Exit fullscreen mode

Note that the actual unit test is more involved as steps have to be taken to set the configuration, create test files etc. See the class within the package.

Rule #3 — Equals

This last rule is more of an example of “semantic sugar”. Technically, you can achieve the same result using Laravel’s native in rule and supplying a single value instead of many comma-separated options.

However, the word “in” implies that multiple values are valid, while perhaps only one value is truly valid given a particular scenario. In this situation, I think using “equals” is more semantically correct / easier to understand.

As you would imagine, the logic is simple. We have a single parameter that we compare to the supplied value and ensure it is the same:

public function passes($attribute, $value)
{
    return $value === $this->parameters[0];
}
Enter fullscreen mode Exit fullscreen mode

We’ll also include the error response:

public function message()
{
    return 'The :attribute must be set to "' . 
           $this->parameters[0] . '"'
}
Enter fullscreen mode Exit fullscreen mode

And the unit test:

/\*\* @test \*/
public function the\_equals\_rule\_can\_be\_validated()
{
    $rule = ['value' => [new Equals('2')]];

    $this->assertFalse(validator(['value' => '0'], $rule)->passes());

    $this->assertFalse(validator(['value' => '1'], $rule)->passes());

    $this->assertTrue(validator(['value' => '2'], $rule)->passes());
}
Enter fullscreen mode Exit fullscreen mode

Wrapping Up

You can see the classes and pull them into your projects by visiting the repo on Github: https://github.com/alphametric/laravel-validation-rules

I have additional validation rules that I intend to share with you in the coming days, so be sure to follow me for those articles. If you’re interested, you can also follow me on Twitter to see everything I’m up to.

Happy coding!


Discussion (0)

pic
Editor guide