32
Сайт на Zend Framework в составе промышленной системы Сергей Морозов, Минск 2012

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

Embed Size (px)

Citation preview

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

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

Сергей Морозов, Минск 2012

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

Сайты бывают разные

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

Отдельно стоящий сайт

• БД принадлежит только

сайту.

• Неограниченные

привилегии.

• Сайт разграничивает

права пользователей.

База данных

Бизнес-логика

Представление

Внешение ресурсы

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

Сайт в составе

промышленной системы

• БД обслуживает

несколько приложений

• Повышенные требова-

ния к безопасности

• Максимально

ограниченные права

База данных

Коммутатор

Биллинг

Инженерное ПО

Сервер

клиентских приложений

Сайт

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

Разграничение прав доступа

средствами БД

• Базы

данных

• Таблицы

• Поля

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

Чего не хватает?

• Разграничения на

доступ к записям

• Прочих

ограничений,

обусловленных

бизнес-логикой

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

Ну например?

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

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

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

Как быть?

• Запретить доступ к таблицам напрямую

• Предоставить абстрактный интерфейс в виде

пакетов хранимых процедур

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

Как будто ООП

Таблицы

БАЗА ДАННЫХ

Пакет 1

процедура_1_1

процедура_1_2

Пакет 2

процедура_2_1

процедура_2_2

Данные

ПРИЛОЖЕНИЕ

Класс 1

метод_1_1

метод_1_2

Класс 2

метод _2_1

метод _2_2

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

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

• Централизованное

разграничение прав

доступа

• Инкапсуляция

• Разделение труда

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

Недостатки подхода

• Бюрократия

• Сложность

реализации

• Отсутствие чѐтких

границ

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

Как выглядит код процедуры?

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;

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

Как выглядит вызов

процедуры?

<?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);

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

Как выглядит код функции?

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;

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

Как выглядит вызов функции?

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

);

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

Как выглядит код функции?

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;

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

Как выглядит вызов функции?

<?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);

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

Необходимо определить: 1. Наименования функций и

процедур 2. Наименования и типы

аргументов 3. Типы возвращаемых

значений 4. Структуру табличных

типов

Рутину нужно

автоматизировать

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

Как получить описание

интерфейса в 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;

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

Обход графа объектов

Package

Procedures

Types

GET_ACCOUNT

ptrResult

piAccount_id

TR_ACCOUNT

S GET_ACCOUNTS

ptnResult

piUser_id

TN_ACCOUNTS

S UPDATE_ACCOUNT

TR_ACCOUNT

TR_ACCOUNT

fiUser_id

fsCurrency_code

fxBalance

TN_ACCOUNTS

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

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

AC

KA

GE

_N

AM

E

OB

JE

CT

_N

AM

E

PO

SIT

ION

DA

TA

_L

EV

EL

AR

GU

ME

NT

_N

A

ME

DA

TA

_T

YP

E

DA

TA

_L

EN

GT

H

DE

FA

UL

TE

D

IN_O

UT

TY

PE

_N

AM

E

TY

PE

_S

UB

NA

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

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

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

<?php class Billing { public function createNumber($account_id, $plan_id, $number, $begin_time, &$product_id, &$login, &$password) { /* implementation goes here */ } }

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

PA

CK

AG

E_N

AM

E

OB

JE

CT

_N

A

ME

PO

SIT

ION

DA

TA

_L

EV

EL

AR

GU

ME

NT

_

NA

ME

DA

TA

_T

YP

E

DA

TA

_L

EN

G

TH

DE

FA

UL

TE

D

IN_O

UT

TY

PE

_N

AM

E

TY

PE

_S

UB

N

AM

E

BILLING GET_NUMBERS 0 0 TABLE N OUT BILLIN

G

TN_NUMBE

RS

BILLING GET_NUMBERS 1 1 PL/SQL RECORD N OUT BILLIN

G

TR_NUMBE

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

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

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

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

<?php class Billing { public function getNumbers($prefix,

$beauty_rating_id = null, $category_id = null) { /* implementation goes here */ } }

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

• Один класс для пакета — «Фасад»

• По одному классу для каждой процедуры

• Ленивая загрузка (Zend_Loader_PluginLoader).

• Дополнительные плагины

Что получается в итоге?

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

Когда уже будет про Zend

Framework?

• Zend_Tool_*

• My_Tool_Provider_DbIntf

• Zend_Application_Resource_Multidb

• My_Application_Resource_DbIntf

• Zend_CodeGenerator_*

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

Но не всѐ так просто

• Необязательные аргументы В зависимости от количества переданных

аргументов нужно формировать

соответствующий ему код SQL-запроса.

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

передавать переменные по ссылке, поэтому

для таких методов перегрузку использовать

нельзя.

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

Повторное использование

запросов

<?php

function get_users(Zend_Db_Select $select = null) { if (null === $select) { $select = Zend_Db_Select(); } return $select ->from('users') ->query() ->fetchAll(); }

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

• Обработка исключительных ситуаций:

• Код ошибки

• Маркер: поле, индекс, триггер и т. д.

• Форматирование и разбор дат

• Репликация master-slave

Что ещѐ можно

автоматизировать?

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

Переход на PostgreSQL

• По-другому получаем описание

интерфейса

• Другой синтаксис вызова процедур

• Описание табличных типов в конечном

итоге не нужно

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

Численные показатели

• Сроки

– Две недели на прототип идеи

– Полтора года активной разработки

– Две недели на переход на PostgreSQL* * только вызовы процедур

• Код

– Написано 621 NCLOC

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

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

Конец