0

I have the function/method below inside a class that I'm creating and I'm just wondering what's the best way to handle empty/null arguments.

For example, in the following example, if I wanted to just set just the category when calling the function, I would need to use:

$data = $class->get_top_headlines( null, 'technology' );

Is there any way of calling the function more efficiently? I know I could pass the arguments as an array instead, but just wondered if there's any way of doing something like:

$data = $class->get_top_headlines( $category='technology' ); and automatically leaving the other arguments as their default of null?

public function get_top_headlines( $query=null, $category=null, $country=null, $sources=null, $page_size=null, $page=null ){
    $url = $this->api_url . $this->endpoint_top_headlines;
    $params = array();
    if ( $query !== null ){
        $params['q'] = urlencode( $query );
    }
    if ( $category !== null ){
        $params['category'] = $category;
    }
    if ( $country !== null ){
        $params['country'] = $country;
    }
    if ( $sources !== null ){
        $params['sources'] = $sources;
    }
    if ( $page_size !== null ){
        $params['pageSize'] = $page_size;
    }
    if ( $page !== null ){
        $params['page'] = $page;
    }
    $params['apiKey'] = $this->api_key;

    $url_query = http_build_query( $params );
    $url = $url . '?' . $url_query;
    echo $url;
    $obj = $this->get_response( $url );
    return $obj;
}

3 Answers 3

1

Try passing an array, and then using an array_merge

$data = $class->get_top_headlines(['category' => 'technology']);

Then in your function, have an array of defaults, then do your merge.

$settings = array_merge($settings, $passedInArray);

http://php.net/manual/en/function.array-merge.php

Sign up to request clarification or add additional context in comments.

2 Comments

I did like the simplicity of this approach, but I decided to spend a little more time writing my code and ended up following the OOP approach that @Riccardo suggested as I think this will be better in the long run. However, if I could have accepted 2 answers, I would have accepted yours too!
I assumed you would be using OO! This code should go in the method!
1

I think

(null, 'technology' );

might be less actual coding but a different solution might be to use OOP. You said it's already a method of a class so you could do something like:

$obj = new thatClass;
$obj->technology = $technology;
$obj->get_top_headlines();

in the Class:

Class thatClass{
   $technology = null;
   $category = null;
   $query = null;
   //...
   public function get_top_headlines(){
    if ( $this->query !== null ){
        $params['q'] = urlencode( $this->query );
    }
    if ( $this->category !== null ){
        $params['category'] = $this->category;
    }
    if ( $this->technology !== null ){
        $params['technology'] = $this->technology;
    }
    //method code..
   }
   //class code..
}

The problem with this approach is if you need to call that same function again passing a different parameter in the same class instance, depending on your application you might need to manually set back to null the previous parameter (now an object attribute)

Comments

0

I would solve this problem by creating a new class or data structure which will encapsulate all the logic of validating and generating the URL and then use it everywhere I need it.

Here's a sample class.

class HeadLineParameters
{
    private $params = [];

    public function setQuery($query)
    {
        // validate/transform query data
        $this->params['q'] = urlencode($query);
        return $this;
    }

    public function setCategory($category)
    {
        // validate/transform category data
        $this->params['category'] = $category;
        return $this;
    }

    public function generateUrl()
    {
        return http_build_query( $this->params );
    }
}

$params = new HeadLineParameters;
$params->setQuery($query)
    ->setCategory($category);

You just pass one argument and you know that it's just an instance of HeadLineParameters.

$class->get_top_headlines($params);

This solution doesn't pollute your current class with unnecessary state or fields. It is easy to test, and it has only one job. You can extend it easily, you can set default values, you can also validate it as you like.

Edit: Why you shouldn't add more fields to your current class?

If you add more fields to your current class you'll be breaking the single responsibility principle, and any method of this class can change these fields too. It shouldn't be a problem if these fields really belong there and more methods require them. This is fine if you are using OOP.

I am not sure what other people think about passing associated arrays to functions, but they are hard to handle if you have no documentation available. I have had trouble with them when reading some external code, and most of time I wasn't sure what's the data I was dealing with.

4 Comments

Thanks for your answer but I feel it's a little bit OOP overkill and not needed.
@Mat This solution doesn't pollute your current class with unnecessary state or fields, unlike your accepted answer. You might not feel the difference today, but later any change will effect your current class, and any method of this class can change these parameters too. It shouldn't be a problem if these fields really belong there and more methods require them. I don't know your current paradigm, but this is not an overkill if you are already using OOP.
After considering this some more, I decided to go with your answer and will be incorporating the methods in your example in to my existing class.
If you could make an edit to your answer I will change my vote to an upvote for you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.