Search code examples
laravelaveragemodels

Laravel Model Average of Non-N/A Values


I am looking for the best way to average the values of a submodel in Laravel, but ignore some of the values. The column I want to average is set as varchar, but contains either a number between 0 and 10 or the value 'N/A'. I need two averages on this column, one ignoring 'N/A' values, and one counting 'N/A' values as 0. I have the fucntions written how how they would be to calculate the averages but I am hoping to get some input on the best way to do this.

I would love to be able to call these functions like this:

    $web_scored_tq = $website->scored_tq;
    $web_uscored_tq = $website->unscored_tq;

Functions:

public function scored_tq() {
    $valid_click_ads = $this->valid_click_ads;
    $total = 0;
    $num = 0;

    foreach ($valid_click_ads as $valid_click_ad) {
        if ($valid_click_ad->tq != "N/A") {
            $total += $valid_click_ad->tq;
            ++$num;
        }
    }

    $scored_tq = $total / $num;
}

public function unscored_tq() {
    $valid_click_ads = $this->valid_click_ads;
    $total = 0;
    $num = 0;

    foreach ($valid_click_ads as $valid_click_ad) {
        if ($valid_click_ad->tq != "N/A") {
            $total += $valid_click_ad->tq;
            ++$num;
        } else {
            ++$num;
        }
    }

    $unscored_tq = $total / $num;
}

Solution

  • I found laravel's model getFooAttribute! I used this to add the following functions to my Website model, and now can call $website->scored_tq or $website->unscored_tq.

    public function getScoredTqAttribute() {
        $valid_click_ads = $this->valid_click_ads;
        $total = 0;
        $num = 0;
    
        foreach ($valid_click_ads as $valid_click_ad) {
            if ($valid_click_ad->tq != -1) {
                $total += $valid_click_ad->tq;
                ++$num;
            }
        }
    
        if ( $num != 0 ) {
            $scored_tq = $total / $num;
        } else {
            $scored_tq = '-';
        }
        return $scored_tq;
    }
    
    public function getUnscoredTqAttribute() {
        $valid_click_ads = $this->valid_click_ads;
        $total = 0;
        $num = 0;
    
        foreach ($valid_click_ads as $valid_click_ad) {
            if ($valid_click_ad->tq != -1) {
                $total += $valid_click_ad->tq;
            }
            ++$num;
        }
    
        if ( $num != 0 ) {
            $unscored_tq = $total / $num;
        } else {
            $unscored_tq = '-';
        }
        return $unscored_tq;
    }
    

    I also changed how my data is structured to integers, where "N/A" values are changed to -1.