Перейти к тексту

developerWorks Россия  >  Open source | XML  >

Полный цикл разработки Ajax-приложений, Часть 2: Реализация уровней Ajax-клиента и сервера

Разделите уровни вашего приложения для создания понятного и элегантного Web-приложения

developerWorks

Вернуться к статье


Листинг 2. Содержимое файла BankLogic.php
                

<?php
/*
============================================================
Проект: Полный цикл разработки Ajax-приложения

Назначение: Это пример сценария, используемого 
 в статье на IBM developerWorks.

Дата последней модификации: 11 мая 2007.

Этот PHP-модуль реализует базовую логику кассира банка,
необходимую для доступа к данным клиента в 
базе данных. Эти функции могут быть вызваны другими PHP-модулями,
имеющимися в сценарии Bank. Вся логика, включенная в операции
кассира банка, подразделяется на три следующие
базовые функции.

 a) Получить информацию о всех счетах
 b) Обработать транзакцию (депозит или дебет)
 c) Вычислить стоимость портфеля ценных бумаг

Здесь используются функции mysqli для прямого доступа к базе данных, 
в противоположность функциям PHP PDO. 
============================================================
*/
   // Эти переменные globals будут использоваться для хранения следующих значений:
   // 1) $link - для хранения объекта connection.
   // 2) $dbResult - для хранения объекта result, результата запроса к базе данных.
   // 3) $finalResult - это ассоциативный массив, в котором упакованы
   //    и возвращены вызывающей стороне результаты 
   //    конкретных операций кассира банка.
   global $link, $dbResult, $finalResult;

   /*
   ============================================================
   Функция: connect_to_db

   Дата последней модификации: 11 мая 2007.
	
   Эта функция выполняет подключение к базе данных BankDB MySQL.
   Если попытка подключения успешна, она сохраняет 
   объект connection в глобальной переменной и 
   возвращает значение true. 
   В противном случае возвращается значение false.
   ============================================================ 
   */
   function connect_to_db() {
      // Мы будем использовать следующие глобальные переменные.
      global $link, $dbResult, $finalResult;
		
      // Инициализация переменных.
      $link = null;
      $dbResult = null;
      $finalResult = null;
		
      // Выполнить подключение mysqli к локальной базе данных BankDB, используя 
      // соответствующие параметры доступа.
      $link = mysqli_connect("localhost", "root", "webtech", "bankdb");

      // Проверить, работает ли подключение к DB.
      if (mysqli_connect_errno()) {
         // Похоже, что есть какая-то проблема.
         // Получить номер MySQL-ошибки и строку, описывающую ошибку.
         $resultMsg = "DB connection error: " . mysqli_connect_errno() .
            " [" . mysqli_connect_error() . "]";
         // Сохранить результаты в ассоциативном массиве.
         // Установить результат операции как неудачный.
         $finalResult["ResultCode"] = 1;
         // Записать сообщение результата.
         $finalResult["ResultMsg"] = $resultMsg;
         // Возвратить значение false для индикации ошибки подключения к DB.
         return (false);
      } else {
         // Подключение DB успешно.
         return(true);		
      } // Конец if (mysqli_connect_errno())
   } // Конец функции connect_to_db

   /*
   ============================================================
   Функция: close_connection_to_db

   Дата последней модификации: 11 мая 2007.

   Эта функция закрывает выполненное ранее подключение к 
   базе данных BankDB.
   ============================================================ 
   */	
   function close_connection_to_db() {
      // Мы будем использовать следующие глобальные переменные.
      global $link, $dbResult;
	
      // Закрыть подключение, если имеется активный 
      // объект connection.
      if ($link != null) {
         if (($dbResult != null) && (is_object($dbResult))) {
            // Если DB result содержит объект запроса данных, 
			// освободить занимаемую им память.
            mysqli_free_result($dbResult);
            $dbResult = null;
         } // Конец if ($dbResult != null)
			
         // Пора закрыть DB connection.
         mysqli_close($link);
         // Установить переменную объекта connection в значение null.
         $link = null;			
      } // Конец if ($link != null)
   } // Конец функции close_connection_to_db

   /*
   ============================================================
   Функция: getAllAccountInformation
	
   Дата последней модификации: 11 мая 2007.
	
   Эта функция считывает информацию обо всех счетах, хранящихся в
   BankDB, и возвращает их в ассоциативном массиве.
   ============================================================ 
   */			
   function getAllAccountInformation() {
      // Мы будем использовать следующие глобальные переменные.
      global $link, $finalResult, $dbResult;
	
      // Выполнить подключение к BankDB.
      $result = connect_to_db();
	
      // Если подключение неудачно, возвратить управление.
      if ($result == false) {
         return ($finalResult);
      } // Конец if ($result == false)
		
      // SQL-запрос для получения всех строк таблицы account.
      $queryStr = "Select * from account";
      // Выполнить SQL-запрос.
      $dbResult = mysqli_query($link, $queryStr);
		
      // Обработать ошибки запроса, если они имеются.
      if (mysqli_errno($link)) {
         // Сначала закрыть подключение.
         close_connection_to_db();		
         // Записать сообщение об ошибке в окончательный ассоциативный массив.	
         $resultMsg = "DB read error: " . mysqli_errno($link) .
            " [" . mysqli_error($link) . "]";
         // Установить специфический для приложения код возврата FAILURE.
         $finalResult["ResultCode"] = 1;				
         $finalResult["ResultMsg"] = $resultMsg;
         // Возвратить окончательный результат.
         return ($finalResult);
      } // Конец if (mysqli_errno($link))
		
      // Получить количество запрошенных строк.
      $rowCount = mysqli_num_rows($dbResult);
	
      // Если база данных пуста, возвратить управление.
      if ($rowCount <= 0) {
         // Сначала закрыть подключение.
         close_connection_to_db();
         // Записать код возврата и возвращаемое сообщение.
         $finalResult["ResultCode"] = 1;				
         $finalResult["ResultMsg"] = "No accounts were found in BankDB.";
         // Возвратить окончательный результат.
         return ($finalResult);			
      } // Конец if ($rowCount <= 0)

      // Установить counter в значение 0.
      $cnt = 0;
      // Создать массив для хранения всех полей из каждой строки.
      $accountInfo = array();

      // Из каждой строки результата запроса извлечь поля данных.
      while($row = mysqli_fetch_assoc($dbResult)) {
         // Инициализировать в null.
         $data = null;
         // Создать ассоциативный массив "на лету" и сохранить 
         // конкретные поля данных, считанные из текущей строки базы данных.
         $data["AccountHolderName"] = $row["AccountHolderName"];
         $data["AccountNumber"] = $row["AccountNumber"];
         $data["CheckingBalance"] = doubleval($row["CheckingBalance"]);
         $data["StockName"] = $row["StockName"];
         $data["StockQuantity"] = intval($row["StockQuantity"]);
         $data["StockValue"] = doubleval($row["StockValue"]);
         // Теперь записать весь ассоциативный массив в обычный массив.
         $accountInfo[$cnt++] = $data;
      } // Конец while($row = mysqli_fetch_assoc($dbResult))
		
      // Мы завершили чтение информации обо всех счетах из базы данных.
      // Установить код возврата, как успешный.
      $finalResult["ResultCode"] = 0;
      // Установить сообщение результата, как успешное.
      $finalResult["ResultMsg"] = "ReadAllAccountsInfoFromDB successful";
      // Сделать весь массив, содержащий информацию обо всех счетах,
      // окончательным ассоциативным массивом результата.
      // $finalResult - это ассоциативный массив, содержащий 
      // обычный массив, который в свою очередь содержит несколько ассоциативных 
      // массивов.
      $finalResult["AccountInfo"] = $accountInfo;
      // Закрыть подключение.	
      close_connection_to_db();	
      // Возвратить окончательный массив результатов.
      return($finalResult);		
   } // Конец функции getAllAccountInformation

   /*
   ============================================================
   Функция: accountTransaction

   Дата последней модификации: 11 мая 2007.
	
   Эта функция выполняет транзакцию, выбранную кассиром банка.
   Функция принимает имя владельца счета, количество и
   тип транзакции в качестве параметров.
   Тип транзакции 1 - это депозит на счет.
   Тип транзакции 2 - это дебет.
   После выполнения транзакции возвращается состояние 
   счета до этой транзакции и состояние счета после транзакции.
   ============================================================ 
   */	
   function accountTransaction($accountHolderName, $amount, $transactionType) {
      // Мы будем использовать следующие глобальные переменные.
      global $link, $finalResult, $dbResult;
      // Выполнить подключение к базе данных.
      $result = connect_to_db();
		
      // Если подключение неуспешно, выполнить возврат.
      if ($result == false) {
         return ($finalResult);
      } // Конец if ($result == false)

      // SQL-запрос для чтения конкретных данных о счете 
      // данного владельца счета.
      $queryStr = "Select * from account where AccountHolderName='$accountHolderName'";
      // Выполнить SQL-запрос.
      $dbResult = mysqli_query($link, $queryStr);
	
      // Возникла ошибка?
      if (mysqli_errno($link)) {
         // Закрыть подключение.
         close_connection_to_db();
         // Записать сообщение об ошибке.
         $resultMsg = "DB read error: " . mysqli_errno($link) .
            " [" . mysqli_error($link) . "]";
         // Установить специфичный для приложения код возврата.
         $finalResult["ResultCode"] = 1;				
         // Записать сообщение результата.
         $finalResult["ResultMsg"] = $resultMsg;
         // Возвратить ассоциативный массив с результатом ошибки.
         return ($finalResult);
      } // Конец if (mysqli_errno($link))

      // Сколько строк было прочитано из DB?
      $rowCount = mysqli_num_rows($dbResult);
	
      // Если строк нет, возвратить управление.
      if ($rowCount <= 0) {
         // Закрыть подключение.
         close_connection_to_db();
         // Установить возвращаемое значение как неудачное.
         $finalResult["ResultCode"] = 1;				
         $finalResult["ResultMsg"] = "No accounts were found in BankDB.";
         // Возвратить окончательный результат.
         return ($finalResult);			
      } // Конец if ($rowCount <= 0)

      // Сохранить запись с текущим балансом.
      // Создать массив для хранения состояний до и после транзакции.
      $accountInfo = array();		
      // Извлечь результат запроса в виде ассоциативного массива.
      $row = mysqli_fetch_assoc($dbResult);		
      $data = null;
      // Записать значения полей из строки базы данных в 
      // новый ассоциативный массив.
      $data["AccountHolderName"] = $row["AccountHolderName"];
      $data["AccountNumber"] = $row["AccountNumber"];
      $data["PreviousCheckingBalance"] = doubleVal($row["CheckingBalance"]);
      $data["StockName"] = $row["StockName"];
      $data["StockQuantity"] = intval($row["StockQuantity"]);
      $data["StockValue"] = doubleVal($row["StockValue"]);
      // Записать состояние счета до транзакции в обычный массив.
      $accountInfo[0] = $data;

      // Инициализировать переменные.
      $newBalance = 0.0;
      // Поскольку мы выполняем транзакцию, меняющую 
      // баланс, необходимо потом обновить DB.
      $updateDB = true;

      if ($transactionType == 1) {
         // Это депозит.
         // Сумма депозита больше 0?
         if ($amount > 0) {
            $newBalance = doubleval($data["PreviousCheckingBalance"]) + $amount;
         } else {
            // Сумма депозита равна 0. Нет необходимости обновлять базу данных.
            $updateDB = false;
            $newBalance = doubleval($data["PreviousCheckingBalance"]);
         } // Конец if ($amount > 0)
      } else if ($transactionType == 2) {
         // Это дебет.
         // Проверить, что сумма дебета больше 0 и 
         // меньше имеющейся на счете.
         if (($amount > 0) &&
            ($amount < doubleval($data["PreviousCheckingBalance"]))) {
            $newBalance = doubleval($data["PreviousCheckingBalance"]) - $amount;	
         } else {
            // Сумма дебета либо 0, либо больше имеющейся на счете.
            $updateDB = false;
            $newBalance = doubleval($data["PreviousCheckingBalance"]);
         }
      } // Конец if ($transactionType == 1)
		
      // Транзакция, выполненная кассиром банка, завершилась.
      // Прекрасно. Возвратить результат.
      $finalResult["ResultCode"] = 0;
      $finalResult["ResultMsg"] = "AccountTransaction successful.";

      // Если мы изменили баланс счета операцией 
      // депозита или дебета, обновить базу данных.
      if ($updateDB == true) {
         // Подготовить выражение SQL Update.
         $updateStr = "update account set CheckingBalance=$newBalance " .
            "where AccountHolderName='$accountHolderName'";

         // Выполнить запрос на обновление.
         $dbResult = mysqli_query($link, $updateStr);

         // Есть ли ошибки?
         if (mysqli_errno($link)) {
            // Закрыть подключение к базе данных.
            close_connection_to_db();				
            // Подготовить возвращаемое сообщение об ошибке.
            $resultMsg = "DB write error: " . mysqli_errno($link) .
               " [" . mysqli_error($link) . "]";
            $finalResult["ResultCode"] = 1;
            $finalResult["ResultMsg"] = $resultMsg;
            // Возвратить сообщение об ошибке.
            return ($finalResult);
         }
					
         if ($dbResult == true) {
            // Все хорошо.
            // Подготовиться к возврату результата данной операции.
            $finalResult["ResultCode"] = 0;
            $finalResult["ResultMsg"] = 
               "New balance for $accountHolderName has been stored in DB.";
         } else {
            $finalResult["ResultCode"] = 1;
            $finalResult["ResultMsg"] = 
            "New balance for $accountHolderName could not be stored in DB.";
            // Возвратить окончательный результат с ошибкой.
            return($finalResult);
         } // Конец if ($dbResult == true)				
      } // Конец if ($updateDB == true)
		
      // Мы уже сохранили состояние счета до транзакции в
      // массиве в начале этой функции.
      // Сохранить вторую запись, которая будет содержать обновленный баланс.
      $data = null;
      $data["AccountHolderName"] = $row["AccountHolderName"];
      $data["TransactionAmount"] = $amount;
      $data["AccountNumber"] = $row["AccountNumber"];
      $data["NewCheckingBalance"] = $newBalance;
      $data["StockName"] = $row["StockName"];
      $data["StockQuantity"] = intval($row["StockQuantity"]);
      $data["StockValue"] = doubleval($row["StockValue"]);
      $accountInfo[1] = $data;		
      $finalResult["AccountInfo"] = $accountInfo;	
      // Закрыть подключение к DB.
      close_connection_to_db();	
      // Возвратить окончательный результат.
      return($finalResult);				
   } // Конец функции accountTransaction.

   /*
   ============================================================
   Функция: portfolioValue
	
   Дата последней модификации: 11 мая 2007.
	
   Эта функция сохраняет текущее значение стоимости портфеля ценных бумаг
   данного владельца счета в базе данных. Она принимает имя 
   владельца счета и текущую цену акции в качестве входных
   аргументов. Она считывает текущую позицию (в сценарии
   Bank каждый владелец владеет акциями только одной компании;
   это сделано для упрощения задачи.) и вычисляет
   текущую рыночную стоимость. Затем функция
   обновляет базу данных новым значением суммарной стоимости акций.
   ============================================================ 
   */		
   function portfolioValue($accountHolderName, $stockPrice) {
      // Мы будем использовать следующие глобальные переменные.
      global $link, $finalResult, $dbResult;

      // Подключиться к базе данных MySQL BankDB.
      $result = connect_to_db();
	
      // При ошибке подключения возвратить управление.
      if ($result == false) {
         return ($finalResult);
      } // Конец if ($result == false)

      // Подготовить строку запроса для получения информации о счете данного владельца.
      $queryStr = "Select * from account where AccountHolderName='$accountHolderName'";
      // Выполнить запрос MySQL.
      $dbResult = mysqli_query($link, $queryStr);
	
      // Есть ошибки?
      if (mysqli_errno($link)) {
         // Ошибка. Закрыть подключение к db.  
         close_connection_to_db();
         // Подготовить сообщение об ошибке для возврата.
         $resultMsg = "DB read error: " . mysqli_errno($link) .
            " [" . mysqli_error($link) . "]";
         $finalResult["ResultCode"] = 1;				
         $finalResult["ResultMsg"] = $resultMsg;
         // Возвратить ошибку.
         return ($finalResult);
      } // Конец if (mysqli_errno($link))

      // Были считаны какие-либо строки из DB? 
      $rowCount = mysqli_num_rows($dbResult);
	
      // Если соответствующих строк в DB нет, возвратить управление.
      if ($rowCount <= 0) {
         // Закрыть подключение к DB.
         close_connection_to_db();
         $finalResult["ResultCode"] = 1;				
         $finalResult["ResultMsg"] = "No accounts were found in BankDB.";
         // Возвратить окончательный результат.
         return ($finalResult);			
      } // Конец if ($rowCount <= 0)

      // Сохранить запись с текущим значением стоимости портфеля.
      // Выделить массив для хранения состояния счета 
      // до и после транзакции.
      $accountInfo = array();		
      // Извлечь результаты из базы данных в виде ассоциативного массива.
      $row = mysqli_fetch_assoc($dbResult);		
      // Сохранить поля данных строки в ассоциативный массив.
      $data = null;
      $data["AccountHolderName"] = $row["AccountHolderName"];
      $data["AccountNumber"] = $row["AccountNumber"];
      $data["CheckingBalance"] = doubleval($row["CheckingBalance"]);
      $data["StockName"] = $row["StockName"];
      $data["StockQuantity"] = intval($row["StockQuantity"]);
      $data["PreviousPortfolioValue"] = doubleval($row["StockValue"]);
      // Записать ассоциативный массив в обычный массив.
      $accountInfo[0] = $data;

      // Вычислить стоимость портфеля.
      $finalResult["ResultCode"] = 0;
      $finalResult["ResultMsg"] = "PortfolioValue successfully calculated.";
      $newPortfolioValue = intval($row["StockQuantity"]) * doubleval($stockPrice);
	
      // Поскольку стоимость портфеля изменилась, обновить ее в DB.
      $updateStr = "update account set StockValue=$newPortfolioValue " .
         "where AccountHolderName='$accountHolderName'";

      // Выполнить SQL-запрос.
      $dbResult = mysqli_query($link, $updateStr);

      // Есть ли ошибки DB?
      if (mysqli_errno($link)) {
         // Закрыть подключение к DB.
         close_connection_to_db();		
         // Подготовить сообщение об ошибке для возврата.		
         $resultMsg = "DB write error: " . mysqli_errno($link) .
            " [" . mysqli_error($link) . "]";
         $finalResult["ResultCode"] = 1;
         $finalResult["ResultMsg"] = $resultMsg;
         // Возвратить сообщение об ошибке.
         return ($finalResult);
      } // Конец if (mysqli_errno($link))
			
      if ($dbResult == true) {
         // Все нормально.
         // Подготовить для возврата сообщение об успешном выполнении.
         $finalResult["ResultCode"] = 0;
         $finalResult["ResultMsg"] = 
            "New stock value for $accountHolderName has been stored in DB.";
      } else {
         $finalResult["ResultCode"] = 1;
         $finalResult["ResultMsg"] = 
            "New stock value for $accountHolderName could not be stored in DB.";
         // Обновление неудачно. Поэтому возвратить ошибочный результат.
         return($finalResult);
      } // Конец else в if ($dbResult == true)				
		
      // Записать вторую запись, которая будет иметь обновленное значение стоимости 
      // портфеля. Мы уже сохранили состояние до транзакции в массиве.
      // Сохраним также состояние после транзакции.
      $data = null;
      $data["AccountHolderName"] = $row["AccountHolderName"];
      $data["AccountNumber"] = $row["AccountNumber"];
      $data["CheckingBalance"] = doubleval($row["CheckingBalance"]);
      $data["StockName"] = $row["StockName"];
      $data["CurrentStockPrice"] = doubleval($stockPrice);
      $data["StockQuantity"] = intval($row["StockQuantity"]);
      $data["NewPortfolioValue"] = $newPortfolioValue;
      // Записать ассоциативный массив в обычный массив.
      $accountInfo[1] = $data;		
      $finalResult["AccountInfo"] = $accountInfo;	
      // Закрыть подключение к DB и возвратить результат.
      close_connection_to_db();	
      return($finalResult);				
   } // Конец функции portfolioValue.
?>
		

Вернуться к статье

    IBM в России Конфиденциальность Контакты