# 教程 1:讓我們通過例子來學習(Tutorial 1: Let’s learn by example)
通過這第一個教程,我們將引導您從基礎完成創建簡單的帶有注冊表單的應用。 我們也將解釋框架行為的基本方面。如果您對Phalcon的自動代碼生成工具有興趣, 您可以查看[developer tools](http://docs.iphalcon.cn/reference/tools.html)。
使用本指南的最好方法就是依次按照每一步來做。你可以得到完整的代碼[點擊這里](https://github.com/phalcon/tutorial).
## 文件結構(File structure)
Phalcon不會強制要求應用程序的開發遵循特定的文件結構。因為它是松散耦合的,你可以實現Phalcon驅動的應用程序,以及使用對你來說最舒服的文件結構。
本教程的目的以此為起點,我們建議使用以下結構:
~~~
tutorial/
app/
controllers/
models/
views/
public/
css/
img/
js/
~~~
需要注意的是,你不需要任何有關Phalcon的 “library” 目錄。該框架已經被加載到內存中,供您使用。
在此之前, 請確認你已經成功的[installed Phalcon](http://docs.iphalcon.cn/reference/install.html), 并設置了:doc:Nginx ,[Apache](http://docs.iphalcon.cn/reference/apache.html)或者[Cherokee](http://docs.iphalcon.cn/reference/cherokee.html).
## 引導程序(Bootstrap)
你需要創建的第一個文件是引導文件。這個文件很重要; 因為它作為你的應用程序的基礎,用它來控制應用程序的各個方面。 在這個文件中,你可以實現組件的初始化和應用程序的行為。
基本上, 它負責做三件事情:
1. 設置自動加載器.
2. 配置依賴注入.
3. 處理應用請求.
### 自動加載(Autoloaders)
我們可以看出,引導程序的第一部分是注冊一個自動加載器。在這個應用程序里,它將用于加載控制器和模型類。例如,我們可以為控制器注冊一個或多個目錄來增加應用程序的靈活性的。在我們的例子中,我們使用了[Phalcon\\Loader](http://docs.iphalcon.cn/api/Phalcon_Loader.html)組件。
有了它,我們可以加載使用各種策略類,但在這個例子中,我們選擇了在預定義的目錄中查找類:
~~~
<?php
use Phalcon\Loader;
// ...
$loader = new Loader();
$loader->registerDirs(
[
"../app/controllers/",
"../app/models/",
]
);
$loader->register();
~~~
### 依賴管理(Dependency Management)
在使用Phalcon時必須理解的一個非常重要的概念是[依賴注入容器(dependency injection container)](http://docs.iphalcon.cn/reference/di.html). 這聽起來復雜,但實際上非常簡單實用。
服務容器是一個全局存儲的將要被使用的應用程序功能包。每次框架需要的一個組件時,會請求這個使用協定好名稱的服務容器。因為Phalcon是一個高度解耦的框架,[Phalcon\\Di](http://docs.iphalcon.cn/api/Phalcon_Di.html)作為黏合劑,促使不同組件的集成,以一個透明的方式實現他們一起進行工作。
~~~
<?php
use Phalcon\Di\FactoryDefault;
// ...
// 創建一個 DI
$di = new FactoryDefault();
~~~
[Phalcon\\Di\\FactoryDefault](http://docs.iphalcon.cn/api/Phalcon_Di_FactoryDefault.html)是[Phalcon\\Di](http://docs.iphalcon.cn/api/Phalcon_Di.html)的一個變體。為了讓事情變得更容易,它已注冊了Phalcon的大多數組件。 因此,我們不需要一個一個注冊這些組件。在以后更換工廠服務的時候也不會有什么問題。
在接下來的部分,我們注冊了“視圖(view)”服務,指示框架將去指定的目錄尋找視圖文件。由于視圖并非PHP類,它們不能被自動加載器加載。
服務可以通過多種方式進行登記,但在我們的教程中,我們將使用一個匿名函數[anonymous function](http://php.net/manual/zh/functions.anonymous.php):
~~~
<?php
use Phalcon\Mvc\View;
// ...
// 設置視圖組件
$di->set(
"view",
function () {
$view = new View();
$view->setViewsDir("../app/views/");
return $view;
}
);
~~~
接下來,我們注冊一個基礎URI,這樣通過Phalcon生成包括我們之前設置的“tutorial”文件夾在內的所有的URI。 我們使用類[Phalcon\\Tag](http://docs.iphalcon.cn/api/Phalcon_Tag.html)生成超鏈接,這將在本教程后續部分很重要。
~~~
<?php
use Phalcon\Mvc\Url as UrlProvider;
// ...
// 設置一個基礎URI, 這樣所有生成的URI都包含"tutorial"文件夾
$di->set(
"url",
function () {
$url = new UrlProvider();
$url->setBaseUri("/tutorial/");
return $url;
}
);
~~~
### 處理應用請求(Handling the application request)
在這個文件的最后部分,我們發現[Phalcon\\Mvc\\Application](http://docs.iphalcon.cn/api/Phalcon_Mvc_Application.html)。其目的是初始化請求環境,并接收路由到來的請求,接著分發任何發現的動作;收集所有的響應,并在過程完成后返回它們。
~~~
<?php
use Phalcon\Mvc\Application;
// ...
$application = new Application($di);
$response = $application->handle();
$response->send();
~~~
### 把每個組件組合在一起(Putting everything together)
這個引導文件 tutorial/public/index.php 文件應該看起來像:
~~~
<?php
use Phalcon\Loader;
use Phalcon\Mvc\View;
use Phalcon\Mvc\Application;
use Phalcon\Di\FactoryDefault;
use Phalcon\Mvc\Url as UrlProvider;
use Phalcon\Db\Adapter\Pdo\Mysql as DbAdapter;
// 注冊一個自動加載器
$loader = new Loader();
$loader->registerDirs(
[
"../app/controllers/",
"../app/models/",
]
);
$loader->register();
// 創建一個 DI
$di = new FactoryDefault();
// 設置視圖組件
$di->set(
"view",
function () {
$view = new View();
$view->setViewsDir("../app/views/");
return $view;
}
);
// 設置一個基礎URI, 這樣所有生成的URI都包含"tutorial"文件夾
$di->set(
"url",
function () {
$url = new UrlProvider();
$url->setBaseUri("/tutorial/");
return $url;
}
);
$application = new Application($di);
try {
// 處理請求
$response = $application->handle();
$response->send();
} catch (\Exception $e) {
echo "Exception: ", $e->getMessage();
}
~~~
正如你所看到的,引導文件很短,我們并不需要引入任何其他文件。在不到30行的代碼里,我們已經為自己設定一個靈活的MVC應用程序。
## 創建控制器(Creating a Controller)
默認情況下Phalcon會尋找一個名為“Index”的控制器。當請求中沒有控制器或動作時,則使用“Index”控制器作為起點。這個“Index”控制器 (app/controllers/IndexController.php) 看起來類似:
~~~
<?php
use Phalcon\Mvc\Controller;
class IndexController extends Controller
{
public function indexAction()
{
echo "<h1>Hello!</h1>";
}
}
~~~
該控制器類必須有“Controller”后綴,且控制器動作必須有“Action”后綴。如果你從瀏覽器訪問應用程序,你應該看到這樣的事情:

恭喜, 讓Phalcon帶你飛!
## 輸出到視圖(Sending output to a view)
從控制器發送輸出到屏幕上有時是必要的,但是在MVC社區,大多數純粹主義者證明這樣做不可取。一切必須傳遞給視圖,視圖負責在屏幕上輸出數據。Phalcon將在最后執行的控制器的同名目錄中,查找最后執行的動作的同名的視圖。在我們的例子 (app/views/index/index.phtml) :
~~~
<?php echo "<h1>Hello!</h1>";
~~~
我們的控制器 (app/controllers/IndexController.php) 現在定義了一個空的動作:
~~~
<?php
use Phalcon\Mvc\Controller;
class IndexController extends Controller
{
public function indexAction()
{
}
}
~~~
瀏覽器輸出應該保持不變。當這個動作已經執行結束[Phalcon\\Mvc\\View](http://docs.iphalcon.cn/api/Phalcon_Mvc_View.html)靜態組件會自動創建。 學習更多關于[視圖使用教程](http://docs.iphalcon.cn/reference/views.html)。
## 設計注冊表單(Designing a sign up form)
現在我們將改變index.phtml視圖文件,添加一個鏈接到一個名為“signup”的新控制器。我們的目標是在應用程序中允許用戶注冊。
~~~
<?php
echo "<h1>Hello!</h1>";
echo PHP_EOL;
echo PHP_EOL;
echo $this->tag->linkTo(
"signup",
"Sign Up Here!"
);
~~~
生成的HTML代碼顯示一個錨 (“a”) HTML標簽鏈接到一個新的控制器:
~~~
<h1>Hello!</h1>
<a href="/tutorial/signup">Sign Up Here!</a>
~~~
我們使用類[Phalcon\\Tag](http://docs.iphalcon.cn/api/Phalcon_Tag.html)去生成標記。 這是一個讓我們構建HTML標記的實用類。 關于生成HTML更詳細的文章可以查看[視圖助手](http://docs.iphalcon.cn/reference/tags.html)

這是一個注冊控制器 (app/controllers/SignupController.php):
~~~
<?php
use Phalcon\Mvc\Controller;
class SignupController extends Controller
{
public function indexAction()
{
}
}
~~~
這個空index動作整潔的傳遞了表單定義給一個視圖 (app/views/signup/index.phtml):
~~~
<h2>
Sign up using this form
</h2>
<?php echo $this->tag->form("signup/register"); ?>
<p>
<label for="name">
Name
</label>
<?php echo $this->tag->textField("name"); ?>
</p>
<p>
<label for="email">
E-Mail
</label>
<?php echo $this->tag->textField("email"); ?>
</p>
<p>
<?php echo $this->tag->submitButton("Register"); ?>
</p>
</form>
~~~
在瀏覽器中查看表單將顯示類似的頁面:

[Phalcon\\Tag](http://docs.iphalcon.cn/api/Phalcon_Tag.html)還提供了有用的方法來構建表單元素。
`Phalcon\Tag::form()`方法只接受一個參數實例, 一個相對uri到這個應用的一個控制器/動作。
通過單擊“Send”按鈕,您將注意到框架拋出了一個異常,這表明我們是錯過了在控制器中注冊“register”動作。我們的 public/index.php 文件拋出這個異常:
> Exception: Action “register” was not found on handler “signup”
實現該方法將移除異常:
~~~
<?php
use Phalcon\Mvc\Controller;
class SignupController extends Controller
{
public function indexAction()
{
}
public function registerAction()
{
}
}
~~~
如果你再點擊“Send”按鈕,您將看到一個空白頁。提供的名稱和電子郵件的輸入的這個用戶應該被存儲在數據庫中。根據MVC的指導方針,必須通過數據庫交互模型,確保整潔的面向對象的代碼。
## 創建模型(Creating a Model)
Phalcon帶來的第一個完全用C語言編寫的PHP ORM。它簡化了開發, 而不是增加了開發的復雜性。
創建我們的第一個模型之前,我們需要在Phalcon以外創建一個數據庫表。一個用來存儲注冊用戶的簡單表,可以這樣定義:
~~~
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(70) NOT NULL,
`email` varchar(70) NOT NULL,
PRIMARY KEY (`id`)
);
~~~
模型應該位于 app/models 目錄 (app/models/Users.php). 這個模型對應“users”表:
~~~
<?php
use Phalcon\Mvc\Model;
class Users extends Model
{
public $id;
public $name;
public $email;
}
~~~
## 設置數據庫連接(Setting a Database Connection)
為了能夠使用一個數據庫連接,然后通過我們的模型訪問數據,我們需要在我們的引導過程指定它。數據庫連接是我們的應用程序可以使用的數個組件中的另一個服務:
~~~
<?php
use Phalcon\Db\Adapter\Pdo\Mysql as DbAdapter;
// 設置數據庫服務
$di->set(
"db",
function () {
return new DbAdapter(
[
"host" => "localhost",
"username" => "root",
"password" => "secret",
"dbname" => "test_db",
]
);
}
);
~~~
使用正確的數據庫參數,我們的模型已經準備和應用程序的其余部分工作。
## 使用模型保存數據(Storing data using models)
下一個步驟是從表單接收數據存儲在表中。
~~~
<?php
use Phalcon\Mvc\Controller;
class SignupController extends Controller
{
public function indexAction()
{
}
public function registerAction()
{
$user = new Users();
// 存儲和檢驗錯誤
$success = $user->save(
$this->request->getPost(),
[
"name",
"email",
]
);
if ($success) {
echo "Thanks for registering!";
} else {
echo "Sorry, the following problems were generated: ";
$messages = $user->getMessages();
foreach ($messages as $message) {
echo $message->getMessage(), "<br/>";
}
}
$this->view->disable();
}
}
~~~
然后我們實例化用戶類,它對應于一個用戶記錄。類的公共屬性映射到用戶表中的記錄的字段。在新記錄中設置相應的值并調用:code:[`](http://docs.iphalcon.cn/reference/tutorial.html#id2)save()`將在數據庫中存儲的數據記錄。:code:[`](http://docs.iphalcon.cn/reference/tutorial.html#id4)save()`方法返回一個布爾值,表示存儲的數據是否成功。
ORM自動轉義輸入以防止SQL注入,所以我們只需要將請求傳遞給:code:[`](http://docs.iphalcon.cn/reference/tutorial.html#id6)save()`方法。
附加的自動驗證會驗證字段定義為not null(必需)。如果我們不輸入任何必需的注冊表單中的字段,我們的屏幕將會看起來像這樣:

## 結束語(Conclusion)
這是一個非常簡單的教程,正如你所看到的,使用Phalcon很容易開始構建應用程序。Phalcon是一個在你的web服務器上沒有干擾、易于開發、特性優良的擴展。我們邀請你繼續閱讀手冊,這樣你就可以發現Phalcon提供的附加功能!
- 簡介
- 安裝
- 安裝(installlation)
- XAMPP下的安裝
- WAMP下安裝
- Nginx安裝說明
- Apache安裝說明
- Cherokee 安裝說明
- 使用 PHP 內置 web 服務器
- Phalcon 開發工具
- Linux 系統下使用 Phalcon 開發工具
- Mac OS X 系統下使用 Phalcon 開發工具
- Windows 系統下使用 Phalcon 開發工具
- 教程
- 教程 1:讓我們通過例子來學習
- 教程 2:INVO簡介
- 教程 3: 保護INVO
- 教程4: 使用CRUD
- 教程5: 定制INVO
- 教程 6: V?kuró
- 教程 7:創建簡單的 REST API
- 組件
- 依賴注入與服務定位器
- MVC架構
- 使用控制器
- 使用模型
- 模型關系
- 事件與事件管理器
- Behaviors
- 模型元數據
- 事務管理
- 驗證數據完整性
- Workingwith Models
- Phalcon查詢語言
- 緩存對象關系映射
- 對象文檔映射 ODM
- 使用視圖
- 視圖助手
- 資源文件管理
- Volt 模版引擎
- MVC 應用
- 路由
- 調度控制器
- Micro Applications
- 使用命名空間
- 事件管理器
- Request Environmen
- 返回響應
- Cookie 管理
- 生成 URL 和 路徑
- 閃存消息
- 使用 Session 存儲數據
- 過濾與清理
- 上下文編碼
- 驗證Validation
- 表單_Forms
- 讀取配置
- 分頁 Pagination
- 使用緩存提高性能
- 安全
- 加密與解密 Encryption/Decryption
- 訪問控制列表
- 多語言支持
- 類加載器 Class Autoloader
- 日志記錄_Logging
- 注釋解析器 Annotations Parser
- 命令行應用 Command Line Applications
- Images
- 隊列 Queueing
- 數據庫抽象層
- 國際化
- 數據庫遷移
- 調試應用程序
- 單元測試
- 進階技巧與延伸閱讀
- 提高性能:下一步該做什么?
- Dependency Injection Explained
- Understanding How Phalcon Applications Work
- Api
- Abstract class Phalcon\Acl