michaldudek / symfony-project
Symfony MD 风格版骨架项目。
Requires
- php: >=5.5
- michaldudek/flavour: ~0.1
- michaldudek/knit-bundle: 0.2.*
- sensio/distribution-bundle: ~4.0
- symfony/monolog-bundle: ~2.4
- symfony/symfony: 2.7.*
Requires (Dev)
- phpmd/phpmd: ~2.2
- phpunit/phpunit: ~4.8
- squizlabs/php_codesniffer: ~2.3
This package is auto-updated.
Last update: 2024-09-06 03:18:36 UTC
README
基于 Symfony2 项目骨架的定制版本,具有高度倾向性的结构更改。
使用
您可以通过 Composer 快速设置项目。
$ composer create-project michaldudek/symfony-project -s dev ./path/to/your/project
目前没有任何生成器/安装程序可以自动构建您的完整应用程序结构,因此在克隆项目后,需要进行一些手动调整。
- 通过复制
config/parameters.yml.dist
创建config/parameters.yml
并调整它 - 设置应用程序 PHP 代码
- 将
src/Project
重命名为您的应用程序/项目名称 - 这将是您的顶级命名空间[ProjectNamespace]
- 将
src/Project/ProjectApp.php
重命名为您的应用程序/项目名称 - 这将是您的应用程序类[Project]App
- 建议包含一个*App
后缀。 - 编辑新的
src/[ProjectNamespace]/[Project]App.php
- 在第 2 行更新其命名空间
- 在第 9 行更新其作者(在这里包含所有参与项目开发的人员是一个好习惯)
- 在第 11 行更新其类名
- 编辑
src/[ProjectNamespace]/Welcome/Controller/Home.php
并在第 2 行更新命名空间。 - 编辑
src/[ProjectNamespace]/Resources/services/services.yml
并在第 9 行更新控制器命名空间。
- 将
web/app.php
:在第 5 行将引用的类名更改为您的项目类web/app_dev.php
:在第 14 行将引用的类名更改为您的项目类console
:在第 6 行将引用的类名更改为您的项目类Vagrantfile
:- 在第 1 行设置您的应用程序名称。
- 在第 23 行您可以调整 VM IP 以使其独一无二
如果您想使用 Capistrano 进行部署
config/build/deploy.rb
:- 在第 4 行设置您的应用程序名称
- 在第 6 行设置您的 Git 仓库 URL
config/build/stages/dev.rb
:- 在第 4 行配置您的服务器
- 在第 5 行配置您的部署位置
现在,使用 $ vagrant up
命令应启动您的 Vagrant VM 并使其在 www.[APP_NAME].dev
域名下可用。
哲学
这些更改、结构和规则背后的主要哲学是 关注点分离 和 控制反转。这意味着每个文件、文件夹或“包”应仅关注单一目的(当然,范围各异)并且不应知道其执行上下文,而是由外部实体控制。
例如,.cache
目录只存储缓存,或 src
目录只存储后端应用程序代码。再比如 tests
目录只存储测试代码,或 views
目录只存储视图模板。
更改
目录和文件结构
目录结构与 Symfony2(或 3)建议的结构相当不同。主要区别在于没有 ./app
目录。理念是将所有应用程序代码(包括配置)放在 ./src
内,所有“工件”(缓存文件、日志文件、动态参数文件)都放在外面。
.cache/ # stores all auto-generated cache files
config/ # various configuration files which are not related to app structure
build/ # build configuration including asset packaging and deployments
assets/ # asset packaging configuration (see further down the README)
js.json
less.json
deploy/ # deployment configuration (see further down the README)
parameters.yml # git ignored file that should include environment specific configuration
logs/ # logs directory
resources/ # various project resources can be stored here, including docs or code coverage
src/ # backend application PHP code
[ProjectNamespace]/ # top level namespace of your application (typically app name)
Resources/ # Symfony2 related configuration files
config/ # configuration files
config.yml
config_*.yml
routing/ # routing files
routing.yml
routing_dev.yml
services/ # dependency injection container configuration files
services.yml
[Project]App.php # main application file that registers bundles
autoload.php
tests/ # contains all tests
vendor/ # composer dependencies
views/ # Twig view templates
web/ # publicly accessible directory
assets/ # contains dynamically built frontend assets (see further down the README)
components/ # Bower components location
js/ # frontend JavaScript
less/ # frontend CSS LESS source files
app.php # prod env front controller
app_dev.php # dev env front controller
.BUILD # contains the current build version
console # console file (used to be app/console)
Gulpfile # Gulpfile for building frontend
Makefile # Makefile that contains various common tasks
phpunit.xml.dist # default PHPUnit configuration
上述列表省略了一些与Symfony没有严格关联的其他文件,而是简化了Web应用程序开发的某些方面,或者增加了其他功能,或者处理前端等。
无捆绑,甚至没有 AppBundle
当前Symfony2的最佳实践是拥有一个单一的应用程序包,最好命名为AppBundle
,其中包含所有应用程序逻辑。MD\Flavour更进一步,甚至不需要这样的包。理念是代码不应该与框架特定的事物,如“一个包”绑定,甚至PHP命名空间中包含“Bundle”这个词也可能感到不舒服。
在MD\Flavour中,应用程序就是这样——一个使用PHP类构建的应用程序,这些类大量使用依赖注入模式,因此不受任何特定框架的约束。应用程序流程可以通过外部配置文件(如services.yml
或routing.yml
)进行配置。
唯一两个与Symfony2相关的特定位置是./src/Project/ProjectApp.php
文件,其中配置要使用的Symfony包(标准版中的AppKernel.php
)以及./src/Project/Resources/
目录,其中包含各种配置文件。
禁止使用注解!
上述内容也部分解释了为什么MD\Flavour严格建议不要在PHP代码中使用注解配置。虽然我们理解使用注解和YML文件进行配置之间没有性能差异,但我们认为使用注解会将代码紧密耦合到特定框架或ORM。
注解需要在PHP文件的头部包含适当的use
语句,这可能会在各种QA分析中触发错误,并可能自动加载这些类(然后需要存在)。
理想情况下,PHP类不应知道其使用的上下文。虽然方便,但使用注解确实会在代码中设置上下文。这可能会导致可读性和调试问题,更重要的是,在从例如Symfony2切换到其他框架时可能会引入问题。
控制器作为服务
干净的分离也是所谓“控制器”不应被视为仅是服务类,这些服务类需要使用依赖注入构建的另一个原因。在许多框架中,包括Symfony2,控制器被某种方式特别对待。它们被允许将依赖注入容器注入到它们中,通过该容器使用隐藏的依赖项,并允许通过注解等方式配置自己。
我们建议将控制器视为与其他PHP类相同级别的公民。主要优势是能够对其进行单元测试。具有明确的依赖关系,可以很容易地模拟所有所需的服务并测试控制器逻辑。
请参阅Symfony2食谱以了解有关此方法的更多信息,但简而言之,您需要执行的两件事是将控制器注册为服务
# services.yml services: hello.controller: class: Project\Controller\HelloController arguments: - @world
并在路由定义中引用它
# routing.yml hello: path: / defaults: { _controller: hello.controller:hello }
请注意,使用这种方式,路由参数到方法参数的映射仍然有效。
控制器结果
进一步扩展上述规则,我们建议控制器不应知道其响应应用于什么上下文。为了便于重用,它们不应具体返回HTML或JSON响应。它们应该只返回数据结果,然后可以由不同的方包装成适当的格式。
这意味着相同的控制器可以在常规HTTP请求中用于返回使用Twig渲染的HTML页面,但在通过XHR调用时可以返回JSON格式的数据,当发送了带有?callback=jsonp
查询参数时,它们可以包装在JSONP响应中。这些都是常见的例子,显然还有许多其他可能性,但核心是控制器不应决定应给出什么类型的响应。
为了允许和简化这种机制,MD\Flavour包提供了MD\Flavour\Controller\ResultConverter
类(md.controller.result_converter
服务),该类将控制器返回值转换为Response
对象。该返回值通常是数组,但在控制器还需要设置响应的HTTP状态码的情况下,它可以是MD\Flavour\Controller\Result
类的实例,该实例接受数组和状态码作为两个构造函数参数。
# HelloController.php public function hello() { return [ 'hello' => 'world' ]; }
等同于
# HelloController.php use MD\Flavour\Controller\Result public function hello() { return new Result([ 'hello' => 'world' ], 200); }
此外,ResultConverter
将尝试根据控制器名称自动加载一个模板进行渲染,通过从中删除controller
单词,并将所有.
和:
转换为目录分隔符/
来实现,例如home.controller:index -> home/index.html.twig
或projects.list.controller:delete -> projects/list/delete.html.twig
。
也可以使用_template
属性设置用于路由路径的模板。
每个控制器一个 URL 规则
MD\Flavour提出的另一个控制器规则是将从URL路由到控制器类的映射数量保持最小,最好为1。单个URL路径应该映射到单个控制器类,控制器方法处理不同的HTTP方法。
规则的例外是带有CRULD(创建-读取-更新-列表-删除)操作的"资源"路由,其中id
参数是可选的。提议将它们映射如下
GET /resource_url -> resource.controller:index
GET /resource_url/{id} -> resource.controller:show
POST /resource_url -> resource.controller:create
PUT /resource_url/{id} -> resource.controller:update
DELETE /resource_url/{id} -> resource.controller:delete
再见 Doctrine,你好 Knit
由于过去与Doctrine2的问题和坎坷的历史,MD\Flavour放弃了这种ORM,转而采用自定义的简单数据映射器,它遵循仓库模式并抽象出与您选择的数据库的通信。
请访问Knit和KnitBundle获取更多信息。
简单来说,使用它就像注册一个仓库服务(Knit强制作为最佳实践)并在任何需要的地方注入它一样简单
# services.yml services: user_repository: parent: knit.repository # handles repository instantiation arguments: - Project\Entity\User # managed object class name - "users" # collection / table name in your database
让前端管理前端 - 无 Assetic
在MD\Flavour看来,后端应由后端管理,前端应由前端管理。这两个应该分开,使用为它设计的工具以及前端开发者感到更舒适的前端构建资产(编译CSS、JS、优化图像等)。因此,不需要Assetic
。
前端添加
虽然与Symfony或MD\Flavour无关,但此项目骨架还添加了几个工具并对如何管理前端提出了一些建议。
Bower 组件
建议使用Bower作为资产管理器。为了使所有Bower组件可供网络访问,它们都下载到./web/components/
目录。有关如何使用它的信息,请参阅Bower。
构建 JS & CSS 资产
此项目引入了一个相当复杂但功能强大的前端资产构建系统。其核心使用Gulp和一些流行的gulp插件进行压缩、连接、生成源映射等。但配置却相当不同。
如果您查看./config/build/assets/
目录,您将找到两个文件:js.json
和less.json
。它们的内容定义和配置了所谓的"包",在构建时间应该将资产编译到这些"包"中。
想法是,虽然连接可以加快页面加载速度,但下载单个大文件有时可能比同时下载两个或三个小文件慢。这也极大地帮助了浏览器缓存。因此,这两个JSON文件定义了应该构建的"包"。
顶级键是包名,生成的文件将与包名相同,它的两个属性定义了哪些文件应包含在包中(files
)以及Gulp在监视给定包的变化时应监视哪些文件(watch
)。watch
参数是可选的,默认值将设置为files
的值,但在只编译导入所有其他文件的文件时特别有用,而所有导入的文件仍然需要被监视,例如:
{ "lib": { "files": "web/less/lib.less" }, "app": { "files": "web/less/page.less", "watch": "web/less/**/*.less" } }
要构建资源,只需在终端中运行$ gulp
或$ gulp watch
来监视文件。也可以使用$ gulp js
和$ gulp less
。或者,最好使用Makefile
。
开发
一些工具和概念是专门为开发过程引入的。
Makefile
由于各种开发和构建过程可能很复杂,需要按正确顺序或使用特定参数运行多个命令,因此Makefile
是一个非常有用的工具,可以标准化和简化所有这些。
此项目中的Makefile
包含几个有用的任务,例如:
make install # installs all dependencies required in production
make install_dev # installs all dependencies required in development
make assets # builds all frontend assets
make watch # watches the frontend assets for changes and compiles if necessary
make test # runs all tests
make lint # lints all the code
make qa # runs all registered Quality Assurance checks
make report # creates a report on the code (e.g. code coverage report)
请参阅$ make help
以获取所有高级任务的列表,并查看Makefile以获取详细信息。
强烈建议将所有命令封装在Makefile
中,并建议所有参与项目的开发者使用它。
构建版本
MD\Flavour引入了一个构建版本的概念。当在Twig模板中引用动态构建的前端资源时非常有用。因为项目的.htaccess文件为几乎所有前端文件添加了大量的缓存,CSS和JavaScript文件都带有构建版本附加到其名称上,例如lib-2015100801.js
。该构建版本从位于项目根目录中的.BUILD
文件中读取(git忽略),如果不存在或为空,则默认为dev
。
此.BUILD
文件应由您使用的任何部署工具编写(在我们的情况下 - Capistrano)以及任何版本标记。在Capistrano的情况下,这是一个发布时间戳,但它可以是任何其他东西,发布号、git提交哈希或UNIX时间戳。
它可以在PHP代码中使用%kernel.build%
容器参数、Twig中的{{ kernel.build }}
变量或[Project]\[Project]App::getBuild()
方法进行引用。
前端文件的引用示例可能如下所示:
<link rel="stylesheet" href="/assets/css/lib-{{ kernel.build }}.css">
Vagrant
此项目包含一个默认的Vagrantfile
,用于构建具有PHP 5.6和MySQL 5.6以及配置Apache2的基本Vagrant VM,以便立即开发。在安装项目后,您可以安全地运行$ vagrant up
并启动该机器。有关Vagrant配置的更多文档,请参阅./resources/docs/Vagrant.md文件。
质量保证
我们认为质量保证应该从开发过程的开始就是一部分。在一条直线上保持高代码标准要比回去修复问题容易得多。因此,项目设置了一些工具,以便从一开始就简化QA检查。
要运行所有这些检查,只需在您的终端中运行$ make qa
。这将执行多个任务,包括:
- PHPUnit - 显然运行位于
./tests/
目录中的所有PHP单元测试,并且可以在./phpunit.xml.dist
文件中配置; - PHPCS - PHP_CodeSniffer,它检查适当的编码风格标准(提示:运行
$ make phpcs_fix
以自动修复可修复的内容),并且可以在./phpcs.xml
文件中进行调整和配置; - PHPMD - PHP代码错误检测器(PHP Mess Detector),可以对PHP代码进行静态分析,查找常见的错误做法、注意事项、错误等。虽然这个工具刚开始使用时可能会非常令人烦恼,但它确实在保持代码标准非常高方面非常有价值。它可以通过
./phpmd.xml
文件进行配置。 - JSHint - JSHint,可以对位于
./web/js/
目录中的JavaScript代码执行静态代码分析,并且可以通过./.jshintrc
文件进行配置。
部署
待定。
Capistrano
待定。
Chef Knife
待定。
其他
待定。
GitLab CI
待定。