Экспорт в CSV

Экспорт пользователей в CSV, который возможно открыть в Excel.

csvExporter.php
class csvExporter {
  public function __construct() {
    require_once('usersGetter.php');
    require_once('valueConverter.php');
  }
 
  private $fHandle, $usersGetter;
  public function export() {
    $offset = 0; $limit = 100;
    $this->fHandle = fopen('php://output', 'w');
    $this->sendHeaders('users.xls');
 
    $this->usersGetter = new usersGetter(); // источник данных
 
    $this->putHead($this->usersGetter->exportedValues);
 
    while (($usersRows = $this->usersGetter->loadUsers($offset, $limit)) !== false) {
      $offset += $limit;
      $this->putUsers($this->usersGetter->exportedValues, $usersRows);
    }
 
    fclose($this->fHandle);
    die();
  }
 
  private function putHead($exportedValues) {
    $head = array();
    foreach ($exportedValues as $exportValue) {
      $head[] = $exportValue['name'];
    }
    fputcsv($this->fHandle, $head);
  }
 
  private function convertValue($value, $function) {
    if (empty($function) || !method_exists('valueConverter', $function)) return $value;
    return valueConverter::$function($value);
  }
 
  private function putUsers($exportedValues, $usersRows) {
    foreach ($usersRows as $row) {
      $data = array();
      foreach ($exportedValues as $exportValue) {
        $data[] = $this->convertValue($row[$exportValue['column']], $exportValue['function']);
      }
      fputcsv($this->fHandle, $data);
    }
  }
 
  private function sendHeaders($fileName) {
    header("Content-Type: application/force-download");
    header("Content-Type: application/octet-stream");
    header("Content-Type: application/download");
    header("Content-Disposition: attachment;filename=".$fileName);
    header("Content-Transfer-Encoding: binary");
  }
 
}
 
// RUN
 
$exporter = new csvExporter();
$exporter->export();
usersGetter.php
class usersGetter {
  private $db;
  public function __construct() {
    $this->db = App::GetDBO();
  }
 
  public function loadUsers($offset, $limit) {
    $query = "SELECT * FROM `users` ORDER BY `id` LIMIT ".(int)$offset.', '.(int)$limit;
    $users = $this->db->SelectSet($query);
    return is_array($users) && count($users) > 0 ? $users : false;
  }
 
  public $exportedValues = array(
    array('column' => 'id', 'name' => 'id'),
    array('column' => 'is_active', 'name' => 'Активность', 'function' => 'isBool'),
    array('column' => 'idate', 'name' => 'Дата', 'function' => 'idate'),
    array('column' => 'email', 'name' => 'E-mail (логин)'),
    array('column' => 'password', 'name' => 'Пароль'),
  );
}
valueConverter.php
class valueConverter {
  public static function idate($value) {
    return $value == 0 ? '--.--.--' : date("d.m.Y", $value);
  }
 
  public static function isBool($value) {
    return $value ? 'да' : 'нет';
  }
}