拉索费尔 / 辣椒
Requires
- php: >=5.3.0
This package is not auto-updated.
Last update: 2022-02-01 12:41:30 UTC
README
辣椒是一个小巧但充满活力的应用程序工具包,旨在帮助您轻松构建出色的RESTful Web应用程序。
辣椒 处于积极开发中, (见以下说明) 提供您所需的一切,但无需多余,易于初学者和专业人士使用。您只需要一个运行PHP >=5.3的Web服务器,如Apache或nginx。您一定会喜欢它。
弃用 (* 2012† 2014)
请注意,自2014年以来,辣椒已被废弃且不再维护。此存储库保留是为了提供维护现有辣椒项目所需的必要文档。如果您正在寻找辣椒的替代方案,您应该查看出色的 Silex 微框架 和所有精彩的 Symfony 组件。
另一个PHP工具包?
我制作了辣椒,因为我想帮助优秀的人创造出色的事物。除此之外,这就是我尽可能多地致力于辣椒的原因。它最初是一个资源,用于帮助在 fapprik 上创建更美观、更易用的内部工具。在整个开发过程中,我知道其他人也可以用它来做酷的事情。由于我是开源工具的巨大支持者,我想用这个工具回馈社区。
入门
下载辣椒
首先,您需要 下载 当前版本的辣椒并将其解压缩到您的虚拟主机的公共目录中。
设置您的Web服务器
为了拥有像 http://example.com/about
这样的美丽URL,辣椒需要您进行一些小的服务器配置——这非常简单,您可以在下面找到所需的一切。
Apache
如果您在Apache Web服务器上运行辣椒,请检查您的托管提供商是否启用了 mod_rewrite
模块(现在通常已启用)。如果已启用,您需要在辣椒安装的根目录中创建一个 .htaccess
文件(如果尚不存在),并将以下重写规则添加到其中。
RewriteEngine on RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L]
nginx
如果您在nginx Web服务器上运行辣椒,您需要将以下重写规则添加到您的站点配置中。
location / { root /path/to/papprika; index index.php; if (!-f $request_filename) { rewrite ^(.*)$ /index.php last; break; } if (!-d $request_filename) { rewrite ^(.*)$ /index.php last; break; } }
辣椒应用程序
要开始使用papprika,你只需要 require
papprika.php
文件并创建一个 papprika\Application
的实例。在你的控制器定义之后,调用你的应用程序的 run
方法。
require_once './papprika.php'; $app = new papprika\Application(); // your controller-definitions $app->run();
子目录
当然,papprika 也可以在子目录中使用。只需通过构造函数传递子目录路径(不带尾随斜杠)。
$app = new papprika\Application('/sub/directory');
路由
使用papprika,您必须定义路由和相应的控制器,当路由匹配时将调用这些控制器。在每条路由的开始处,您必须选择适当的方法(GET
、POST
、PUT
或 DELETE
),它描述了与资源的交互。如果您无法决定选择哪个方法,您可以使用 $app->any('/home', …)
来使用所有四种方法。每个路由有一个或多个模式,定义指向您的资源的路径,并且可以包含您能够捕获和处理的变量。如果想要为路由使用多个模式,只需传递一个数组而不是字符串。最后但同样重要的是,您必须使用闭包或方法(有关更多信息,请参阅「扩展papprika」)提供您的控制器。
$app->get('/home', function() { // do something });
这很简单,对吧?别担心,剩下的同样简单。让我们看一个更详细的示例,它展示了闭包的优点——可以从其定义外部导入内容的匿名函数。这与全局变量不同,因为外部状态不一定是全局的。
$news = array( 1 => array( 'date' => '2010-01-01', 'author' => 'thomas', 'title' => 'Hello World!', 'text' => 'Hello World!' ), 2 => array( 'date' => '2011-01-01', 'author' => 'thomas', 'title' => 'papprika 0.1 released', 'text' => 'Hello World!' ), 3 => array( 'date' => '2012-01-01', 'author' => 'thomas', 'title' => 'papprika 0.2 released', 'text' => 'Hello World!' ) ); $app->get('/news', function() use ($news) { echo '<ul>'; foreach($news as $id => $post) { echo '<li><a href="/news/'.$id.'">'.$post['title'].'</a></li>'; } echo '</ul>'; });
访问 /news
将返回新闻列表。use
-语句告诉闭包从外部作用域导入 $news
-变量,这允许我们在闭包中使用它。
动态路由
现在我们需要另一个控制器来查看单个新闻,这是通过动态路由实现的。
$app->get('/news/:id', function($id) use ($news) { if(!array_key_exists($id, $news)) { die('Post #'.$id.' wasn\'t found…'); } }, function($id) use ($news) { echo '<h1>'.$news[$id]['title'].'</h1>'; echo '<h2>'.$news[$id]['date'].'</h2>'; echo nl2br($news[$id]['text']); });
您注意到两个变化吗?一方面,我们将 :id
添加到模式中,这导致该路由定义有一个名为 id
的变量,它传递给闭包。当然,您可以使用尽可能多的这些变量。另一方面,我们在本例中使用了两个控制器来处理模式。您可以为这些中间回调提供无限数量的这些,这些回调必须是可调用的闭包或方法,并且将按照指定的顺序调用。这没有更大的原因,但允许您分离代码(首先检查传递的ID是否存在,然后显示它)。
如您所知,现在您已经了解了获取页面的所有内容,现在是时候创建第一条路由了:一个联系表单,我们将使用 mail
-函数来发送电子邮件。
$app->post('/contact', function() use ($app) { $message = $app->request('message'); mail('papprika@thomasrasshofer.com', 'Contact', $message); });
papprika为您提供了一个简单的方法来根据请求方法检索传输的变量。在上面的示例中,$app->request('message')
返回 $_POST['message']
。这适用于所有方法。
从配置文件添加路由
有时将您的路由从 index.php
中分离出来可能是有意义的——例如,如果您希望使 index.php
可重用且独立于应用程序的路由。因此,您可以从配置文件(INI文件)中添加路由。
$app->ini('./routing.ini');
[get] /contact = Thomas\TestApp\Controller\ContactController::indexAction [post] /contact = Thomas\TestApp\Controller\ContactController::sendAction
如您所注意到的,您必须使用方法来定义路由的回调。有关更多信息,请参阅「扩展papprika」。
出于安全原因,您应该通过您的web服务器拒绝对该配置文件的任何访问。
条件
在某些情况下,您可能只想匹配某些表达式——因此papprika允许您通过在由路由方法返回的控制器对象上调用assert
来使用正则表达式定义条件。
$app->get('/news/:id', function($id) use ($news) { // do something })->assert('id', '\d+');``` ```php $app->get('/hello/:name', function($name) { echo 'Hello, '.$name; })->assert('name', '([a-zA-Z]+)');
上面的示例确保id
参数是数字的,因为\d+
是一个匹配任意数量数字的正则表达式。
before / after / error
papprika允许您在每次请求之前和之后,或者在请求的页面未找到时运行代码。您只需传递闭包/方法即可。
$app->before(function() { echo '<!DOCTYPE html>'; echo '<html>'; echo '<head>'; echo '<meta charset="utf-8">'; echo '</head>'; echo '<body>'; echo '<header>Test-Application</header>'; })->after(function() { echo '<footer>© papprika</footer>'; echo '</body>'; echo '</html>'; })->error(function() { echo 'The page you requested couldn’t be found.'; });
如您所见,before
和after
对于某些头部/页脚内容来说非常漂亮。您注意到上面的示例中的路由是链式调用的吗?这有点像jQuery,非常适合组织/分组您的路由。
$app->get(array('/', '/news'), function() use ($news) { // do something })->get('/news/:id/:title', function($id, $title) use ($news) { // do something with $id and $title });
papprika\Templates
尽管有几个模板系统可用,但它们的方法都没有真正令人满意。其中许多使用它们自己的伪语法,这使得事情变得更复杂而不是简化整个模板问题。因此,papprika带来了自己的小型模板系统,它易于理解和使用。这在布局和逻辑分离方面可能有点危险,需要特别注意,但您将得到非常快速的实施和高可变的应用。因此,请始终仔细考虑函数应该放在哪里。
因为三行代码胜过千言万语,让我们看看在papprika应用程序中使用模板有多容易!
echo new papprika\Template('./footer.php', array( 'copyright' => 2011-'.date('Y') ));
哇,这真快,而且没有痛苦,对吧?让我们看一下footer.php
文件...
echo '<footer>© '.$this->copyright.' papprika</footer>'; echo '</body>'; echo '</html>';
就是这样。
自定义 / beforeParse / afterParse
如果您需要/想要,您可以自定义该类。此外,还有两个名为beforeParse
和afterParse
的方法,它们在模板解析并填充您的内容之前和之后执行。它们也需要一些自定义。想要一个例子吗?
class tpl extends papprika\Template { public function __construct($file, $data = array()) { parent::__construct('/var/www/templates/'.$file, $data); } function afterParse() { $this->_output = str_replace('HTML', '<abbr title="Hypertext Markup Language">HTML</abbr>', $this->_output); } }
papprika\File
papprika还为您提供了在应用程序中处理文件的一些有用且方便的函数。
方法 | 描述 |
---|---|
$file->name() |
返回文件名(不带扩展名) |
$file->filename() |
返回文件的完整名称 |
$file->extension() |
返回文件扩展名 |
$file->modified() |
返回文件的最后修改日期(Unix时间戳) |
$file->size() |
返回原始文件大小(字节) |
$file->niceSize() |
返回可读的文件大小(KB,MB,…) |
$latest = new papprika\File('./latest.zip'); echo '<a href="latest.zip">Download <em>'.$latest->name().'</em>.'.$latest->extension().' ('.$latest->niceSize().')</a>';
顺便说一句:对于图像,每个文件都有进一步的信息提供。
方法 | 描述 |
---|---|
$file->width() |
返回图像的宽度 |
$file->height() |
返回图像的高度 |
$file->mime() |
返回图像的MIME类型 |
$team = new papprika\File('./team.jpg'); echo '<img src="team.jpg" alt="" width="'.$team->width().'"> height="'.$team->height().'">';
遗憾的是,papprika还没有内置图像调整大小功能,但它提供了一些有用的函数来重新计算您图像的大小。当然,您不会得到更小的文件,但您可以将图像以不同的尺寸嵌入到您的应用程序中。
$logo = new papprika\File('./logo.jpg')->max(200); echo '<img src="logo.jpg" alt="" width="'.$logo->width().'" height="'.$logo->height().'">';
$logo = new papprika\File('./logo.jpg')->maxWidth(200); echo '<img src="logo.jpg" alt="" width="'.$logo->width().'" height="'.$logo->height().'">';
$logo = new papprika\File('./logo.jpg')->maxHeight(200); echo '<img src="logo.jpg" alt="" width="'.$logo->width().'" height="'.$logo->height().'">';
papprika\MySQL\Connection
papprika为您提供了在应用程序中使用MySQL数据库的简单方法。首先,您使用主机、用户名和密码连接到数据库,并选择数据库。
$db = new papprika\MySQL\Connection('localhost', 'root', '123', 'app');
字符集
您也可以轻松设置适当连接的默认字符集。
$db->charset('utf8');
papprika\MySQL\Queries
由于我们已经建立了连接,我们可以开始执行一些查询并获取结果行,这些结果以对象的形式返回。
$res = new papprika\MySQL\Query('SELECT * FROM news', $db); echo '<ul>'; while($post = $res->fetch()) { echo '<li><a href="/news/'.$post->id.'">'.$post->title.'</a></li>'; } echo '</ul>';
除了 fetch
方法外,还有三种其他方法可能对您的日常数据库业务也很有用。
获取行
rows
方法从适当的结果集中检索行数。此命令仅对返回实际结果集的 SELECT
或 SHOW
语句有效。
$res = new papprika\MySQL\Query('SELECT * FROM news', $db); echo $res->rows().' news found.';
受影响行
要检索受 INSERT
、UPDATE
、REPLACE
或 DELETE
查询影响的行数,affected
方法是您的得力助手。
$res = new papprika\MySQL\Query('UPDATE news SET title = "abc"', $db); echo $res->affected().' news were affected.';
插入的 ID
最后但同样重要的是,您可能希望检索由适当的查询生成的 AUTO_INCREMENT
列的 ID。
$res = new papprika\MySQL\Query('INSERT INTO news (title) VALUES ("Hello World")', $db); $newsId = $res->id();
转义
众所周知,周围有几个人试图对您的应用程序进行一些 SQL 注入。Papprika 就像您一样讨厌这些人,因此它提供了一个非常简单的语法来构建查询,同时准备和转义一切以防止注入。让我们来看一个例子。
$a = $app->request('a'); $b = $app->request('b'); $query = 'SELECT * FROM news WHERE a = "%s" && b = "%s"'; $res = new papprika\MySQL\Query($query, $a, $b, $db);
$a
和 $b
将自动转义并插入到 %s
占位符中。用法等同于 sprintf
。
只有 MySQL?:(
如您所注意到的,我们将 MySQL 相关内容放入了其自己的子命名空间(papprika\MySQL
)。那么,猜猜看!未来对其他数据库扩展的实施也已计划!:)
扩展 Papprika
当使用 Papprika 在大型项目中工作时,您可能有 20-30 个长的内联控制器,一切都会变得有些混乱。我听到的常见抱怨之一是 papprika 强迫您将所有代码放入单个文件中。但您不必这样做,相反,我强烈建议将您的控制器移动到类中。
namespace Thomas\TestApp\Controller; class ChatController { public function messageAction($id) { … } }
$app->get('/chat/message/:id', 'Thomas\TestApp\Controller\ChatController::messageAction');
如果类名太长,您可以轻松编写一个花哨的函数来缩短它们。
function controller($name) { list($class, $method) = explode('/', $name, 2); return sprintf('Thomas\TestApp\Controller\%sController::%sAction', ucfirst($class), $method); } $app->get('/chat/message/:id', controller('chat/message'));
因此,如您所希望看到的,Papprika 能够随着代码库的增长而有机地扩展。
Papprika 与框架对比
在 Papprika 和其庞大的兄弟之间划一条界限很困难。Papprika 不是框架,但它为您提供了构建自己框架所需的一切。如果您对做出所有自己的架构决策感到舒适,请使用 Papprika;如果不舒服,请使用完整的全栈框架。换句话说:您的应用程序有多大,有多少路由、控制器和服务,这并不重要。您将在技术层面上找到解决方案。您实际上将面临的挑战是人员。
完整示例
以下示例展示了上述提到的几个事物的组合。
$app = new papprika\Application(); $app->before(function() { echo new papprika\Template('./header.php', array( 'title' => 'News @ '.$_SERVER['HTTP_HOST'], 'time' => time() )); })->after(function() { echo new papprika\Template('./footer.php', array( 'copyright' => '2011-'.date('Y') )); })->error(function() { echo new papprika\Template('./404.php'); }); $db = new papprika\MySQL\Connection('localhost', 'root', '123', 'app'); $db->charset('utf8'); $app->get('/news', function() use ($db) { $news = new papprika\MySQL\Query('SELECT * FROM news', $db); echo '<ul>'; while($post = $news->fetch()) { echo '<li><a href="/news/'.$post->id.'">'.$post->title.'</a></li>'; } echo '</ul>'; }); $app->get('/news/:id', function($id) use ($db, $templates) { $query = 'SELECT title, text, date FROM news WHERE id = "'.$id.'"'; $res = new papprika\MySQL\Query($query, $db); if($res->rows() == 0) { echo 'FOUR OH FOUR'; } else { $post = $res->fetch(); echo new papprika\Template('./post.php', array( 'title' => $post->title, 'text' => nl2br($post->text), 'date' => date('F jS Y', $post->date) )); } })->assert('id', '\d+'); $app->get('/search', function() use ($db, $app) { $q = $app->request('q'); $query = 'SELECT title, text, date FROM news WHERE title = "%s"'; $res = new papprika\MySQL\Query($query, $q, $db); if($res->rows() == 0) { echo 'Nothing found…'; } else { echo '<ul>'; while($post = $res->fetch()) { echo '<li><a href="/news/'.$post->id.'">'.$post->title.'</a></li>'; } echo '</ul>'; } }); $app->run();
许可
版权所有 (c) 2012-2014 托马斯·拉斯霍弗
许可协议:MIT。
有关更多信息,请参阅 LICENSE。