jarick / bx
BX PHP 框架 - 开发包
Requires
- bojaspus/zendsearch: dev-master
- filp/whoops: 1.*
- gregwar/captcha: dev-master
- illuminate/cache: 4.1.*
- illuminate/events: 4.1.*
- imagine/imagine: 0.5.*
- ircmaxell/password-compat: 1.0.*
- leafo/lessphp: 0.4.*
- makhov/phpmorphy: dev-master
- monolog/monolog: 1.7.*
- mthaml/mthaml: 1.3.*
- nesbot/carbon: 1.8.*
- phpoffice/phpexcel: dev-develop
- phpspec/phpspec: 2.0.*
- phpunit/dbunit: 1.3.*
- phpunit/phpunit: 4.0.*
- pimple/pimple: 2.0.*
- symfony/http-foundation: 2.4.*
- symfony/translation: 2.4.*
- symfony/yaml: 2.4.*
This package is not auto-updated.
Last update: 2024-09-28 15:34:14 UTC
README
总体架构。
运行需要 PHP 版本 5.4 或更高版本,memcache(在没有网站的情况下,网站不会使用缓存),mysql 或 sqlite。
编码标准。
框架完全基于标准 psr。除了使用缩进的规则(使用缩进而不是空格)外。
结构。
代码位于 src 文件夹中,并分解为独立组件。组件结构分为 4 个业务层
- 模型(Entity)是一个简单类,继承自接口 IEntity 并使用特质 EntityTrait。
在 labels 函数中列出字段名称。示例
protected function labels() { return [ self::C_ID => $this->trans('user.entity.user.id'), self::C_UNIQUE_ID => $this->trans('user.entity.user.unique_id'), self::C_LOGIN => $this->trans('user.entity.user.login'), self::C_PASSWORD => $this->trans('user.entity.user.password'), self::C_EMAIL => $this->trans('user.entity.user.email'), self::C_CODE => $this->trans('user.entity.user.code'), self::C_CREATE_DATE => $this->trans('user.entity.user.create_date'), self::C_TIMESTAMP_X => $this->trans('user.entity.user.timestamp_x'), self::C_REGISTERED => $this->trans('user.entity.user.registered'), self::C_ACTIVE => $this->trans('user.entity.user.active'), self::C_DISPLAY_NAME => $this->trans('user.entity.user.display_name'), ]; }
在 rules 函数中列出字段验证规则。示例
protected function rules() { return [ [self::C_LOGIN,self::C_EMAIL], $this->rule()->string()->notEmpty()->setMax(50), [self::C_PASSWORD], $this->rule()->custom([$this,'filterPassword'])->notEmpty(), [self::C_CODE], $this->rule()->setter()->setFunction([$this,'filterCode'])->setValidators([ $this->rule()->string()->notEmpty()->setMax(50), ]), [self::C_CREATE_DATE], $this->rule()->setter()->setValidators([ $this->rule()->datetime()->withTime()->notEmpty() ])->setValue($this->date()->convertTimeStamp())->onAdd(), [self::C_TIMESTAMP_X], $this->rule()->setter()->setValidators([ $this->rule()->datetime()->withTime()->notEmpty() ])->setValue($this->date()->convertTimeStamp())->onAdd(), [self::C_DISPLAY_NAME], $this->rule()->string()->setMax(100), [self::C_REGISTERED,self::C_ACTIVE], $this->rule()->boolean(), ]; }
规则列表按顺序排列。首先指定字段集,然后指定这些字段的验证规则。可以为单个字段指定任意数量的规则。在验证字段时,首先应用数组中的早期元素,如果验证器返回错误,则不会应用该字段的后续验证器。
可以使用函数 $this->rule()->custom 设置字段的自定义过滤器和验证器。示例
public function filterPassword(&$value) { if ($this->string()->length($value) === 0){ return $this->trans('user.entity.user.error_password_empty'); } $min = $this->getMinLengthPassword(); if ($this->string()->length($value) < $min){ return $this->trans('user.entity.user.error_password_min',['#MIN#' => $min]); } $value = password_hash($value,PASSWORD_BCRYPT); } public function filterCode(&$value) { $value = $this->string()->substr($this->string()->getSlug($this->getValue(self::C_LOGIN)),0,50); }
如示例所示,要更改字段输入的值,需要更改 $value 变量。要生成错误,需要返回包含错误的字符串。如果验证成功,则可以不返回任何内容或返回 null。
Entity 封装了字段值、字段名称、验证器和验证错误。要为实体设置值,请将包含值的数组传递给函数 setData。
要验证传递的值,请执行函数 checkFields。要获取验证错误,请调用函数 getErrors。
- 数据存储层(Store)。在此层中描述了与不同数据库实体(Entity)交互的逻辑。例如,用户会话可以存储在 PHP 会话中、数据库中或 NoSql 存储中。在这种情况下,业务逻辑不必知道使用的是哪种存储。它将使用统一接口和相同的实体与所有存储进行交互。
存储数据的方式在类 BX\Base\Registry 中设置。如果没有指定存储机制,框架会自动选择最佳存储方法。
实际项目配置示例
sites: ###: title: '###' keywords: '###' charset: UTF-8 name: ### regex: - ###.com - localhost folder: / layout_rule: ###: - "" admin: - admin\/ url_rewrite: console: /console/ news: /news/ admin: /admin/ lang: ru date: timezone: Europe/Kaliningrad mode: production templating: engine: haml haml: ~/../haml php: ~/../cache doc_root: ~/../www cache: type: memcache host: localhost post: 11211 pdo: dsn: 'sqlite:../db.db' zend_search: morphy_dicts: ~/../search/dicts stop_words: ~/../search/stop-words/stop-words-ru.txt index: ~/../search/data user: password_min_length: 6
配置可以以 php array 或 yaml 格式指定,请参阅 Registry::init 函数的第二个参数。
- 数据管理层(Manager)。这是包含所有数据交互逻辑的主要层。通常,在将对象实例存储在 ioc 存储库(请参阅 BX\Base\DI 类)的特质中隐藏对管理器的调用。在自己的逻辑中,始终可以重定义标准管理器。示例
function it_clearCache(CacheManager $cache) { $cache->clearByTags('test')->shouldBeCalled()->willReturn(null); DICService::update('cache',$cache->getWrappedObject()); $this->clearCache(); DICService::update('cache',null); }
在此示例中,我们重定义了标准管理器为我们的 Mock 类,以检查 clearCache 函数的正确性。然后我们清除了容器,以便框架继续使用默认的管理器缓存。
- 表示层(Widget)。类继承自 BX\MVC\Widget 类。应包含尽可能少的业务逻辑。用作代理类,以获取请求参数并将它们传递给数据管理层(Manager)。示例
class CaptchaWidget extends Widget { use \BX\Translate\TranslateTrait; public function run() { $this->view->buffer()->flush(); try{ $ip = $this->request()->server()->get('REMOTE_ADDR'); $cpt = new CaptchaManager($ip); if ($this->request()->query()->has('reload')){ $cpt->reload(); } $builder = new CaptchaRender($cpt->getEntity()->code); $this->response()->headers['Content-type'] = 'image/jpeg'; $builder->output(); }catch (\Exception $e){ $this->log('captcha.widget.captcha')->err($e); echo $this->trans('captcha.widget.captcha.error_generate_captcha'); } $this->view->abort(); } }
从数据库中选择值。
ORM 框架使用 UnitOfWork 模式编写,并确保防止 Race condition。示例更改数据
/** * Clear old captcha * @param integer $day * @return boolean * @throws \RuntimeException */ public function clear($day = 30) { $repository = new Repository('captcha'); $time = $this->date()->convertTimeStamp(time() - $day * 3600 * 24); $captches = static::finder(CaptchaEntity::getClass()) ->filter(['<TIMESTAMP_X' => $time]) ->all(); foreach($captches as $captcha){ $repository->delete($this,$captcha); } if (!$repository->commit()){ $mess = print_r($repository->getErrorEntity()->getErrors()->all(),1); throw new \RuntimeException('Error clear old captches. Error:'.$mess); } return true; }
在本例中,我们从数据库中删除所有旧的验证码哈希记录。要开始更改,需要创建一个 Repository 类的实例。添加操作通过 add 函数执行,更新操作通过 update 函数执行,删除操作通过 delete 函数执行。要使更改生效,需要调用 commit 函数。如果发生错误,它将返回 false。
要执行过滤,需要调用函数 BX\DB\TableTrait::finder(参见 BX\DB\Filter\SqlBuilder 类)。
索引文件示例。
<?php require dirname(__DIR__).'/vendor/autoload.php'; BX\Config\Config::init('yaml_file',dirname(__DIR__).'/config/main.yml'); BX\MVC\SiteController::run()->end();