Introducing the Blog Module
Introducing the Blog Module
Now that we know about the basics of the zend-mvc skeleton application, let's continue and create our very own module. We will create a module named "Blog". This module will display a list of database entries that represent a single blog post. Each post will have three properties: id, text, and title. We will create forms to enter new posts into our database and to edit existing posts. Furthermore we will do so by using best-practices throughout the whole tutorial.
Writing a new Module
Let's start by creating a new folder under the /module directory called Blog, with the following stucture:
module/
Blog/
config/
src/
view/
To be recognized as a module by the ModuleManager, we need to do three things:
- Tell Composer how to autoload classes from our new module.
- Create a
Moduleclass in theBlognamespace. - Notify the application of the new module.
Let's tell Composer about our new module. Open the composer.json file in the project root, and edit the autoload section to add a new PSR-4 entry for theBlog module; when you're done, it should read:
"autoload": {
"psr-4": {
"Application\\": "module/Application/src/",
"Album\\": "module/Album/src/",
"Blog\\": "module/Blog/src/"
}
}
Once you're done, tell Composer to update its autoloading definitions:
$ composer dump-autoload
Next, we will create a Module class under the Blog namespace. Create the filemodule/Blog/src/Module.php with the following contents:
<?php
namespace Blog;
class Module
{
}
We now have a module that can be detected by the ModuleManager. Let's add this module to our application. Although our module doesn't do anything yet, just having the Module.php class allows it to be loaded by the ModuleManager. To do this, add an entry for Blog to the modules array insideconfig/modules.config.php:
<?php
// In config/modules.config.php:
return [
/* ... */
'Application',
'Album',
'Blog',
];
If you refresh your application you should see no change at all (but also no errors).
At this point it's worth taking a step back to discuss what modules are for. In short, a module is an encapsulated set of features for your application. A module might add features to the application that you can see, like our Blogmodule; or it might provide background functionality for other modules in the application to use, such as interacting with a third party API.
Organizing your code into modules makes it easier for you to reuse functionality in other application, or to use modules written by the community.
Configuring the Module
The next thing we're going to do is add a route to our application so that our module can be accessed through the URL localhost:8080/blog. We do this by adding router configuration to our module, but first we need to let theModuleManager know that our module has configuration that it needs to load.
This is done by adding a getConfig() method to the Module class that returns the configuration. (This method is defined in the ConfigProviderInterface, although explicitly implementing this interface in the module class is optional.) This method should return either an array or a Traversable object. Continue by editing module/Blog/src/Module.php:
// In /module/Blog/Module.php:
class Module
{
public function getConfig()
{
return [];
}
}
With this, our module is now able to be configured. Configuration files can become quite big, though, and keeping everything inside the getConfig()method won't be optimal. To help keep our project organized, we're going to put our array configuration in a separate file. Go ahead and create this file atmodule/Blog/config/module.config.php:
<?php
return [];
Now rewrite the getConfig() function to include this newly created file instead of directly returning the array:
<?php
// In /module/Blog/Module.php:
public function getConfig()
{
return include __DIR__ . '/../config/module.config.php';
}
Reload your application and you'll see that everything remains as it was. Next we add the new route to our configuration file:
// In /module/Blog/config/module.config.php:
namespace Blog;
return [
// This lines opens the configuration for the RouteManager
'router' => [
// Open configuration for all possible routes
'routes' => [
// Define a new route called "blog"
'blog' => [
// Define a "literal" route type:
'type' => 'literal',
// Configure the route itself
'options' => [
// Listen to "/blog" as uri:
'route' => '/blog',
// Define default controller and action to be called when
// this route is matched
'defaults' => [
'controller' => Controller\ListController::class,
'action' => 'index',
],
],
],
],
],
];
We've now created a route called post that listens to the URLlocalhost:8080/blog. Whenever someone accesses this route, theindexAction() function of the class Blog\Controller\ListController will be executed. However, this controller does not exist yet, so if you reload the page you will see this error message:
A 404 error occurred
Page not found.
The requested controller could not be mapped by routing.
Controller:
Blog\Controller\ListController(resolves to invalid controller class or alias: Blog\Controller\ListController)
We now need to tell our module where to find this controller namedBlog\Controller\ListController. To achieve this we have to add this key to thecontrollers configuration key inside yourmodule/Blog/config/module.config.php.
namespace Blog;
use Zend\ServiceManager\Factory\InvokableFactory;
return [
'controllers' => [
'factories' => [
Controller\ListController::class => InvokableFactory::class,
],
],
/* ... */
];
This configuration defines a factory for the controller classBlog\Controller\ListController, using the zend-servicemanagerInvokableFactory (which, internally, instantiates the class with no arguments). Reloading the page should then give you:
Fatal error: Class 'Blog\Controller\ListController' not found in {projectPath}/vendor/zendframework/zend-servicemanager/src/Factory/InvokableFactory.php on line 32
This error tells us that the application knows what class to load, but was not able to autoload it. In our case, we've already setup autoloading, but have not yet defined the controller class!
Create the file module/Blog/src/Controller/ListController.php with the following contents:
<?php
namespace Blog\Controller;
class ListController
{
}
Reloading the page now will finally result into a new screen. The new error message looks like this:
A 404 error occurred
Page not found.
The requested controller was not dispatchable.
Controller:
Blog\Controller\List(resolves to invalid controller class or alias: Blog\Controller\List)
Additional information:
Zend\ServiceManager\Exception\InvalidServiceException
File:
{projectPath}/vendor/zendframework/zend-mvc/src/Controller/ControllerManager.php:{lineNumber}
Message:
Plugin of type "Blog\Controller\ListController" is invalid; must implement Zend\Stdlib\DispatchableInterface
This happens because our controller must implement DispatchableInterface in order to be 'dispatched' (or run) by zend-mvc. zend-mvc provides a base controller implementation of it with AbstractActionController, which we are going to use. Let's modify our controller now:
// In /module/Blog/src/Blog/Controller/ListController.php:
namespace Blog\Controller;
use Zend\Mvc\Controller\AbstractActionController;
class ListController extends AbstractActionController
{
}
It's now time for another refresh of the site. You should now see a new error message:
An error occurred
An error occurred during execution; please try again later.
Additional information:
Zend\View\Exception\RuntimeException
File:
{projectPath}/vendor/zendframework/zend-view/src/Renderer/PhpRenderer.php:{lineNumber}
Message:
Zend\View\Renderer\PhpRenderer::render: Unable to render template "blog/list/index"; resolver could not resolve to a file
Now the application tells you that a view template-file can not be rendered, which is to be expected as we've not created it yet. The application is expecting it to be at module/Blog/view/blog/list/index.phtml. Create this file and add some dummy content to it:
<!-- Filename: module/Blog/view/blog/list/index.phtml -->
<h1>Blog\ListController::indexAction()</h1>
Before we continue let us quickly take a look at where we placed this file. Note that view files are found within the /view subdirectory, not /src as they are not PHP class files, but template files for rendering HTML. The path, however, deserves some explanation. First we have the lowercased namespace, followed by the lowercased controller name (without the suffix 'controller'), and lastly comes the name of the action that we are accessing (again without the suffix 'action'). As a templated string, you can think of it as:view/{namespace}/{controller}/{action}.phtml. This has become a community standard but you you have the freedom to specify custom paths if desired.
However creating this file alone is not enough and this brings as to the final topic of this part of the tutorial. We need to let the application know where to look for view files. We do this within our module's configuration file,module.config.php.
// In module/Blog/config/module.config.php:
return [
'controllers' => [ /** Controller Configuration */ ],
'router' => [ /** Route Configuration */ ]
'view_manager' => [
'template_path_stack' => [
__DIR__ . '/../view',
],
],
];
The above configuration tells the application that the folder module/Blog/view/has view files in it that match the above described default scheme. It is important to note that with this you can not only ship view files for your module, but you can also overwrite view files from other modules.
Reload your site now. Finally we are at a point where we see something different than an error being displayed! Congratulations, not only have you created a simple "Hello World" style module, you also learned about many error messages and their causes. If we didn't exhaust you too much, continue with our tutorial, and let's create a module that actually does something.
Introducing the Blog Module的更多相关文章
- Reviewing the Blog Module
Reviewing the Blog Module Throughout the tutorial, we have created a fully functional CRUD module us ...
- Introducing my blog
作为一名计算机专业的学生,在我的博客中我会记录以下几方面的内容: 1.在阅读各类专业书籍的过程中,遇到了一些自己通过很大努力才思考.解决出来的问题/知识/概念,我会通过我自己的讲解将这些问题较为全面. ...
- programing Python --Sys module
Recall that every python module has a built_in __name__ variable that python sets to the __main__ st ...
- Building Applications with Force.com and VisualForce (DEV401)(五):Application Essential: Introducing Business Logic
Dev 401-005 Application Essential: Introducing Business Logic Module Agenda1.Custom object Queues2.W ...
- lua MVC框架 Orbit初探
介绍 http://keplerproject.github.io/orbit/ Orbit是lua语言版本的MVC框架. 此框架完全抛弃CGILUA的脚本模型, 支持的应用, 每个应用可以卸载一个单 ...
- iOS应用架构现状分析
iOS从2007年诞生至今已有近10年的历史,10年的时间对iOS技术圈来说足够产生相当可观的沉淀,尤其这几年的技术分享氛围无论国内国外都显得异常活跃.本文就iOS架构这一主题,结合开发圈里讨论较多的 ...
- 【转发】构建高可伸缩性的WEB交互式系统(下)
原文转自:http://kb.cnblogs.com/page/504518/ 本文是<构建高可伸缩性的WEB交互式系统>系列文章的第三篇,以网易的NEJ框架为例,对模块的可伸缩性进行分析 ...
- Making Use of Forms and Fieldsets
Making Use of Forms and Fieldsets So far all we have done is read data from the database. In a real- ...
- Understanding the Router
Understanding the Router Our module is coming along nicely. However, we're not really doing all that ...
随机推荐
- nopcommerce商城系统--源代码结构和架构
这个文档是让开发者了解nopcommerce解决方案结构的指南.这是新的nopcommerce开发者学习nopcommerce代码的相关文档.首先,nopCommerce源代码是很容易得到的.它是一个 ...
- NopCommerce架构分析之三---数据库初试化及数据操作
系统启动时执行任务:IStartupTask,启动时执行的任务主要是数据库的初始化和加载. IStartupTask调用IEfDataProvider进行数据库的初始化. IEfDataProvide ...
- Android学习系列(23)--App主界面实现
在上篇文章<Android学习系列(22)--App主界面比较>中我们浅略的分析了几个主界面布局,选了一个最大众化的经典布局.今天我们就这个经典布局,用代码具体的实现它. 1.预览图先看下 ...
- HDU4614 Vases and Flowers 二分+线段树
分析:感觉一看就是二分+线段树,没啥好想的,唯一注意,当开始摆花时,注意和最多能放的比大小 #include<iostream> #include<cmath> #includ ...
- 初涉C#防止黑客攻击站短
一.同一个IP如果在一分钟内连续发送5个站短可以认为是不正确的,原因有2方面: 1.发站短的页面是有点击按钮,点击按钮后马上按钮会变为不可点击,所以在前端要防止点击一次触发多次的情况 2.发送短信的U ...
- html5爱心表白
http://js.itivy.com/jiaoben1892/index.html http://bangpai.sourceforge.net/main.html
- Error starting static Resources java.lang.IllegalArgumentException: Document base D:\Program Files\apache-tomcat-xxx\webapps\xxx does not exist or is not a readable directory
网上的答案大多数如下: 但并没有解决我的问题 经过我的观察: 在tomcat的server.xml有Lottery项目描述,但实际上,该项目已被我删除,不存在于webapps中了 该行Cont ...
- 引爆公式让你的APP游戏成为下一个“爆款”
在2014年的移动互联网领域,“魔漫相机”是一款值得关注的产品.虽然没有腾讯.百度或阿里巴巴等大资源的支持,但是这款应用一上线就在中国市场发展迅猛,日下载量超过80万次,最高一日达300万次.类似的成 ...
- FreeModbus Slave For AVR源代码 精简版2 【worldsing 笔记】
FreeModbus 源码:点击下载 线圈BUG解决(后来发现不一定是BUG) 1.eMBException eMBFuncWriteCoil( UCHAR * pucFrame, USHORT * ...
- UVa 二分图匹配 Examples
这些都是刘汝佳的算法训练指南上的例题,基本包括了常见的几种二分图匹配的算法. 二分图是这样一个图,顶点分成两个不相交的集合X , Y中,其中同一个集合中没有边,所有的边关联在两个集合中. 给定一个二分 ...