SlideShare a Scribd company logo
1 of 32
Download to read offline
Сайт на Zend Framework в составе
    промышленной системы

        Сергей Морозов,
          Минск 2012
Сайты бывают разные
Отдельно стоящий сайт


   Внешение ресурсы                       • БД принадлежит только
                                            сайту.

                Бизнес-логика
                                          • Неограниченные
                                            привилегии.

Представление                             • Сайт разграничивает
                                База данных

                                            права пользователей.
Сайт в составе
                промышленной системы
                  Биллинг

                              • БД обслуживает
 Коммутатор
                                несколько приложений
                База данных

                              • Повышенные требова-
Инженерное ПО                   ния к безопасности
                              • Максимально
    Сервер                      ограниченные права
  клиентских
 приложений

                   Сайт
Разграничение прав доступа
                   средствами БД


•   Базы
    данных
•   Таблицы
•   Поля
Чего не хватает?

     • Разграничения на
       доступ к записям
     • Прочих
       ограничений,
       обусловленных
       бизнес-логикой
Ну например?

Если у пользователя есть права на выполнение запроса
SELECT
         id
 FROM
         users
WHERE
         login = :login
  AND
         password = SOME_SECRET_ALG(:password, :salt) ,

значит он может выполнить и
SELECT
         id, login, password
 FROM
         users
Как быть?

• Запретить доступ к таблицам напрямую
• Предоставить абстрактный интерфейс в виде
  пакетов хранимых процедур
Как будто ООП

БАЗА ДАННЫХ               ПРИЛОЖЕНИЕ


         Таблицы                   Данные



   Пакет 1                   Класс 1
     процедура_1_1               метод_1_1

     процедура_1_2               метод_1_2




   Пакет 2                   Класс 2
     процедура_2_1               метод _2_1

     процедура_2_2               метод _2_2
Преимущества подхода


• Централизованное
  разграничение прав
  доступа
• Инкапсуляция
• Разделение труда
Недостатки подхода


       • Бюрократия
       • Сложность
         реализации
       • Отсутствие чѐтких
         границ
Как выглядит код процедуры?

CREATE PROCEDURE AUTHENTICATE(
    psUsername IN VARCHAR2,
    psPassword IN VARCHAR2,
    viAccount_id OUT PLS_INTEGER,
    viStatus OUT VARCHAR2
)
BEGIN
   SELECT
           fiAccount_id,
           fiStatus
      INTO
           viAccount_id,
           viStatus
      FROM
           users
    WHERE
           fsUsername = psUsername
       AND
           fsPassword = SOME_SECRET_ALG(psPassword, 'some salt')
END;
Как выглядит вызов
                              процедуры?
<?php

$query = <<<QUERY
BEGIN
  AUTH.AUTHENTICATE(:psUsername, :psPassword, :piAccount_id, :piStatus);
END
QUERY;

$stmt = oci_parse($conn, $query);

oci_bind_by_name($stmt,   ':psUsername',     $username,     32,   SQLT_CHR);
oci_bind_by_name($stmt,   ':psPassword',     $password,     32,   SQLT_CHR);
oci_bind_by_name($stmt,   ':piAccount_id',   $account_id,   -1,   SQLT_INT);
oci_bind_by_name($stmt,   ':piStatus',       $status,       -1,   SQLT_INT);

oci_execute($stmt);
Как выглядит код функции?

CREATE TYPE TR_ACCOUNT IS RECORD (
   fiUser_id NUMBER(10),
   fsCurrency_code VARCHAR2(3),
   fxBalance NUMBER(10,2)
);

CREATE FUNCTION GET_ACCOUNT_INFO (
  piAccount_id NUMBER
) RETURN TR_ACCOUNT IS
BEGIN
  /* ... */
END;
Как выглядит вызов функции?

<?php

$query = <<<QUERY
DECLARE
  vrAccount BILLING.ACCOUNT;
BEGIN
  vrAccount := BILLING.GET_ACCOUNT_INFO(:piAccount_id);

  :piUser_id       := vrAccount.fiUser_id;
  :psCurrency_code := vrAccount.psCurrency_code;
  :pxBalance       := vrAccount.pxbalance;
END;
QUERY;

$stmt = oci_parse($conn, $query);

oci_bind_by_name($stmt,    ':piAccount_id',      $account_id,   -1, SQLT_INT);
oci_bind_by_name($stmt,    ':piUser_id',         $user_id,      -1, SQLT_INT);
oci_bind_by_name($stmt,    ':psCurrency_code',   $currency_code, 3, SQLT_CHR);
oci_bind_by_name($stmt,    ':pxBalance',         $balance,      22, SQLT_LNG);

oci_execute($stmt);

$result = array(
  'account_id'      =>   $account_id,
  'user_id'         =>   $user_id,
  'currency_code'   =>   $currency_code,
  'balance'         =>   $balance,
);
Как выглядит код функции?

CREATE TYPE TN_ACCOUNTS IS TABLE OF TR_ACCOUNT;

CREATE FUNCTION GET_ACCOUNTS(
  piUser_id NUMBER DEFAULT NULL
) RETURN TN_ACCOUNTS PIPELINED IS
BEGIN
  /* ... */
END;
Как выглядит вызов функции?

<?php

$query = <<<QUERY
SELECT
  *
FROM
  TABLE(BILLING.GET_ACCOUNTS(:piUser_id))
END;
QUERY;

$stmt = oci_parse($conn, $query);

oci_bind_by_name($stmt, ':piUser_id', $user_id, -1, SQLT_INT);

oci_execute($stmt);

oci_fetch_all($stmt, $result);
Рутину нужно
                 автоматизировать
Необходимо определить:
1. Наименования функций и
   процедур
2. Наименования и типы
   аргументов
3. Типы возвращаемых
   значений
4. Структуру табличных
   типов
Как получить описание
                  интерфейса в Oracle?
  SELECT
           PACKAGE_NAME, OBJECT_NAME, POSITION,
           DATA_LEVEL, ARGUMENT_NAME, DATA_TYPE,
           DATA_LENGTH, DEFAULTED, IN_OUT, TYPE_NAME,
           TYPE_SUBNAME
    FROM
           USER_ARGUMENTS
   WHERE
           PACKAGE_NAME = 'MY_PACKAGE'
ORDER BY
           PACKAGE_NAME, OBJECT_NAME, SEQUENCE, POSITION,
           DATA_LEVEL;
Обход графа объектов

Package

                            Types

  Procedures
                                    TR_ACCOUNT
      GET_ACCOUNT
                                        fiUser_id
           ptrResult
                                        fsCurrency_code
           piAccount_id
                                        fxBalance
           TR_ACCOUNT
           S
      GET_ACCOUNTS                  TN_ACCOUNTS


           ptnResult

           piUser_id

          TN_ACCOUNTS
          S
      UPDATE_ACCOUNT

               TR_ACCOUNT
PACKAGE_NAME
                                        Разбор результатов




                                                                                                                                                   TYPE_SUBNAME
                                                                  ARGUMENT_NA
                        OBJECT_NAME




                                                                                                   DATA_LENGTH
                                                 DATA_LEVEL




                                                                                                                                       TYPE_NAME
                                                                                                                 DEFAULTED
                                                                                       DATA_TYPE
                                      POSITION




                                                                                                                              IN_OUT
                                                                  ME
BILLING           CREATE_NUMBER          1             0      ACCOUNT_ID        BINARY_INTEGER                   N           IN

BILLING           CREATE_NUMBER          2             0      PLAN_ID           BINARY_INTEGER                   N           IN

BILLING           CREATE_NUMBER          3             0      NUMBER            BINARY_INTEGER                   N           IN

BILLING           CREATE_NUMBER          4             0      BEGIN_TIME        DATE                             N           IN

BILLING           CREATE_NUMBER          5             0      PRODUCT_ID        NUMBER                     22    N           OUT

BILLING           CREATE_NUMBER          6             0      LOGIN             VARCHAR2                         N           OUT

BILLING           CREATE_NUMBER          7             0      PASSWORD          VARCHAR2                         N           OUT
Разбор результатов
<?php

class Billing
{
  public function createNumber($account_id,
    $plan_id, $number, $begin_time,
    &$product_id, &$login, &$password)
  {
    /* implementation goes here */
  }
}
Разбор результатов


                                         DATA_LEVEL




                                                               ARGUMENT_
  PACKAGE_N




                                                                                                                                   TYPE_NAME
                                                                                               DATA_LENG
                  OBJECT_NA




                                                                                                           DEFAULTED




                                                                                                                                                 TYPE_SUBN
                                                                                   DATA_TYPE
                              POSITION




                                                                                                                        IN_OUT
                                                               NAME
  AME




                                                                                                                                                 AME
                  ME




                                                                                               TH
                                                                                                                                 BILLIN        TN_NUMBE
BILLING       GET_NUMBERS       0            0                             TABLE                           N           OUT
                                                                                                                                 G             RS
                                                                                                                                 BILLIN        TR_NUMBE
BILLING       GET_NUMBERS       1            1                             PL/SQL RECORD                   N           OUT
                                                                                                                                 G             R

BILLING       GET_NUMBERS       1            2        NUMBER_ID            NUMBER                22        N           OUT

BILLING       GET_NUMBERS       2            2        NUMBER               VARCHAR2              20        N           OUT

BILLING       GET_NUMBERS       3            2        BEAUTY_RATING_ID     NUMBER                22        N           OUT

BILLING       GET_NUMBERS       4            2        BEAUTY_RATING        VARCHAR2              20        N           OUT

BILLING       GET_NUMBERS       5            2        CATEGORY_ID          NUMBER                22        N           OUT

BILLING       GET_NUMBERS       1            0        PREFIX               VARCHAR2                        Y           IN

BILLING       GET_NUMBERS       2            0        BEAUTY_RATING_ID     NUMBER                22        Y           IN

BILLING       GET_NUMBERS       3            0        CATEGORY_ID          NUMBER                22        Y           IN
Разбор результатов
<?php

class Billing
{
  public function getNumbers($prefix,
    $beauty_rating_id = null, $category_id = null)
  {
    /* implementation goes here */
  }
}
Что получается в итоге?

• Один класс для пакета — «Фасад»
• По одному классу для каждой процедуры
• Ленивая загрузка
  (Zend_Loader_PluginLoader).
• Дополнительные плагины
Когда уже будет про Zend
                Framework?

• Zend_Tool_*
• My_Tool_Provider_DbIntf
• Zend_Application_Resource_Multidb
• My_Application_Resource_DbIntf
• Zend_CodeGenerator_*
Но не всѐ так просто

• Необязательные аргументы
 В зависимости от количества переданных
 аргументов нужно формировать
 соответствующий ему код SQL-запроса.

• Передача переменных по ссылке
 Перегрузка методов в PHP не позволяет
 передавать переменные по ссылке, поэтому
 для таких методов перегрузку использовать
 нельзя.
Повторное использование
                         запросов

<?php

function get_users(Zend_Db_Select $select = null)
{
  if (null === $select) {
    $select = Zend_Db_Select();
  }

    return $select
      ->from('users')
      ->query()
      ->fetchAll();
}
Что ещѐ можно
               автоматизировать?

• Обработка исключительных ситуаций:
  • Код ошибки
  • Маркер: поле, индекс, триггер и т. д.
• Форматирование и разбор дат
• Репликация master-slave
Переход на PostgreSQL

• По-другому получаем описание
  интерфейса
• Другой синтаксис вызова процедур
• Описание табличных типов в конечном
  итоге не нужно
Численные показатели

• Сроки
  – Две недели на прототип идеи
  – Полтора года активной разработки
  – Две недели на переход на PostgreSQL*
   * только вызовы процедур

• Код
  – Написано 621 NCLOC
  – Сгенерировано 7415 NCLOC*
   * для 150-ти процедур
Конец

More Related Content

Viewers also liked

TUGAS SEMINAR AKUNTANSI KELAS AK2 08 UNISMUH
TUGAS SEMINAR AKUNTANSI KELAS AK2 08 UNISMUHTUGAS SEMINAR AKUNTANSI KELAS AK2 08 UNISMUH
TUGAS SEMINAR AKUNTANSI KELAS AK2 08 UNISMUHiman18
 
Michael Campana - From Central American to South Caucus: Water Resources in D...
Michael Campana - From Central American to South Caucus: Water Resources in D...Michael Campana - From Central American to South Caucus: Water Resources in D...
Michael Campana - From Central American to South Caucus: Water Resources in D...engineerou
 
Feleke Zewge - Fluorosis Mitigation in Ethiopia
Feleke Zewge - Fluorosis Mitigation in EthiopiaFeleke Zewge - Fluorosis Mitigation in Ethiopia
Feleke Zewge - Fluorosis Mitigation in Ethiopiaengineerou
 
MongoDB. Области применения, преимущества и узкие места, тонкости использован...
MongoDB. Области применения, преимущества и узкие места, тонкости использован...MongoDB. Области применения, преимущества и узкие места, тонкости использован...
MongoDB. Области применения, преимущества и узкие места, тонкости использован...phpdevby
 
Использование AMQP в основе архитектуры бэкенда для мобильного приложения
Использование AMQP в основе архитектуры бэкенда для мобильного приложенияИспользование AMQP в основе архитектуры бэкенда для мобильного приложения
Использование AMQP в основе архитектуры бэкенда для мобильного приложенияphpdevby
 
Dr. Richard Taylor - Groundwater-climate interactions: current challenges & n...
Dr. Richard Taylor - Groundwater-climate interactions: current challenges & n...Dr. Richard Taylor - Groundwater-climate interactions: current challenges & n...
Dr. Richard Taylor - Groundwater-climate interactions: current challenges & n...engineerou
 
Dr. David Dzombak - Need and Challenge of Alternative Water Sources for use i...
Dr. David Dzombak - Need and Challenge of Alternative Water Sources for use i...Dr. David Dzombak - Need and Challenge of Alternative Water Sources for use i...
Dr. David Dzombak - Need and Challenge of Alternative Water Sources for use i...engineerou
 
Как удержать проект от анархии с помощью Git
Как удержать проект от анархии с помощью GitКак удержать проект от анархии с помощью Git
Как удержать проект от анархии с помощью Gitphpdevby
 
Dr. Menachem Elimelech - Water Technologies to Solve Increasing Global Water ...
Dr. Menachem Elimelech - Water Technologies to Solve Increasing Global Water ...Dr. Menachem Elimelech - Water Technologies to Solve Increasing Global Water ...
Dr. Menachem Elimelech - Water Technologies to Solve Increasing Global Water ...engineerou
 

Viewers also liked (9)

TUGAS SEMINAR AKUNTANSI KELAS AK2 08 UNISMUH
TUGAS SEMINAR AKUNTANSI KELAS AK2 08 UNISMUHTUGAS SEMINAR AKUNTANSI KELAS AK2 08 UNISMUH
TUGAS SEMINAR AKUNTANSI KELAS AK2 08 UNISMUH
 
Michael Campana - From Central American to South Caucus: Water Resources in D...
Michael Campana - From Central American to South Caucus: Water Resources in D...Michael Campana - From Central American to South Caucus: Water Resources in D...
Michael Campana - From Central American to South Caucus: Water Resources in D...
 
Feleke Zewge - Fluorosis Mitigation in Ethiopia
Feleke Zewge - Fluorosis Mitigation in EthiopiaFeleke Zewge - Fluorosis Mitigation in Ethiopia
Feleke Zewge - Fluorosis Mitigation in Ethiopia
 
MongoDB. Области применения, преимущества и узкие места, тонкости использован...
MongoDB. Области применения, преимущества и узкие места, тонкости использован...MongoDB. Области применения, преимущества и узкие места, тонкости использован...
MongoDB. Области применения, преимущества и узкие места, тонкости использован...
 
Использование AMQP в основе архитектуры бэкенда для мобильного приложения
Использование AMQP в основе архитектуры бэкенда для мобильного приложенияИспользование AMQP в основе архитектуры бэкенда для мобильного приложения
Использование AMQP в основе архитектуры бэкенда для мобильного приложения
 
Dr. Richard Taylor - Groundwater-climate interactions: current challenges & n...
Dr. Richard Taylor - Groundwater-climate interactions: current challenges & n...Dr. Richard Taylor - Groundwater-climate interactions: current challenges & n...
Dr. Richard Taylor - Groundwater-climate interactions: current challenges & n...
 
Dr. David Dzombak - Need and Challenge of Alternative Water Sources for use i...
Dr. David Dzombak - Need and Challenge of Alternative Water Sources for use i...Dr. David Dzombak - Need and Challenge of Alternative Water Sources for use i...
Dr. David Dzombak - Need and Challenge of Alternative Water Sources for use i...
 
Как удержать проект от анархии с помощью Git
Как удержать проект от анархии с помощью GitКак удержать проект от анархии с помощью Git
Как удержать проект от анархии с помощью Git
 
Dr. Menachem Elimelech - Water Technologies to Solve Increasing Global Water ...
Dr. Menachem Elimelech - Water Technologies to Solve Increasing Global Water ...Dr. Menachem Elimelech - Water Technologies to Solve Increasing Global Water ...
Dr. Menachem Elimelech - Water Technologies to Solve Increasing Global Water ...
 

Similar to Сайт на Zend Framework в составе промышленной системы

ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)ZFConf Conference
 
Аспектно-Ориентированный Подход
Аспектно-Ориентированный ПодходАспектно-Ориентированный Подход
Аспектно-Ориентированный Подходakopium
 
Meet Magento Belarus debug Pavel Novitsky (rus)
Meet Magento Belarus debug Pavel Novitsky (rus)Meet Magento Belarus debug Pavel Novitsky (rus)
Meet Magento Belarus debug Pavel Novitsky (rus)Pavel Novitsky
 
Yii2
Yii2Yii2
Yii2Noveo
 
Magento code debugging
Magento code debuggingMagento code debugging
Magento code debuggingaheadWorks
 
Клиент-серверное взаимодействие под android в деталях
Клиент-серверное взаимодействие под android в деталяхКлиент-серверное взаимодействие под android в деталях
Клиент-серверное взаимодействие под android в деталяхKirill Zotin
 
Обзор платформы B4
Обзор платформы B4Обзор платформы B4
Обзор платформы B4Bars Group
 
Kirill Zotin клиент серверное взаимодействие под android в деталях
Kirill Zotin клиент серверное взаимодействие под android в деталяхKirill Zotin клиент серверное взаимодействие под android в деталях
Kirill Zotin клиент серверное взаимодействие под android в деталяхDneprCiklumEvents
 
kranonitS20 Сергей Бурма. Django - легко, быстро, эффективно
kranonitS20 Сергей Бурма. Django - легко, быстро, эффективноkranonitS20 Сергей Бурма. Django - легко, быстро, эффективно
kranonitS20 Сергей Бурма. Django - легко, быстро, эффективноKrivoy Rog IT Community
 
Индексирование в Magento
Индексирование в MagentoИндексирование в Magento
Индексирование в MagentoMagecom Ukraine
 
Intersystems Cache - Как не загреметь в долговую яму
Intersystems Cache - Как не загреметь в долговую ямуIntersystems Cache - Как не загреметь в долговую яму
Intersystems Cache - Как не загреметь в долговую ямуDenis Pavlov
 
Enterprise Patterns in Magento
Enterprise Patterns in MagentoEnterprise Patterns in Magento
Enterprise Patterns in MagentoVrann Tulika
 
Создание повторно используемых бизнес моделей с помощью технологии Domain Com...
Создание повторно используемых бизнес моделей с помощью технологии Domain Com...Создание повторно используемых бизнес моделей с помощью технологии Domain Com...
Создание повторно используемых бизнес моделей с помощью технологии Domain Com...GetDev.NET
 
Knockoutjs на примере 2ГИС-Онлайн
Knockoutjs на примере 2ГИС-ОнлайнKnockoutjs на примере 2ГИС-Онлайн
Knockoutjs на примере 2ГИС-Онлайн2ГИС Технологии
 
Web осень 2013 лекция 6
Web осень 2013 лекция 6Web осень 2013 лекция 6
Web осень 2013 лекция 6Technopark
 

Similar to Сайт на Zend Framework в составе промышленной системы (17)

ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)
 
Аспектно-Ориентированный Подход
Аспектно-Ориентированный ПодходАспектно-Ориентированный Подход
Аспектно-Ориентированный Подход
 
Meet Magento Belarus debug Pavel Novitsky (rus)
Meet Magento Belarus debug Pavel Novitsky (rus)Meet Magento Belarus debug Pavel Novitsky (rus)
Meet Magento Belarus debug Pavel Novitsky (rus)
 
Yii2
Yii2Yii2
Yii2
 
Magento code debugging
Magento code debuggingMagento code debugging
Magento code debugging
 
Клиент-серверное взаимодействие под android в деталях
Клиент-серверное взаимодействие под android в деталяхКлиент-серверное взаимодействие под android в деталях
Клиент-серверное взаимодействие под android в деталях
 
Обзор платформы B4
Обзор платформы B4Обзор платформы B4
Обзор платформы B4
 
Kirill Zotin клиент серверное взаимодействие под android в деталях
Kirill Zotin клиент серверное взаимодействие под android в деталяхKirill Zotin клиент серверное взаимодействие под android в деталях
Kirill Zotin клиент серверное взаимодействие под android в деталях
 
kranonitS20 Сергей Бурма. Django - легко, быстро, эффективно
kranonitS20 Сергей Бурма. Django - легко, быстро, эффективноkranonitS20 Сергей Бурма. Django - легко, быстро, эффективно
kranonitS20 Сергей Бурма. Django - легко, быстро, эффективно
 
Индексирование в Magento
Индексирование в MagentoИндексирование в Magento
Индексирование в Magento
 
Ci
CiCi
Ci
 
Intersystems Cache - Как не загреметь в долговую яму
Intersystems Cache - Как не загреметь в долговую ямуIntersystems Cache - Как не загреметь в долговую яму
Intersystems Cache - Как не загреметь в долговую яму
 
Enterprise Patterns in Magento
Enterprise Patterns in MagentoEnterprise Patterns in Magento
Enterprise Patterns in Magento
 
Создание повторно используемых бизнес моделей с помощью технологии Domain Com...
Создание повторно используемых бизнес моделей с помощью технологии Domain Com...Создание повторно используемых бизнес моделей с помощью технологии Domain Com...
Создание повторно используемых бизнес моделей с помощью технологии Domain Com...
 
Knockoutjs на примере 2ГИС-Онлайн
Knockoutjs на примере 2ГИС-ОнлайнKnockoutjs на примере 2ГИС-Онлайн
Knockoutjs на примере 2ГИС-Онлайн
 
Aspect Oriented Approach
Aspect Oriented ApproachAspect Oriented Approach
Aspect Oriented Approach
 
Web осень 2013 лекция 6
Web осень 2013 лекция 6Web осень 2013 лекция 6
Web осень 2013 лекция 6
 

Сайт на Zend Framework в составе промышленной системы

  • 1. Сайт на Zend Framework в составе промышленной системы Сергей Морозов, Минск 2012
  • 3. Отдельно стоящий сайт Внешение ресурсы • БД принадлежит только сайту. Бизнес-логика • Неограниченные привилегии. Представление • Сайт разграничивает База данных права пользователей.
  • 4. Сайт в составе промышленной системы Биллинг • БД обслуживает Коммутатор несколько приложений База данных • Повышенные требова- Инженерное ПО ния к безопасности • Максимально Сервер ограниченные права клиентских приложений Сайт
  • 5. Разграничение прав доступа средствами БД • Базы данных • Таблицы • Поля
  • 6. Чего не хватает? • Разграничения на доступ к записям • Прочих ограничений, обусловленных бизнес-логикой
  • 7. Ну например? Если у пользователя есть права на выполнение запроса SELECT id FROM users WHERE login = :login AND password = SOME_SECRET_ALG(:password, :salt) , значит он может выполнить и SELECT id, login, password FROM users
  • 8. Как быть? • Запретить доступ к таблицам напрямую • Предоставить абстрактный интерфейс в виде пакетов хранимых процедур
  • 9. Как будто ООП БАЗА ДАННЫХ ПРИЛОЖЕНИЕ Таблицы Данные Пакет 1 Класс 1 процедура_1_1 метод_1_1 процедура_1_2 метод_1_2 Пакет 2 Класс 2 процедура_2_1 метод _2_1 процедура_2_2 метод _2_2
  • 10. Преимущества подхода • Централизованное разграничение прав доступа • Инкапсуляция • Разделение труда
  • 11. Недостатки подхода • Бюрократия • Сложность реализации • Отсутствие чѐтких границ
  • 12. Как выглядит код процедуры? CREATE PROCEDURE AUTHENTICATE( psUsername IN VARCHAR2, psPassword IN VARCHAR2, viAccount_id OUT PLS_INTEGER, viStatus OUT VARCHAR2 ) BEGIN SELECT fiAccount_id, fiStatus INTO viAccount_id, viStatus FROM users WHERE fsUsername = psUsername AND fsPassword = SOME_SECRET_ALG(psPassword, 'some salt') END;
  • 13. Как выглядит вызов процедуры? <?php $query = <<<QUERY BEGIN AUTH.AUTHENTICATE(:psUsername, :psPassword, :piAccount_id, :piStatus); END QUERY; $stmt = oci_parse($conn, $query); oci_bind_by_name($stmt, ':psUsername', $username, 32, SQLT_CHR); oci_bind_by_name($stmt, ':psPassword', $password, 32, SQLT_CHR); oci_bind_by_name($stmt, ':piAccount_id', $account_id, -1, SQLT_INT); oci_bind_by_name($stmt, ':piStatus', $status, -1, SQLT_INT); oci_execute($stmt);
  • 14. Как выглядит код функции? CREATE TYPE TR_ACCOUNT IS RECORD ( fiUser_id NUMBER(10), fsCurrency_code VARCHAR2(3), fxBalance NUMBER(10,2) ); CREATE FUNCTION GET_ACCOUNT_INFO ( piAccount_id NUMBER ) RETURN TR_ACCOUNT IS BEGIN /* ... */ END;
  • 15. Как выглядит вызов функции? <?php $query = <<<QUERY DECLARE vrAccount BILLING.ACCOUNT; BEGIN vrAccount := BILLING.GET_ACCOUNT_INFO(:piAccount_id); :piUser_id := vrAccount.fiUser_id; :psCurrency_code := vrAccount.psCurrency_code; :pxBalance := vrAccount.pxbalance; END; QUERY; $stmt = oci_parse($conn, $query); oci_bind_by_name($stmt, ':piAccount_id', $account_id, -1, SQLT_INT); oci_bind_by_name($stmt, ':piUser_id', $user_id, -1, SQLT_INT); oci_bind_by_name($stmt, ':psCurrency_code', $currency_code, 3, SQLT_CHR); oci_bind_by_name($stmt, ':pxBalance', $balance, 22, SQLT_LNG); oci_execute($stmt); $result = array( 'account_id' => $account_id, 'user_id' => $user_id, 'currency_code' => $currency_code, 'balance' => $balance, );
  • 16. Как выглядит код функции? CREATE TYPE TN_ACCOUNTS IS TABLE OF TR_ACCOUNT; CREATE FUNCTION GET_ACCOUNTS( piUser_id NUMBER DEFAULT NULL ) RETURN TN_ACCOUNTS PIPELINED IS BEGIN /* ... */ END;
  • 17. Как выглядит вызов функции? <?php $query = <<<QUERY SELECT * FROM TABLE(BILLING.GET_ACCOUNTS(:piUser_id)) END; QUERY; $stmt = oci_parse($conn, $query); oci_bind_by_name($stmt, ':piUser_id', $user_id, -1, SQLT_INT); oci_execute($stmt); oci_fetch_all($stmt, $result);
  • 18. Рутину нужно автоматизировать Необходимо определить: 1. Наименования функций и процедур 2. Наименования и типы аргументов 3. Типы возвращаемых значений 4. Структуру табличных типов
  • 19. Как получить описание интерфейса в Oracle? SELECT PACKAGE_NAME, OBJECT_NAME, POSITION, DATA_LEVEL, ARGUMENT_NAME, DATA_TYPE, DATA_LENGTH, DEFAULTED, IN_OUT, TYPE_NAME, TYPE_SUBNAME FROM USER_ARGUMENTS WHERE PACKAGE_NAME = 'MY_PACKAGE' ORDER BY PACKAGE_NAME, OBJECT_NAME, SEQUENCE, POSITION, DATA_LEVEL;
  • 20. Обход графа объектов Package Types Procedures TR_ACCOUNT GET_ACCOUNT fiUser_id ptrResult fsCurrency_code piAccount_id fxBalance TR_ACCOUNT S GET_ACCOUNTS TN_ACCOUNTS ptnResult piUser_id TN_ACCOUNTS S UPDATE_ACCOUNT TR_ACCOUNT
  • 21. PACKAGE_NAME Разбор результатов TYPE_SUBNAME ARGUMENT_NA OBJECT_NAME DATA_LENGTH DATA_LEVEL TYPE_NAME DEFAULTED DATA_TYPE POSITION IN_OUT ME BILLING CREATE_NUMBER 1 0 ACCOUNT_ID BINARY_INTEGER N IN BILLING CREATE_NUMBER 2 0 PLAN_ID BINARY_INTEGER N IN BILLING CREATE_NUMBER 3 0 NUMBER BINARY_INTEGER N IN BILLING CREATE_NUMBER 4 0 BEGIN_TIME DATE N IN BILLING CREATE_NUMBER 5 0 PRODUCT_ID NUMBER 22 N OUT BILLING CREATE_NUMBER 6 0 LOGIN VARCHAR2 N OUT BILLING CREATE_NUMBER 7 0 PASSWORD VARCHAR2 N OUT
  • 22. Разбор результатов <?php class Billing { public function createNumber($account_id, $plan_id, $number, $begin_time, &$product_id, &$login, &$password) { /* implementation goes here */ } }
  • 23. Разбор результатов DATA_LEVEL ARGUMENT_ PACKAGE_N TYPE_NAME DATA_LENG OBJECT_NA DEFAULTED TYPE_SUBN DATA_TYPE POSITION IN_OUT NAME AME AME ME TH BILLIN TN_NUMBE BILLING GET_NUMBERS 0 0 TABLE N OUT G RS BILLIN TR_NUMBE BILLING GET_NUMBERS 1 1 PL/SQL RECORD N OUT G R BILLING GET_NUMBERS 1 2 NUMBER_ID NUMBER 22 N OUT BILLING GET_NUMBERS 2 2 NUMBER VARCHAR2 20 N OUT BILLING GET_NUMBERS 3 2 BEAUTY_RATING_ID NUMBER 22 N OUT BILLING GET_NUMBERS 4 2 BEAUTY_RATING VARCHAR2 20 N OUT BILLING GET_NUMBERS 5 2 CATEGORY_ID NUMBER 22 N OUT BILLING GET_NUMBERS 1 0 PREFIX VARCHAR2 Y IN BILLING GET_NUMBERS 2 0 BEAUTY_RATING_ID NUMBER 22 Y IN BILLING GET_NUMBERS 3 0 CATEGORY_ID NUMBER 22 Y IN
  • 24. Разбор результатов <?php class Billing { public function getNumbers($prefix, $beauty_rating_id = null, $category_id = null) { /* implementation goes here */ } }
  • 25. Что получается в итоге? • Один класс для пакета — «Фасад» • По одному классу для каждой процедуры • Ленивая загрузка (Zend_Loader_PluginLoader). • Дополнительные плагины
  • 26. Когда уже будет про Zend Framework? • Zend_Tool_* • My_Tool_Provider_DbIntf • Zend_Application_Resource_Multidb • My_Application_Resource_DbIntf • Zend_CodeGenerator_*
  • 27. Но не всѐ так просто • Необязательные аргументы В зависимости от количества переданных аргументов нужно формировать соответствующий ему код SQL-запроса. • Передача переменных по ссылке Перегрузка методов в PHP не позволяет передавать переменные по ссылке, поэтому для таких методов перегрузку использовать нельзя.
  • 28. Повторное использование запросов <?php function get_users(Zend_Db_Select $select = null) { if (null === $select) { $select = Zend_Db_Select(); } return $select ->from('users') ->query() ->fetchAll(); }
  • 29. Что ещѐ можно автоматизировать? • Обработка исключительных ситуаций: • Код ошибки • Маркер: поле, индекс, триггер и т. д. • Форматирование и разбор дат • Репликация master-slave
  • 30. Переход на PostgreSQL • По-другому получаем описание интерфейса • Другой синтаксис вызова процедур • Описание табличных типов в конечном итоге не нужно
  • 31. Численные показатели • Сроки – Две недели на прототип идеи – Полтора года активной разработки – Две недели на переход на PostgreSQL* * только вызовы процедур • Код – Написано 621 NCLOC – Сгенерировано 7415 NCLOC* * для 150-ти процедур