Creating an Adapter for Laravel Filesystem

I recently was using the Laravel Filesystem to connect to an FTP server and move/copy/download files but ran into an error related to the PHP function ftp_chmod.

After a bit of research it looked like this issue on the thephpleague/flysystem project (Which the Laravel Filesystem abstracts) was exactly what I was encountering.

The error was similar and I also determined that the FTP site I was connecting to was a Windows system.

Overall it looks like the problem is when writing a file it is also trying to set the permissions. But this Windows FTP server does not support this or had troubles doing so.

The solution I went with was to create a new FTP Adapter for the Laravel Filesystem that just overrode the one method that tries to set the permissions so that it doesn't.

Credit to this thead on Laracasts.com that got me there.

Step 01 - Make your own adapter

I created an adapter called WindowsFtp that overrides the setVisibility() method so that it actually does NOT set the visibility. This is what was causing the problem:

<?php

namespace App\Adapter;

use League\Flysystem\Adapter\Ftp as LeagueFtp;  
use League\Flysystem\AdapterInterface;

class WindowsFtp extends LeagueFtp  
{
    public function setVisibility($path, $visibility)
    {
        $visibility === AdapterInterface::VISIBILITY_PUBLIC ? $this->getPermPublic() : $this->getPermPrivate();

        return compact('visibility');
    }
}

Step 02 - Extend the FilesystemManager

We want to be able to use our new WindowsFTP driver instead of the default FTP driver so to do that we extend the Illuminate\Filesystem\FilesystemManager class and override the createFtpDriver() method to return an instance of our the new WindowsFtp adapter:

<?php

namespace App\Filesystem;

use Illuminate\Support\Arr;  
use Illuminate\Filesystem\FilesystemManager as BaseManager;  
use App\Adapter\WindowsFtp;

class FilesystemManager extends BaseManager  
{
    public function createFtpDriver(array $config)
    {
        $ftpConfig = Arr::only($config, [
            'host', 'username', 'password', 'port', 'root', 'passive', 'ssl', 'timeout',
        ]);

        return $this->adapt($this->createFlysystem(
            new WindowsFtp($ftpConfig),
            $config
        ));
    }
}

Step 03 - Extend the Service Provider

We have the new Adapter created and setup the FilesystemManager to create it. Now we just need to tell our app to use our custom FilesystemManager instead of the default one.

<?php

namespace App\Filesystem;

use App\Filesystem\FilesystemManager;  
use Illuminate\Filesystem\FilesystemServiceProvider as BaseFilesystemServiceProvider;

class FilesystemServiceProvider extends BaseFilesystemServiceProvider  
{
    protected function registerManager()
    {
        $this->app->singleton('filesystem', function () {
            return new FilesystemManager($this->app);
        });
    }
}

Step 04 - Register the Service Provider

Last step is to tell Laravel to use our custom FilesystemServiceProvider instead of the default. To do this edit the config/app.php file, look for this line within the providers array:

Illuminate\Filesystem\FilesystemServiceProvider::class,  

and replace with:

App\Filesystem\FilesystemServiceProvider::class,  

Now your custom Adapter will be used.

Detect @todo statements with PHPCS

When your code is pushed to production you likely don't want to have any outstanding @todo statements leftover:

// @todo Make sure you remove the following before pushing to producton.

One way to do this is using PHP Code Sniffer.

Install PHPCS

Add as a dependency to your composer file:

{
    "require-dev": {
        "squizlabs/php_codesniffer": "2.*"
    }
}

Then run a composer install.

Make a config file to check for @todo

Name it something like phpcstodo.xml and add the following:

<?xml version="1.0"?>  
    <ruleset name="MyStandard">  
    <description>My custom coding standard.</description>
    <rule ref="Generic.Commenting.Todo"/>
    <rule ref="Generic.Commenting.Todo.CommentFound">
        <message>@todo comment found</message>
    </rule>
</ruleset>  

Then run PHPCS (where 'src' represents the folder with your PHP files):

vendor/bin/phpcs src --standard=phpcstodo.xml  

If any of your files have a @todo in them, they will show up like this:

----------------------------------------------------------------------
FOUND 0 ERRORS AND 1 WARNING AFFECTING 1 LINE  
----------------------------------------------------------------------
 65 | WARNING | @todo comment found
----------------------------------------------------------------------

More Info

GitHub Page
Official Page
https://pear.php.net/manual/en/package.php.php-codesniffer.annotated-ruleset.php

Arguments against the Ternary Operator (in PHP)

What is the Ternary Operator?

If you aren't familiar with the ternary operator, it's basically a shorthand way of writing an if-else statement.

If you have an if-else statement like this:

$age = 35;
if ($age > 30) {  
   $canBeTrusted = false;
} else {
   $canBeTrusted = true;
}

You can condense it into a ternary operator:

$age = 35;
$canBeTrusted = ($age > 30 ? false : true);

Why to not use them

The main reason I don't like to use ternary operators is because when I run into one it takes an extra processing in my head to remember what they do.

When I see this:

($age > 30 ? false : true);

The thought process in my head goes something like:

  • OK here we have a ternary operator.
  • Is it the first argument that is returned if the condition is true or is it the second? Right, it's the first.

That might notseem like much, but when you're coding and having to remember many other things it can add up. It's unnecessary.

On the other hand when I see an if-else statement:

if ($age > 30) {  
   $canBeTrusted = false;
} else {
   $canBeTrusted = true;
}

I can glance at it and right away understand. It's much more readable. It flows nicely with the rest of my code which is in a similar structure. It's consistent with the rest of the code.

This situation can be amplified if it's the end of the day or you're working on a difficult problem or bug. Running into a ternary operator is going to force you to do more mental work which could lead to more bugs, a poor solution etc...

Other reasons to avoid

Debugging

It makes debugging difficult. You can't place a breakpoint or dump a variable from within a ternary. You'll have to extract it out to an if-else anyway.

Readability

I mentioned this before but readability is very important. It's much better to have more lines of code, be more explicit and have a better readability than it is to condense your code and use up fewer lines.

Think of the next developer to come along and run into your code. The readability of your code is very important. The developer should be able to read through it like paragraphs in a book and be able to understand what is happening.

Why are they used?

There might have been a time when you needed to fit your program within the available memory and using ternary operators was a way to save on space. That still might be the case currently in some situations but I can't see that being a situation when programming for the web with PHP which I mostly do.

I have a theory that some people use the ternary and feel like they are being very clever by using up fewer lines. Might give them a sense of superiority. Of course I'm not talking about everyone who uses them but I'm sure there are these types out there.

(From http://stackoverflow.com/a/535122/460075 )

These might be the same people who will argue against the opinions in this post saying that I might not like them because I don't understand them or am not clever enough to work with them.

Programming can be difficult and especially when you're working with an unfamiliar code base. so why make our jobs more difficult than they need to be.

Conclusion

I have used ternary operators in the past but I do try and avoid them as much as possible. As with most things in programming avoiding ternary operators is more of a guideline I follow than a rule.

Your thoughts?

Do you agree? Disagree? Am I missing out on any other scenarios where the ternary can come in handy? Any other arguments against it? Discuss below!

Sudo !!

Have you ever executed a command and then realise right after that you need super user privelages in order to execute it?

You type the command:

./myscript

Then need to enter it again:

sudo ./myscript  

Well instead of retyping it you can just enter:

sudo !!  

Which will run the previously like as super user.

From the Bash Reference Manual:

!!
Refer to the previous command. This is a synonym for ‘!-1’.  

Bang bang!!