'Undefined variable in Laravel 8 project (php 7.4)

Most of the functions i the project works but when it comes to register results I’m getting an error.

This is an extensive pistol competition system where administrators can create competitions of different kinds. Shooters can register and signup for the competitions. When competitions is over the results it to be input to the system. That’s when the problem appears.

The system is upgraded from Laravel 5.3 to 8 and it works fine in 5.3. Here is a 5.3 functioning test-system: https://test.webshooter.se

Undefined variable: patrols Error:

    [2022-02-20 14:14:12] local.ERROR: Undefined variable: patrols {"userId":1,"exception":"[object] (ErrorException(code: 0): Undefined variable: patrols at /Users/ralph/laravel9/webshooter_web/app/Repositories/ResultsRepository.php:156)

Possible patrol_type: null, finals, distinguish. In this case it's type null.

This is the part of the PatrolRepository.php where the error occurs:


        public function getPatrols($competitionsId)
    {
        if (!$this->request->has('patrol_type')) :
            $patrols = Patrol::where('competitions_id', $competitionsId)->orderBy('sortorder')->get();
        elseif ($this->request->get('patrol_type') == 'finals') :
            $patrols = PatrolFinals::where('competitions_id', $competitionsId)->orderBy('sortorder')->get();
        elseif ($this->request->get('patrol_type') == 'distinguish') :
            $patrols = PatrolDistinguish::where('competitions_id', $competitionsId)->orderBy('sortorder')->get();
        endif;

        return $patrols;
    }

With this code instead it works very well:

public function getPatrols($competitionsId)
{
    if ($this->request->get('patrol_type') == 'finals'):
        return PatrolFinals::where('competitions_id', $competitionsId)->orderBy('sortorder')->get();
    endif;
    
    if ($this->request->get('patrol_type') == 'distinguish'):
        return PatrolDistinguish::where('competitions_id', $competitionsId)->orderBy('sortorder')->get();
    endif;

    return Patrol::where('competitions_id', $competitionsId)->orderBy('sortorder')->get();
}

It does not check for null, instead it checks for the other states and if not any of them it's null.

In this case patrol_type is null. The function is suppose to get info from database: table patrols. Then it creates posts in database table: result. These posts suppose to show a form where the results can be put in. But nothing shows. This is the ”filter_default.blade.php” that will show the form for the null-patrol:


    <div class="row">
    <div class="col-sm-3">
        <div class="panel panel-default">
            <div class="panel-heading">{{_('Inmatning')}}</div>
            <table class="table table-bordered">
                <tbody>
                <tr>
                    <td>{{_('Datum')}}</td>
                    <td><% competitions.competition.date %></td>
                </tr>
                <tr>
                    <td>{{_('Tävlingsgrupp')}}</td>
                    <td><% (competitions.competition.championship.name) ? competitions.competition.championship.name : '-' %></td>
                </tr>
                <tr ng-if="competitions.competitions.competitiontype">
                    <td>{{_('Tävlingstyp')}}</td>
                    <td><% competitions.competitions.competitiontype.name %></td>
                </tr>
                </tbody>
            </table>
            <div class="panel-body">
                <div class="row form-group">
                    <div class="col-lg-12">
                        <label><% competitions.competition.translations.patrols_name_singular | ucfirst %></label>
                        <select class="form-control" ng-options="patrol.sortorder as (patrol.sortorder+ ' ('+patrol.start_time_human+')') for patrol in results.patrols" ng-model="results.filter.patrol">
                            <option value=""><% competitions.competition.translations.patrols_name_singular | ucfirst %></option>
                        </select>
                    </div>
                </div>
                <div class="row form-group">
                    <div class="col-lg-6">
                        <label><% competitions.competition.translations.stations_name_singular | ucfirst %> ({{_('från')}})</label>
                        <select class="form-control" ng-options="n for n in [] | range:1:competitions.competition.stations_count+1" ng-model="results.filter.station_start">
                            <option value=""><% competitions.competition.translations.stations_name_singular | ucfirst %></option>
                        </select>
                    </div>
                    <div class="col-lg-6">
                        <label><% competitions.competition.translations.stations_name_singular | ucfirst %> ({{_('till')}})</label>
                        <select class="form-control" ng-options="n for n in [] | range:1:competitions.competition.stations_count+1" ng-model="results.filter.station_end">
                            <option value=""><% competitions.competition.translations.stations_name_singular | ucfirst %></option>
                        </select>
                    </div>
                </div>
                <div class="row form-group">
                    <div class="col-lg-6">
                        <label><% competitions.competition.translations.patrols_lane_singular | ucfirst %> ({{_('från')}})</label>
                        <select class="form-control" ng-options="n for n in [] | range:1:competitions.competition.patrol_size+1" ng-model="results.filter.lane_start">
                            <option value=""><% competitions.competition.translations.patrols_lane_singular | ucfirst %></option>
                        </select>
                    </div>
                    <div class="col-lg-6">
                        <label><% competitions.competition.translations.patrols_lane_singular | ucfirst %> ({{_('till')}})</label>
                        <select class="form-control" ng-options="n for n in [] | range:1:competitions.competition.patrol_size+1" ng-model="results.filter.lane_end">
                            <option value=""><% competitions.competition.translations.patrols_lane_singular | ucfirst %></option>
                        </select>
                    </div>
                </div>
                <div class="row form-group">
                    <div class="col-lg-12">
                        <div class="checkbox">
                            <label>
                                <input type="checkbox" ng-model="results.filter.per_shot" ng-true-value="1" ng-false-value="0"> {{_('Registrera alla skott')}}
                            </label>
                        </div>
                    </div>
                </div>
                <div class="row form-group">
                    <div class="col-lg-12">
                        <div class="checkbox">
                            <label>
                                <input type="checkbox" ng-model="results.filter.show_empty_lanes" ng-true-value="1" ng-false-value="0"> {{_('Visa tomma %s')}}
                            </label>
                        </div>
                    </div>
                </div>
                <a class="btn btn-primary" ui-sref-opts="{reload: true}" ui-sref="competitions.admin.results.registration({competitions_id: competitions.competition.id, patrol:results.filter.patrol, patrol_type:results.filter.patrol_type, station_start: results.filter.station_start, station_end: results.filter.station_end, lane_start:results.filter.lane_start, lane_end:results.filter.lane_end, show_empty_lanes:results.filter.show_empty_lanes, per_shot:results.filter.per_shot})">{{_('Visa')}}</a>
            </div>
        </div>
    </div>

    <div class="col-sm-9">
        <div ng-if="results.signups">
            <div ui-view="military" ng-if="competitions.competition.results_type == 'military'"></div>
            <div ui-view="field" ng-if="competitions.competition.results_type == 'field' || competitions.competition.results_type == 'pointfield' || competitions.competition.results_type == 'magnum'"></div>
            <div ui-view="precision" ng-if="competitions.competition.results_type == 'precision'"></div>
        </div>
    </div>
</div>

Here is the Models/Result.php:


    <?php
    namespace App\Models;
    use Illuminate\Database\Eloquent\Model;
    use Illuminate\Database\Eloquent\SoftDeletes;
    class Result extends Model
{
    use SoftDeletes;
    protected $table = 'results';
    protected $fillable = [
        'stations_id',
        'figure_hits',
        'hits',
        'points',
        'station_figure_hits',
    ];

    protected $casts = [
        'station_figure_hits' => 'array',
    ];

    public function Signup()
    {
        return $this->belongsTo(\App\Models\Signup::class, 'signups_id', 'id');
    }
}

Output from debugger:

 "patrol" => "1"
  "patrol_type" => null
  "station_start" => "1"
  "station_end" => "2"
  "lane_start" => "1"
  "lane_end" => "20"
  "show_empty_lanes" => "1"
  "per_shot" => "1"

Would appreciate some ideas. Regards, Ralph in Sweden



Solution 1:[1]

It seems that any else condition match and you return $patrols; To avoid the error you can return like that: return $patrols ?? null; or initiate $$patrols in the beginning of your function. Instead null you have check what are expected.

Solution 2:[2]

PROBLEM SOLVED! The trick is to rearrange the statements so it does not check for patrol_type first as it could be null but check for the other two. If it is not one of them it's assumed null and then it works perfect as here:

public function getPatrols($competitionsId)
{
    if ($this->request->get('patrol_type') == 'finals'):
        return PatrolFinals::where('competitions_id', $competitionsId)->orderBy('sortorder')->get();
    endif;
    
    if ($this->request->get('patrol_type') == 'distinguish'):
        return PatrolDistinguish::where('competitions_id', $competitionsId)->orderBy('sortorder')->get();
    endif;

    return Patrol::where('competitions_id', $competitionsId)->orderBy('sortorder')->get();
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Maik Lowrey
Solution 2