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;
}
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.
Related
Am doing a league management system where the system generates fixtures and assign each match to an official who later enters results. Now when i have set everything possible for the log table but when i pass the results, am getting the some few errors : Too few arguments to function App\Models\Gamescores::updateStandings(), 0 passed in E:\Video\laraVids\laraProjects\HAM\app\Models\Gamescores.php on line 28 and exactly 1 expected
here is my code for the sorting of the league
class Gamescores extends Model
{
use HasFactory;
protected $table = 'gamescores';
protected $fillable = [
'games_id',
'away_score',
'home_score',
];
public function game()
{
return $this->belongsTo(Game::class, 'games_id');
}
public static function boot()
{
parent::boot();
static::created(function ($gamescore) {
$gamescore->updateStandings();
});
}
public function updateStandings($league_id)
{
// Get all gamescores for the specified league
$gameScores = Gamescores::whereHas('game', function ($query) use ($league_id) {
$query->where('league_id', $league_id);
})->get();
// Loop through each gamescore and update the log table for each team
foreach ($gameScores as $gameScore) {
$game = Games::find($gameScore->games_id);
$league_id = $game->league_id;
$home_team_id = $game->home_team;
$away_team_id = $game->away_team;
$home_team_log = Logtable::where('team_id', $home_team_id)->first();
if ($home_team_log !== null) {
$home_team_log->played += 1;
if ($gameScore->home_score > $gameScore->away_score) {
$home_team_log->won += 1;
$home_team_log->points += 3;
} else if ($gameScore->home_score == $gameScore->away_score) {
$home_team_log->drawn += 1;
$home_team_log->points += 1;
} else {
$home_team_log->lost += 1;
}
$home_team_log->goals_for += $gameScore->home_score;
$home_team_log->goals_against += $gameScore->away_score;
$home_team_log->goal_difference = $home_team_log->goals_for - $home_team_log->goals_against;
$home_team_log->save();
}
$away_team_log = Logtable::where('team_id', $away_team_id)->first();
if ($away_team_log !== null) {
$away_team_log->played += 1;
if ($gameScore->away_score > $gameScore->home_score) {
$away_team_log->won += 1;
$away_team_log->points += 3;
} else if ($gameScore->home_score == $gameScore->away_score) {
$away_team_log->drawn += 1;
$away_team_log->points += 1;
} else {
$away_team_log->lost += 1;
}
$away_team_log->goals_for += $gameScore->away_score;
$away_team_log->goals_against += $gameScore->home_score;
$away_team_log->goal_difference = $away_team_log->goals_for - $away_team_log->goals_against;
$away_team_log->save();
}
}
}
}
thats my model where am passing the method to genererate the results
public function fixtureToView($league)
{
// Fetch all rows from the games table, including the related official model
$games = Games::where('league_id', $league)->get();
// Extract the values for the role column as an array
$pluckedFixtures = $games->pluck('Fixture')->toArray();
// Count the number of occurrences of each value in the array
$counts = array_count_values($pluckedFixtures);
// Initialize an empty array to store the duplicate keys and values
$fixtures = collect([]);
// Iterate over the counts array
foreach ($counts as $key => $count) {
// If the count is greater than 1, add the key and value to the duplicates array
$fixtures->push($games->where('Fixture', $key));
}
// In your controller
$gamescores = Gamescores::all();
foreach ($gamescores as $gamescore) {
$game = Games::find($gamescore->games_id);
$league_id = $game->league_id;
$gamescore->updateStandings($league_id);
if($gamescore->games_id){
$game = Games::find($gamescore->games_id);
$league_id = $game->league_id;
$gamescore->updateStandings($league_id);
}
}
$standings = Logtable::all();
$standings = $standings->sortByDesc('points');
// return view('standings', compact('standings'));
return view(
'admin.league.fixtures.index',
compact('fixtures', 'standings')
);
thats my controller where am passing the method to retrieve it in the view, what i want is the log table to get the Id of the league where the games/matches belong to
the error am getting this error
I'm trying to filter a numeric value by values greater, lesser or equal to the one given in input.
So far I have managed to filter individually or at most by >= or <=
->andFilterWhere(['<=', 'production_order.qnt', $this->qnt])
but I can't find a solution to filter by writing in the input "<500"
or "> 500" because in the rules I set this value ( qnt ) as integer.
public function rules()
{
return [
[['product_routing_id', 'qnt', 'qnt_worked', 'production_status_id', 'production_order_id', 'acceptance_order_id', 'customer_id', 'product_id', 'casting_id', 'trash'], 'integer'],
}
Do i need a custom filter for it?
Any ideas?
Thanks
Here is the code I have created for this (and yes, you need to change the rule to string because "<" is not an integer, it is a string)
First I have a public static function which is contained in a class called NumberFilter. NumberFilter contains one public function getArray()
This allows the user to apply any of the following filters (obviously it allows greater than as well)
< 1000
<= 1000
= 1000
< 1k
< 1,000
1000
Null
!null
{
public static function getArray($param, $filterString)
{
if (empty($filterString)){
return [];
}
// remove any whitespace
$filterString = trim($filterString);
$filterString = str_replace(" ", "", $filterString);
$filterString = str_replace(",", ".", $filterString);
$filterString = strtolower($filterString);
if (substr($filterString, 0, 2) == ">=") {
$n = substr($filterString, 2);
$n = self::applyMultiplier($n);
if (is_numeric($n))
return [">=", $param, (integer)$n];
} else if (substr($filterString, 0, 1) == ">") {
$n = substr($filterString, 1);
$n = self::applyMultiplier($n);
if (is_numeric($n))
return [">", $param, (integer)$n];
} else if (substr($filterString, 0, 2) == "<=") {
$n = substr($filterString, 2);
$n = self::applyMultiplier($n);
if (is_numeric($n))
return ["<=", $param, (integer)$n];
} else if (substr($filterString, 0, 1) == "<") {
$n = substr($filterString, 1);
$n = self::applyMultiplier($n);
if (is_numeric($n))
return ["<", $param, (integer)$n];
} else if (substr($filterString, 0, 1) == "=") {
$n = substr($filterString, 1);
$n = self::applyMultiplier($n);
if (is_numeric($n))
return [$param => (integer)$n];
} else if ($filterString == "null") {
return [$param => NULL];
} else if ($filterString == "!null") {
return ['NOT', [$param => NULL]];
} else if (is_numeric($filterString)) {
return [$param => (integer)$filterString];
}
Yii::$app->session->setFlash('error', 'The filter was not a valid number. Please try again');
return '0=1'; // invalid query - return no results
}
// used to replace k with 1,000 etc
private static function applyMultiplier($n)
{
if (strpos($n, "k") !== false) {
$n = str_replace("k", "", $n);
$n = doubleval($n) * 1000;
if (is_numeric($n))
return $n;
}
if (strpos($n, "m") !== false) {
$n = str_replace("m", "", $n);
$n = doubleval($n) * 1000000;
if (is_numeric($n))
return $n;
}
if (strpos($n, "b") !== false) {
$n = str_replace("b", "", $n);
$n = doubleval($n) * 1000000000;
if (is_numeric($n))
return $n;
}
// nothing to do
return $n;
}
}
From within the DataProvider, I can call the filter as follows:
$query->andWhere(NumberFilter::getArray('FIELD_NAME', $this->FIELD_NAME));
This function will return the array needed by Yii, for example:
['>' , 'FIELD_NAME' , 1000]
You should use between
andFilterWhere(['between', 'created_at', $start_date, $end_date])
i am trying to show value in array but all value is showing in array but i need to show all those record which is not null how can i remove null in array Does anyone have an idea please help me thanks.
Note : only i want to get value which already exist into database not null values
[1,2,3,4,5,6,7,8,null,null,null,null]
COntroller
public function store(Request $request)
{
$project = Project::with('projectBillingInfo')->where('is_amc', 1)->get();
foreach ($project as $key => $value) {
$count = 0;
if ($value->projectBillingInfo->jan != null) {
$count = $count += 1;
}
if ($value->projectBillingInfo->feb != null) {
$count = $count += 1;
}
if ($value->projectBillingInfo->mar != null) {
$count = $count += 1;
}
if ($value->projectBillingInfo->apr != null) {
$count = $count += 1;
}
if ($value->projectBillingInfo->may != null) {
$count = $count += 1;
}
if ($value->projectBillingInfo->june != null) {
$count = $count += 1;
}
if ($value->projectBillingInfo->july != null) {
$count = $count += 1;
}
if ($value->projectBillingInfo->aug != null) {
$count = $count += 1;
}
if ($value->projectBillingInfo->sep != null) {
$count = $count += 1;
}
if ($value->projectBillingInfo->oct != null) {
$count = $count += 1;
}
if ($value->projectBillingInfo->nov != null) {
$count = $count += 1;
}
if ($value->projectBillingInfo->dec != null) {
$count = $count += 1;
}
$months = [
$value->projectBillingInfo->jan,
$value->projectBillingInfo->feb,
$value->projectBillingInfo->mar,
$value->projectBillingInfo->apr,
$value->projectBillingInfo->may,
$value->projectBillingInfo->june,
$value->projectBillingInfo->july,
$value->projectBillingInfo->aug,
$value->projectBillingInfo->sep,
$value->projectBillingInfo->oct,
$value->projectBillingInfo->nov,
$value->projectBillingInfo->dec,
];
return $months;
[1,2,3,4,5,6,7,8,null,null,null,null]
}
use array_filter()
example:
$result = array_filter($array);
array_filter() remove empty array elements from array.
based on this answer:
$month=array_filter($month);
if you did not provide a callback for array_filter, all entries of array equal to FALSE or Null will be removed
The orignial code was like this , I want to get landline_no value also in getRecords, How to do that
public function checklead() {
$lead = $_POST['number'];
$check = $this->common_model->getRecords('leads',array("phone_no"=>$lead));
if(count($check) > 0) {
$lead = $this->common_model->getRecored_row('leads',array("phone_no"=>$lead));
if($lead->assignto_self != 0) {
$assignto = $lead->assignto_self;
$key = 'Self Assign';
} else if($lead->assignto_se != 0) {
$assignto = $lead->assignto_se;
$key = '';}
What I have achieved so far,but not getting array values from getRecords
$lead = $_POST['number'];
$check = $this->common_model->getRecords('leads',array("phone_no"=>$lead),array("landline_no"=>$lead));
//echo "<pre>";
//print_r($check);
//echo $check[0]['landline_no'];exit;
if(count($check) > 0) {
$lead = $this->common_model->getRecored_row('leads',array("phone_no"=>$lead,"landline_no"=>$check[0]['landline_no']));
Code for getRecords:
function getRecords($table,$db = array(),$select = "*",$ordercol = '',$group = '',$start='',$limit=''){
$this->db->select($select);
if(!empty($ordercol)){
$this->db->order_by($ordercol);
}
if($limit != '' && $start !=''){
$this->db->limit($limit,$start);
}
if($group != ''){
$this->db->group_by($group);
}
$q=$this->db->get_where($table, $db);
return $q->result_array();
}
// Get Recored row
public function getRecored_row($table,$where)
{
$q = $this->db->where($where)
->select('*')
->get($table);
return $q->row();
}
Check my answer: This code also working well, i have written, but i am not sure , this logic is correct or not kindly check this one.
public function checklead() {
$lead = $_POST['number'];
if($this->common_model->getRecords('leads',array("phone_no"=>$lead)))
{
$check=$this->common_model->getRecords('leads',array("phone_no"=>$lead));
}
else
{
$check=$this->common_model->getRecords('leads',array("landline_no"=>$lead));
}
echo "<pre>";
//echo $check;
//print_r($check); exit;
$p= $check[0]['phone_no'];
$l= $check[0]['landline_no'];
// exit;
if(count($p) > 0 || count($l)>0) {
$lead = $this->common_model->getRecored_row('leads',array("phone_no"=>$p));
$lead1 = $this->common_model->getRecored_row('leads',array("landline_no"=>$l));
if($lead->assignto_self != 0 || $lead1->assignto_self != 0) {
$assignto = $lead->assignto_self;
$key = 'Self Assign';
} else if($lead->assignto_se != 0 || $lead1->assignto_se != 0) {
$assignto = $lead->assignto_se;
$key = '';
}else if($lead->assignto_tl != 0 || $lead1->assignto_tl != 0) {
$assignto = $lead->assignto_tl;
$key = '';
} else if($lead->uploaded_by != 0 || $lead1->uploaded_by != 0) {
$assignto = $lead->uploaded_by;
$key = 'Uploaded by';
}
$user = $this->common_model->getRecored_row('admin',array("id"=>$assignto));
$role = $this->common_model->getRecored_row('role',array("id"=>$user->role));
$this->session->set_flashdata('message', array('message' => 'This Lead Already exist with '.$user->name.' ('.$role->role.') '.' ','class' => 'danger'));
redirect(base_url().'leads');
} else {
redirect(base_url().'leads/add_newlead/'.$lead);
}
}
There does not seem to be any reason to use getRecords(). The $check value has no useful purpose and creating it is a waste of resources.
We don't need $check because getRecord_row() will return the "lead" if found so the only check needed is to see if getRecord_row() returns anything. getRecord_row() uses the database function row() which returns only one row or null if no rows are found. Read about row() here.
If what you want is to find the "lead" that has either a "phone_no" or a "landline_no" equal to $_POST['number'] then you need to use a custom string for the where clause. (See #4 at on this documentation page.) You need a custom string because getRecord_row() does not allow any other way to ask for rows where a='foo' OR b='foo'. Here is what I think you are looking for.
public function checklead()
{
// use input->post() it is the safe way to get data from $_POST
$phone = $this->input->post('number');
// $phone could be null if $_POST['number'] is not set
if($phone)
{
$lead = $this->common_model->getRecored_row('leads', "phone_no = $phone OR landline_no = $phone");
// $lead could be null if nothing matches where condition
if($lead)
{
if($lead->assignto_self != 0)
{
$assignto = $lead->assignto_self;
$key = 'Self Assign';
}
else if($lead->assignto_se != 0)
{
$assignto = $lead->assignto_se;
$key = '';
}
}
}
}
The main difference between getRecords() and getRecord_row() is the number of records (rows of data) to return. getRecord_row() will return a maximum of one record while getRecords() might return many records.
getRecords() accepts arguments that allow control of what data is selected ($db, $select), how it is arranged ($ordercol, $group), and the number of rows to retrieve ($limit) starting at row number x ($start) .
Controller:
$next_id = $this->o->next_id();
$data['next_id']=$next_id;
Model:
public function next_id(){
$this->db->select_max('p_ori_id');
$max = $this->db->get('orientation_master');
if($max==0){
$next_id = 1;
}else{
$next_id = 1+$max;
}
return $next_id;
}
Return Error:
Object of class CI_DB_mysqli_result could not be converted to int
Please solve problem..
No offense to #pradeep but you may have some unexpected results if you don't have any rows. I suggest:
public function next_id()
{
$this->db->select_max('p_ori_id', 'max');
$query = $this->db->get('orientation_master');
if ($query->num_rows() == 0) {
return 1;
}
$max = $query->row()->max;
return $max == 0 ? 1 : $max + 1;
}
Hope this will help you:
public function next_id()
{
$this->db->select_max('p_ori_id', 'max');
$query = $this->db->get('orientation_master');
// Produces: SELECT MAX(p_ori_id) as max FROM orientation_master
$max = $query->row()->max;
if($max == 0){
$next_id = 1;
}else{
$next_id = $max+1;
}
return $next_id;
}
For more : https://www.codeigniter.com/user_guide/database/query_builder.html
You are getting that error becuase $max is a result set object and not an integer record value like you're trying to use it.
You can try this function to get the next id.
Modified function:
public function next_id(){
$this->db->select_max('p_ori_id', 'max');
$result = $this->db->get('orientation_master');
$row = $result->row_array();
$next_id = isset($row['max']) ? ($row['max']+1) : 1;
return $next_id;
}
If the column is auto increment, you can use the below code instead.
Alternative:
public function next_id() {
$sql_string = "SELECT `auto_increment` FROM INFORMATION_SCHEMA.TABLES WHERE table_name = '".$this->db->dbprefix."orientation_master'";
$query = $this->db->query($sql_string);
$row = $query->row_array();
return $row['auto_increment'];
}