1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/hylun-lua-resty-yii

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
README.md 28 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 29.11.2024 12:32 07217c4

Lua-resty-yii

Сетевой фреймворк, основанный на OpenResty Imitation Yii, через этот фреймворк можно значительно снизить порог вхождения в разработку openresty. 中文

Системные требования

Установите OpenResty 1.0+ https://openresty.org/en/download.html

Быстрый старт

  • Linux OS: Измените путь /usr/local/openresty/bin/openresty в вашем runtime/start.sh на путь вашего openresty.

    • Вначале выполните команду bash CD в текущий каталог и выполните: runtime/start.sh.
    • Остановите выполнение, перейдите в текущий каталог, выполните: runtime/stop.sh.
  • Windows: Измените runtime/start.bat в d:\openresty-1.11.2.2--Win32\ на путь вашей установленной версии openresty.

    • Запустите, дважды щёлкнув: runtime/win-start.bat.
    • Остановитесь, дважды щёлкните: runtime/win-stop.bat.

Инструкции по разработке

Структура приложения

| | index.lua # файл входа | lua-releng # проверка качества кода / использование глобальных переменных | config # каталог файлов конфигурации | | :-- |:--:| --:| | db.lua # конфигурация базы данных | lang.lua # настройка языкового пакета | memcache.lua # конфигурация memcache | | session.lua #конфигурация сессии | web.lua # базовая информация о сайте | Controller #каталог контроллеров | | site.lua # главная страница | Model #каталог моделей | runtime # каталог запуска Openresty | | LoginForm.lua # класс логической обработки входа | Userinfo.lua #класс управления пользовательской информацией | Logs # каталог журналов сайта | | access.log # журнал запросов | error.log #журнал ошибок | nginx.pid #файл процесса nginx | | nginx.conf # конфигурационный файл сайта nginx | proxy_temp #proxy_temp | scgi_temp #scgi_temp | | start.sh # запуск сайта | stop.sh # остановка программы | uwsgi_temp #uwsgi_temp | | vendor #фреймворк и сторонние классы | ActiveRecord.lua # базовый класс обработки базы данных | Application.lua # класс обработки запросов | | Controller.lua #базовый класс контроллера | Files.lua # класс получения файла загрузки | Memcache.lua #операционный класс memcache | | Model.lua #модельный базовый класс | Mysql.lua #операционный класс mysql | Pager.lua #классы пейджинга | | Query.lua #конструктор запросов | Request.lua #инструмент класса информации запроса | resty # сторонние инструменты resty | | http.lua # инструмент запроса http | template.lua #инструменты шаблона lua | Session.lua #класс действий сеанса | | User.lua #информационный класс пользователя | Util.lua #основные инструменты | views # каталог шаблонов страниц | | layout #каталог фреймов страниц | main.lua.html # основная структура сайта | site #каталог страниц сайта | | error.lua.html #страница сообщения об ошибке | guide.lua.html # страница примечаний к разработке | index.lua.html #главная | | login.lua.html #страница входа | web # каталог статических ресурсов | css #стиль | | bootstrap-theme.css #bootstrap | bootstrap-theme.min.css #bootstrap | bootstrap.css #bootstrap | | bootstrap.min.cs #bootstrap | site.css #стиль сайта | js #javascript | | bootstrap.js #bootstrap | bootstrap.min.js #bootstrap | jquery.js #jquery | | jquery.min.js #jquery | jquery.slim.js #jquery | jquery.slim.min.js #jquery | | favicon.ico #значок | robots.txt #robots.txt | |

Обзор механизма работы

Каждый раз, когда приложение начинает обрабатывать HTTP-запрос, оно выполняет приблизительный процесс.

--Пользователь отправляет запрос на скрипт входа index.lua --Скрипт входа создаёт экземпляр Application для обработки. Запрос и загрузка конфигурации

— Приложение анализирует запрошенный маршрут через компонент приложения запроса.

— Приложению необходимо создать экземпляр контроллера для обработки запроса.

— Выполнить метод before() в контроллере для фильтрации запроса.

— Продолжить действие, если before() возвращает true, иначе завершить.

— Действие загрузит модель данных, обычно загружаемую из базы данных.

— Действие отображает представление и предоставляет ему необходимую модель данных.

— Отображённые результаты возвращаются компоненту приложения ответа (response).

— Компонент ответа отправляет результат обратно в браузер пользователя.

Режим отладки:

— Доступ к /lua/index будет использовать режим off lua_code_cache для доступа к сайту.

— Посещение /lua/{filepath} позволяет отладить соответствующий скрипт Lua.

Приложение

Каждый раз, когда принимается HTTP-запрос, скрипт входа index.lua создаёт экземпляр приложения для обработки запроса. После создания экземпляра приложения глобальная переменная ngx.ctx перезаписывается (для каждого запроса, соответствующего жизненному циклу глобальной переменной).

ngx.ctx = require ("vendor.Application"): new()

Когда приложение создано, оно загружает базовую конфигурацию и основные инструменты веб-сайта в качестве атрибутов, таких как:

— ngx.ctx.web эквивалентен require («config.web»), — таблица информации о конфигурации сайта;

— ngx.ctx.lang эквивалентен require («config.lang»), — информация о конфигурации языкового пакета;

— ngx.ctx.session эквивалентен require («config.session»), — класс сеанса сайта;

— ngx.ctx.user эквивалентен require («vendor.User»), — инструменты пользователя сайта;

— ngx.ctx.request эквивалентен require («vendor.Request»), — обработка запросов сайта.

При выполнении нового () приложения экземпляр контроллера наследуется от приложения, поэтому ngx.ctx является приложением, которое также является экземпляром контроллера и доступно в контроллере self.web, self.lang, self.session.self.user.self.request. Прямая ссылка на вышеуказанную конфигурацию и инструменты.

Примечание: при использовании минимизируйте использование глобальной переменной ngx.ctx, но следует передать значение функции pass, чтобы получить более высокую скорость.

Контроллер (Controller):

local _M = require("vendor.Controller"):new{_VERSION='0.01'}    --Generate a new Controller instance

function _M:indexAction()   --The action method name must be name + Action
    if not self.user.isLogin then return self:loginAction() end     --use the user information to determine whether the user login

    local Product = require('models.Product')               --Uses the Product Datasheet operation class
    local query = Product.find().where{'in','product_id',self.user.resource} --The fin() method generates a new querier

    local page = Pager{                 
        pageSize = 8,                   
        totalCount = query.count(),     
    }

    local list = query.orderBy('create_time desc').page(page).all()
    
    return self:render('index',{
        page = page,
        list = list,
    })
end

retrun _M

Если сохранить как controller / filename.lua, то доступ? ACT = filename.index, он выполнит вышеуказанный соответствующий метод indexAction().

Модель (model): Модель является частью шаблона MVC и представляет бизнес-данные, правила и логические объекты. Класс модели можно определить, унаследовав «vendor.Model» или его подклассы. Базовый класс «vendor.Model» поддерживает множество полезных функций, таких как: ``` in the login password'}, --Use custom methods to verify the parameters {'Password', 'checkPass'} --Validate using the custom checkPass method } End

Function _M: checkPass (key) If self: hasErrors() then return to the end

Local user = Userinfo.getUserByName (self.username) If not user then From: addError ('username', 'account does not exist') Elseif user.password ~ ​​= self.password Then From: addError ('password', 'wrong password') Other Self.userinfo = user End End

Function _M: login (user) If not self: validate() then returns false The company is located in: Return user.login (self.userinfo, rememberMe and 3600 * 24 * 30 or 0) End

return _M


Use in controller Model:

```lua
--Because the model contains data, be sure to call the new method to generate a new instance, to avoid data caching problems
local model = require ('models.LoginForm'): new()

--Load data automatically through model load() method
If model: load (self.request.post()) and model: login (self.user) then
Back to myself: goHome()
End

view (view):

The view is based on the [LUA-resty template (https://github.com/bungle/lua-resty-template)

The following tags must be used in the view: --{{expression}}, output the expression, and html formatted --{* expression }, the result of the expression expression is output as it is --{% lua code%}, execute Lua code* --{# comments #} All content between {# and #} is considered commented (ie not output or executed)

Unlike the normal usage of the LUA-resty template, all view files are saved as LUA files in the sub-directory with the filename *.lua.html Rendering methods in your controller When you try to render, you get the content of the view as you need it

views / layout directory storage frame view, rendering view default views / layout / main.lua.html, Controller can be set by the layout of the property to use a different frame view, such as: lua Local_M = require ("vendor.Controller"): new {layout = 'manage'}

Under the views of the other sub-directories for different functional modules corresponding to the content view, all page headers, page footers, menus and other content should be implemented in the frame view
Other views are deprecated in the content view as {(templates)}, which can cause errors such as missing files due to different default renderings

When the controller renders the view, it passes all application and controller data to the view so that it can be used directly in the view
Such as: {{lang.siteName}} output the name of the site configured in the language pack

In the view, you can set a contextual property to pass values between the content view and the frame view, such as setting:
{% Context.title = 'Development Description'%}
You can display the {{title}} output in the frame view

## request processing
### Get request parameters
lua
Local request = require ("vendor.Request")
--In the controller method can be obtained directly through self.request call

local get = request.get()
--equivalent to php: $get = $_GET;

Local id = request.get ('id');
--equivalent to php: $id = isset ($_ GET ['id'])? $_GET ['id']: null;

Local id = request.get ('id', 1)
--equivalent to php: $id = isset ($_ GET ['id'])? $_GET ['id']: 1;

Local post = request.post()
--equivalent to php: $post = $_POST;

Local name = request.post ('name')
--equivalent to php: $name = isset ($_ POST ['name'])? $_POST ['name']: null;

Local name = request.post ('name', '')
--equivalent to php: $name = isset ($_ POST ['name'])? $_POST ['name']: '';

Local cookie = request.cookie()
--equivalent to php: $cookie = $_COOKIE;

Local sso = request.cookie ('sso')
--equivalent to php: $sso = isset ($_ COOKIE ['sso'])? $_COOKIE ['sso']: null;

Local sso = request.cookie ('sso', '')
--equivalent to php: $sso = isset ($_ COOKIE ['sso'])? $_COOKIE ['sso']: '';

--Determine whether there is an upload file
ngx.say (request.isPostFile())
--Note different places with PHP, if there is an upload file, the normal parameters can not be obtained through the request.post() method
--Recommended to upload files, ### Получение общих параметров через GET

*—Получение загруженных файлов*  

Local file = required ('vendor.Files')  
Local savename = path .. filename  
  
Local ok, err = file.receive ('upfile', savename) --получение файла загрузки с именем upfile  
If not  
Return {retcode = 1, retmsg = 'Ошибка получения файла, попробуйте ещё раз:' .. err}  
End

### Установка cookie:
```lua
Local util = needs "vendor.Util"
util.set_cookie ('ABC', '123')
util.set_cookie ('HD', '456', 3600)
util.set_cookie (Name, Value, Expired, Path, Domain, Security, Http Only)

Операция с сессией:

ocal session = require "vendor.Session"
--В методе Controller можно вызвать напрямую через self.session
--session.start() --Включить сессию, установит cookie _sessionid, эту операцию можно опустить
--session.exptime = 1800 --Время сессии по умолчанию составляет 30 минут
--session.cache = ngx_shared ['session_cache'] --По умолчанию кэш ngx соответствует конфигурации lua_shared_dict в runtime / nginx.conf
--session.cache = require ("vendor.Memcache"): new {host = "127.0.0.1", port = "11211"} --Открыть эту конфигурацию с помощью memcached кэша

local sessions = session.get()
--эквивалентно php: $sessions = $_SESSION;

local abc = session.get ('abc')
--эквивалентно: local abc = session.abc
--эквивалентно: local abc = session ['abc']
--эквивалентно php: $abc = isset ($_SESSION['abc'])? $_SESSION['abc']: null;

local abc = session.get ('abc', '')
--эквивалентно php: $abc = isset ($_SESSION['abc'])? $_SESSION['abc']: '';

--установить значение сессии
session.set ('abc', 'abc-value')
--эквивалентно: session.abc = 'abc-value'
--эквивалентно: session ['abc'] = 'abc-value'

операция с базой данных (Работа с базами данных):

Доступ к базе данных (DAO):

local db = require ('vendor.Mysql'): new {
    host = "127.0.0.1",
    port = 3306,
    database = "mytest",
    user = "root",
    password = "",
    charset = "utf8", --Рекомендуется настроить Mysql по умолчанию на соединение с набором символов utf8, вы можете избавиться от этого элемента конфигурации, эта конфигурация добавит операцию 'SET NAMES utf8'
}

--Или получить его непосредственно из файла конфигурации:
local db = require ('config.db')

--Выполнить sql:
local rows = db: query ('select * from mytable')
ngx.say (#rows)

Использование Query Builder (Query Builder):

vendor.Query инкапсулирует vendor.Mysql и предоставляет быстрый способ создания безопасного запроса, например:

local db = require ('config.db')
local query = require ('vendor.Query')()
local rows = query.use (db) .from ('products'). where ({product_id = 123}). all()
--эквивалентен выполнению local rows = db:query("select * from products where product_id = '123'")
ngx.say (query.get ('sql')) --можно получить для построения оператора sql

--query.use() Используется для указания связанной базы данных
query.use (require ('config.db'))

--query.select() используется для указания поля для запроса, если не указано, по умолчанию используется select *
query.select ({'id', 'email'})
--Эквивалент:
query.select ('id, email')

--query.from() используется для указания таблицы, которую нужно запросить SELECT * FROM `user`
query.from ('user')

query.where() используется для определения предложения WHERE в операторе SQL. Вы можете использовать следующие три формата для определения условия WHERE: **

—** строковый формат**, например: 'status = 1', этот метод не добавляет кавычки или экранирование автоматически.

—** хеш-формат**, например: {status = 1, type = 2} Этот метод правильно заключит в кавычки имя поля и экранирует диапазон значений

—** формат оператора**, например: {'in', {'2012', '2011'}} Формат оператора позволяет вам указать любое условное выражение стиля класса, как показано ниже: {Оператор, операнд1, операнд2, ...} Каждый из этих операндов может быть строковым форматом, хеш-форматом или вложенным форматом оператора, а оператор может быть одним из следующих:

Оператор использование
** and ** Операнды объединяются с ключевым словом AND. Например, {'and', 'id = 1', 'id = 2'} создаст id = 1 AND id = 2. Если операндом является массив, он также преобразуется в Строка представляет собой описанное выше. Например, {'and', 'type = 1', {'or', 'id = 1', 'id = 2'}} сгенерирует type = 1 AND (id = 1 OR id = 2). Этот метод не добавляет автоматически кавычки или экранирование.

** or ** | Аналогично оператору and.

** between ** | Первый операнд — это имя поля, а второй и третий представляют диапазон значений для этого поля. Например, {'between', 'id', 1, 10} сгенерирует id BETWEEN 1 AND 10.

** not between ** | Использование аналогично between.

** in ** | Первым операндом должно быть имя поля, а вторым оператором является массив. Например, {'in', 'id', {1, 2, 3}} сгенерирует id IN ('1', '2', '3'). Этот метод правильно заключит в кавычки имя поля и экранирует диапазон значений.

** not in ** | Использование аналогично in.

Метод query.orderBy() используется для указания предложения ORDER BY в операторе SQL. Например, чтобы достичь ... ORDER BY create_time desc можно:

query.orderBy ('create_time desc')
--эквивалентно: query.orderBy {create_time = desc}

Метод query.groupBy() используется для указания фрагмента GROUP BY в операторе SQL. Например, чтобы достичь ... GROUP BY id, status можно:

query.groupBy {'id', 'status'}

Методы query.limit() и query.offset() используются для указания предложений LIMIT и OFFSET в операторах SQL. Например, чтобы достичь ... LIMIT 10 OFFSET 20 эквивалентно mysql limit 20,10 можно:

query.limit (10) .offset (20)

Если вы укажете недопустимый предел или смещение (например, отрицательное число), оно будет проигнорировано.

** Метод query.page() может устанавливать LIMIT и OFFSET для запроса подкачки, передавая объект "vendor.Pager":**

local page = require ("vendor.Pager") {
    pageSize = 8,
    totalCount = 10,
}
query.page (page) --Эквивалент: query.limit (page.limit) .offset (page.offset)

Метод Query

vendor.Query предоставляет полный набор методов для различных целей запросов.

query.all(): возвращает массив строк. query.one(): возвращает первую строку набора результатов. query.count(): возвращает результат запроса COUNT.

Пример:

local db = require ('config.db')
local query = require ('vendor.Query') {}. use (db) .from ('products'). where {product_id = 123}
local rows = query.all()
local row = query.one()
local count = query.count()

Другие методы:

query.insert(): Вставляет данные. query.update(): обновляет данные. query.delete(): удаляет данные. query.save(): Новый вызов данных эквивалентен query.insert(), а вызов набора результатов запроса эквивалентен query.update().

Пример:

local db = require ('config.db')
local data = {product_id = 123, product_name = 'name123'}
local query = require ('vendor.Query') (data) .use (db) .from ('products')

insert:
local row = query.insert()
—Чтобы получить идентификатор самороста вновь вставленных данных, используйте:
local id = row.get ('insert_id') --эквивалент query.get ('insert_id')

—Обновление:
row.product_name = 'name456'
row.update() --или query.update (row)

—Удаление:
row.delete() --или query.delete (row)

Active Record

vendor.ActiveRecord дополнительно инкапсулирует генератор запросов vendor.Query. В то же время vendor.ActiveRecord наследуется от vendor.Model и может использовать методы load(), rules(), hasErrors(), validate() объекта модели.

Пример использования:

local Product = require ('vendor.ActiveRecord') {
    --db = require ('config.db'), --необязательный атрибут, укажите используемое подключение к базе данных, по умолчанию 'config.db'
    tableName = function() --метод tableName должен быть реализован для возврата имени таблицы данных для управления
        return 'products'
    end
}

—Вставка данных:
local product = Product.new {
    product_id = 123,
    product_name = 'name123',
} --Возвращаемый объект поддерживает использование метода vendor.Query
product.save() --эквивалентен product.insert()

—Быстро найти строку
local row = Product.findOne {product_id = 123} --Возвращаемый объект поддерживает использование метода vendor.Query

—Быстро найти несколько строк
local rows = Product.findAll {user = 'creater'} --Возвращаемый объект поддерживает использование vendor.Query ```
method

--Complex queries
local query = Product.find(). where {user = 'creater'} --The returned object supports using the vendor.Query method
local page = Pager {
    pageSize = 8,
    totalCount = query.count(),
}
local list = query.orderBy ('create_time desc'). page (page) .all()

--You can also do the following
query.insert() --insert data.
query.update() --Update the data.
query.delete() --delete the data.

Рекомендуется каждую таблицу данных создавать в каталоге models как класс операций, который наследуется от vendor.ActiveRecord.

Проблемы безопасности базы данных

Используйте vendor.ActiveRecord или vendor.Query, чтобы автоматически генерировать операторы запросов. В процессе построения оператора SQL, если переданные параметры являются формой, конструктор будет выполнять операцию экранирования для предотвращения внедрения SQL.

Но если передана строка, операция экранирования выполняться не будет. Рекомендуется минимизировать её использование и обеспечить безопасность SQL. Оператор SQL можно получить с помощью метода Query.get('sql').

Если вы хотите выполнить экранирование, вы можете использовать метод util.mescape():

local util = require ("vendor.Util")
value = util.mescape (value)

lua-resty-yii доступен под лицензией MIT. Дополнительную информацию см. в файле LICENSE.

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/hylun-lua-resty-yii.git
git@api.gitlife.ru:oschina-mirror/hylun-lua-resty-yii.git
oschina-mirror
hylun-lua-resty-yii
hylun-lua-resty-yii
master