<?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.
?>
|