Saturday, March 18, 2017

Laravel function belong in model or controller

I have a function which contains a query and a percentile calculation (below) on the query's results/collection.

This function is needed in the following way:

I have an Athlete model, with many Tests. Each Test also has many Results. For every result (displayed in a table), I need to display a calculated percentile (which is not stored). It's at this point (the table view) where I need the function to calculate the percentile for every result.

I have detailed the models here. The answer of that post also shows the query used.

If I stick that function in the Result model, it allows me easy access to it from the view in this manner

If I put it in a Controller, I would need some dynamic and complex way to call a route for each specific Result in the table. Not even sure how to do this.

Question: Is it correct to have this query and calculation in the Result model?

An earlier post here, seems to also go with model.

The calculation performed on the query collection:

                for ($i = 1; $i < 100; $i++ ){
                $rank = 0.0;
                $p = 0.0;
                $rank = $i/100 * ($count + 1);
                $p = $rank;
                //get integer and decimal for interpolation  http://onlinestatbook.com/lms/introduction/percentiles.html                
                $intpart = floor($p);    
                $fraction = $p - $intpart;
                //dd($intpart . ' '.$fraction);
                if($fraction > 0){ //part of percentile formula - see article
                    //test for min array index to not be out of bound. Test negative, most used case.
                    if($intpart != 0){ 
                        $scoreLow = $all_scores[$intpart - 1];
                        if($intpart == $count){ //test for max array index to not go over bound
                            $scoreHigh = $all_scores[$intpart - 1];
                        } else{
                            $scoreHigh = $all_scores[$intpart];    
                        }                            
                    } else{
                        $scoreLow = $all_scores[0];
                        $scoreHigh = $all_scores[$intpart];
                    }                
                    //scoreLow and scoreHigh has been determined, now final step for decimal rank         
                    $scoreHigh = $scoreHigh * 1.0;
                    $scoreLow = $scoreLow * 1.0;
                    $rank = ($fraction * ($scoreHigh - $scoreLow)) + $scoreLow;
                } else{
                    $rank = ($all_scores[$intpart - 1] * 1.0);//no decimal rank, plain rank calculation
                }

                if($sortorder == 'asc'){
                    $rankings[$i.'th %'] = $rank;                            
                }else{
                    $rankings[100 - $i.'th %'] = $rank;
                }

                  //$rankings->add(['rank'.$i => $rank]);
            }                 
            //dd($rankings);
            //reverse rankings
            $rev_rankings = array_reverse($rankings);
            if ($battery == 111){
                dd($rev_rankings);
            }

            $view_rank = null;
            foreach($rev_rankings as $key => $rank){
                if($athlete_score == $rank){
                    $view_rank = $key;
                    break;
                }
                if($athlete_score > $rank){
                    $view_rank = $key;
                    break;
                }
            }
            return($view_rank);
        }
        else{
            return ('Not available');
        }



via louisav

Advertisement