Skip to content

6. Application Exercise – Tax Calculation with Objects (impots_03)

We revisit the exercise previously studied (sections 4.2 and 4.3) to solve it using PHP code that utilizes a class.


<?php

// definition of a Taxes class
class Taxes {

  // attributes: the 3 data arrays
  private $limits;
  private $coeffR;
  private $coeffN;
  
  // constructor

  public function __construct($TAXES) {
    // $IMPOTS: the name of the file containing the data for the $limites, $coeffR, and $coeffN tables
    // Does the $IMPOTS file exist?
    if (!file_exists($IMPOTS)) {
      throw new Exception("The $IMPOTS file does not exist");
    }//if
    // read the file in blocks
    $tables = file($IMPOTS);
    if (!$tables) {
      throw new Exception("Error while processing the $IMPOTS file");
    }//if
    // Create the 3 tables - assuming the rows are syntactically correct
    $u = new Utilities(); // to provide utility functions
    $this->limits = explode(":", $u->cutNewLineChar($tables[0]));
    $this->coeffR = explode(":", $u->cutNewLineChar($tables[1]));
    $this->coeffN = explode(":", $u->cutNewLineChar($tables[2]));
    }

  // --------------------------------------------------------------------------
  public function calculate($married, $children, $salary) {
    // $marié: yes, no
    // $children: number of children
    // $salary: annual salary
    
    // number of shares
    $married = strtolower($married);
    if ($married == "yes")
      $nbParts = $children / 2 + 2;
    else
      $nbParts = $children / 2 + 1;
    // add 1/2 portion if there are at least 3 children
    if ($children >= 3)
      $nbParts+=0.5;
    // taxable income
    $taxableIncome = 0.72 * $salary;
    // family quotient
    $quotient = $taxableIncome / $numberOfChildren;
    // is placed at the end of the limits array to stop the following loop
    $this->limits[count($this->limits) - 1] = $quota;
    // tax calculation
    $i = 0;
    while ($quotient > $this->limits[$i])
      $i++;
    // Since we placed $quotient at the end of the $limites array, the previous loop
    // cannot go beyond the $limits array
    // now we can calculate the tax
    return floor($taxableIncome * $this->coeffR[$i] - $numberOfShares * $this->coeffN[$i]);
  }

}

// a utility class
class Utilities {

  public function cutNewLineChar($line) {
    // remove the end-of-line character from $line if it exists
    $L = strlen($line);  // line length
    while (substr($line, $L - 1, 1) == "\n" or substr($line, $L - 1, 1) == "\r") {
      $line = substr($line, 0, $L - 1);
      $L--;
    }//while
    // end
    return($line);
  }

}

// test -----------------------------------------------------
// definition of constants
$DATA = "data.txt";
$RESULTS = "results.txt";
$TAXES = "taxes.txt";
// The data needed to calculate the tax has been placed in the TAXES file
// with one line per table in the form
// "val1":"val2":"val3",...
// we create a Taxes object
try {
  $I = new Taxes($TAXES);
} catch (Exception $e) {
  print $e->getMessage();
  exit;
}
// create a utilities object
$u = new Utilities();

// read user data
$data = fopen($DATA, "r");
if (!$data) {
  print "Unable to open the data file [$DATA] for reading\n";
  exit;
}

// Open the results file
$results = fopen($RESULTS, "w");
if (!$results) {
  print "Unable to create the results file [$RESULTS]\n";
  exit;
}

// process the current line of the data file
while ($line = fgets($data, 100)) {
  // remove any end-of-line characters
  $line = $u->cutNewLineChar($line);
  // We retrieve the three fields married, children, and salary that make up $line
  list($married, $children, $salary) = explode(",", $line);
  // calculate the tax
  $tax = $I->calculate($married, $children, $salary);
  // print the result
  fputs($results, "$married:$children:$salary:$tax\n");
  // next data
}// while
// close the files
fclose($data);
fclose($results);

// end
print "Done\n";
exit;
?>

The [taxes.txt] file:

12620:13190:15640:24740:31810:39970:48360:55790:92970:127860:151250:172040:195000:0
0:0.05:0.1:0.15:0.2:0.25:0.3:0.35:0.4:0.45:0.5:0.55:0.6:0.65
0:631:1290.5:2072.5:3309.5:4900:6898.5:9316.5:12106:16754.5:23147.5:30710:39312:49062

The file [data.txt]

yes,2,200000
no,2,200000
yes,3,200000
no,3,200000
yes,5,50000
no,0,3000000

Results: those already obtained in the versions with tables and files.

The file [results.txt]

yes:2:200000:22504
no:2:200000:33388
yes:3:200000:16400
no:3:200000:22504
yes:5:50000:0
no:0:3000000:1354938

Comments

  • Line 4: the Taxes class. It encapsulates data and methods for calculating taxes:
  • data: lines 7–9 – these are the three data arrays used to calculate the tax. These three arrays are initialized by the constructor on line 13 from a text file.
  • methods: line 32 – the *calculate* method calculates the tax.
  • Lines 17, 22: When the constructor cannot create the Taxes object, it throws an exception.
  • line 25: the Utilities class was defined to encapsulate the cutNewLineChar function.
  • Lines 26–28: Initialization of the three private fields of the Taxes class
  • Line 32: The *calculate method of the *Taxes class calculates a taxpayer's tax.
  • lines 65–78: the Utilities class
  • lines 89–94: creation of a Taxes object with exception handling. This creation will use the $IMPOTS text file to populate the three private fields of the Taxes object.
  • Line 96: Creation of a Utilities object to access the cutNewLineChar function.