Ad

How Can I Rewrite This Such That It Doesn't Need A Return Statement Out Side The Foreach

- 1 answer

So for testing purposes this method, which uses laravel relations will never reach the return statement out side the foreach loop. How do I know? Because the fieldName exists on one of these form fields, I just don't know which one, hence the for loop.

Consider the following method:

protected function fetchFieldLabel(string $fieldName) {
    foreach ($this->forms as $form) {
        $foundField = $form->fields->where('name', '=', $fieldName)->first();

        if (!is_null($foundField)) {
            return $foundField->label;
        }
    }

    return null;
}

I should not need the return null at the end of the method, if I remove it, my code coverage is not 100% on this method, so I am looking for a better way to return the $foundField->label with out a for loop as the code coverage will always hit this return statement (eventually) and it will never leave the foreach loop.

For context:

enter image description here

I have been looking at filter but I am unsure how to use it in this context.

When I write something like:

    $this->forms->filter(function($form) use($fieldName) {
        return $form->fields->where('name', $fieldName);
    })->first();

I get the whole form object, all its fields and all their dependencies.

For reference:

  • Form has many fields, field belongs to form.

Any thoughts on how I could write this such that I get 100% code coverage and not have a "never reached return null"

PS: All I want is to find the field (in the collection of forms) which $fieldName belongs to and return the label of that field.

PS2: There is no test I could write where it would return the null, because the field name in this case will ALWAYS exist on the collection of forms fields. Again, we just don't know which one it exists on.

Ad

Answer

The simple way would be using a break instead of the return.

protected function fetchFieldLabel(string $fieldName) {
    $label = null;

    foreach ($this->forms as $form) {
        $foundField = $form->fields->where('name', '=', $fieldName)->first();

        if (! is_null($foundField)) {
            $label = $foundField->label;
            break;
        }
    }

    return $label;
}

Otherwise you could use the Collection directly like this:

protected function fetchFieldLabel(string $fieldName) {
    return optional($this->forms->map(function ($form) use ($fieldName) {
        return $form->fields->firstWhere('name', $fieldName);
    })->filter()->first())->label;
}

So basically, you map the form into the field that matches the $fieldName, which would return null if the form doesn't have a field. Then filter to remove out those that doesn't pass the truth value test. And then chaining first to retrieve the first field. Finally label to get the label of the field.

You could also wrap everything in the optional helper to make sure the label never throws an error if no field is found even though you said that should never happen.

Ad
source: stackoverflow.com
Ad