validation of superglobal

Asked

Viewed 107 times

2

I am developing a class to assist multiple upload using the codeigniter and I decided to analyze my code using some online tools.

One of them was the code Climate; I noticed that when checking reports for code improvement it informs that it is not recommended to use superglobals such as $_FILES even in specific functions for validation such as;

public function hasFile($key)
{
   if (!isset($_FILES[$key]) {
       throw new Exception("Não existe o indice $key", 1);
   }
   return TRUE;
}

I tried to modify this by creating an attribute called key

public $key = 'userFile';

And call you within the duties

if (!isset($_FILES[$this->key]) {.....

But I keep getting the report that this is not a good practice! I also looked in the PHP documentation if there is any type of filter for superglobal $_FILES using the function filter_input and I haven’t found.

What would be the best way to validate the superglobal $_FILES?

print of the report;

screenshot code climate

In the function in question I do not attribute the super-global to any variable, I only perform the validation as shown above.

  • 1

    @Jorgeb. is not a duplicate, because the context is different, I’m not questioning the use of isset or filter_input is a method to validate the superglobal $_FILES which in turn does not have a filter_input.

  • You’re absolutely right. I forgot it doesn’t work for $_FILES.

  • @rray added.

  • It is the Codeclimate that sends the warning?

  • @Guillhermenascimento yes.

  • I talked to the bigown and Wallace in the chat today, I think "good practice" is not "rule", it’s more like "tip". Of course this is my opinion :)

Show 2 more comments

3 answers

3

Looking closely at the question, it seems you want to use a class to apply upload operations.

I would recommend you in such cases really not use the $_FILES within the class. Also because, to that end, there would be no need for the methods to be dynamic, but rather static.

A good example I always like to use is the Symfony, that in their source codes, the class Request, Response or UploadedFile, are only entities that aim to process the data, regardless of the way they come - which in your case would be through the variable $_FILES.

What Symfony actually does is to create a static method that initializes a new instance, based on global elements. So yes, I think there’s something more organized, and not dependent on just having uploads coming from $_FILES - you could add file_get_contents('php://input') for example.

So in this context, I suggest creating the following static method for creating the instance:

class Upload
{
    protected $files = [];

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

    public function hasFile($key)
    {
        return isset($this->files[$key]);
    }

    public function getFile($key)
    {
        if ($this->hasFile($key)) {
            return $this->files[$key];
        }

        throw new Exception("Não existe o arquivo $key");
    }


    public static function createFromFilesGlobal()
    {
        return new static($_FILES);
    }
}

So the use would be:

 $files = Upload::createFromFilesGlobals();


 $files->getFile('key');

Note that, in this case, the createFromFilesGlobals is a static method - the opposite of dynamic. This method, aims to only return new static, passing as parameter the global variable $_FILES. This will cause an instance of Upload is returned with the property $files filled with the values of $_FILES.

Now, imagine if you want to use that same class to capture some sort of request that didn’t perhaps go through $_FILES PHP. What would be the solution?

Fictitious example:

 // essa função não existe no PHP, é só um exemplo
 $raw_files = parse_uploaded_files_from_php_raw_input('php://input'); 

 $files = new Upload($raw_files);

So, this way, you have a class that is not limited by a super global PHP variable, but only uses its values (or not), if necessary.

  • I didn’t quite understand the use of this new static().

  • 2

    @Rafaelacioly it creates an instance of the class itself, which will return itself by passing $_FILES by parameter. Thus, you do not use the $_FILES within the class, but only its data. It is a default used to initialize the class from Super Global values, which is different from the "depend" class of $_FILES.

1

In programming, in part of time (ideally) you should not treat or change external elements within a function, that is to say function or method should not be able to be passed as argument or that belongs to the class.

This 'rule' is more or less as your mother said it does not accept anything from strangers, it includes variables or objects :P.

Remember that this rule can change as the language can be more or less rigid, take for example javascript, a function does not access N external elements?

I believe the solution to remove this Warning is to pass $_FILES in your class constructor and always change/return that copy.

  • This is not a programming rule, it’s a language rule and it doesn’t apply to PHP. Yes, we can change the content of a variable passed as a parameter. Since version 5.3, if I am not mistaken, it is no longer necessary to pass an argument by reference in order to change it internally.

  • 1

    @Brittz a function should not change external elements to its signature because it modifies the source variable. For example in a function vc da um unset($_POST); and after the execution of the function are still made modifications in $_POST that now no longer exists a side effect has been created. With exceptions most of the time vc must pass the global elements as arguments in functions and preference by value.

  • I agree that it is bad practice to change the content of SUPER GLOBAL inside or outside methods and functions.

  • @Brittz see the question was edited :P now think q to understand my answer.

  • I agree with your answer. I just wanted to note about editing variables within methods and functions in PHP. I’m looking in the changelog for the need to pass by reference for this, because I think I made a mistake. In any case, if necessary, just set at the beginning of the function global $myvar, so you can edit the content, with external impact.

1

In the code you presented there is no bad practice.

A bad practice would be to sanitize or filter the data of the superglobal.

Example of what would be a bad practice:

$_POST['foo'] = mysql_real_escape_string($_POST['foo']);

In the case of isset(), there is no change in value. There is nothing wrong with using it this way.

if (isset($POST['foo'])) {
    // bla bla bla
}

In the examples I used $_POST, however, the same applies $_GET, $_FILES, $_SERVER, finally, the superglobal: http://php.net/manual/en/language.variables.superglobals.php

Browser other questions tagged

You are not signed in. Login or sign up in order to post.