firelit/framework

简单的PHP框架和辅助类,适用于Web项目

v2.0.0 2016-10-27 15:52 UTC

This package is not auto-updated.

Last update: 2024-09-28 21:02:07 UTC


README

Build Status

Firelit的标准化PHP框架提供了一组有助于开发网站的类。它们被创建并命名空间化,以便可以轻松地与自动加载器一起使用,遵循PSR-4标准

需求

  • PHP版本5.4.0或更高
  • 测试PHP版本5.6.0或更高

外部PHP扩展

  • OpenSSL扩展(用于CryptoCryptoKey类)
  • cURL扩展(用于HttpRequest类)
  • 特定数据库的PDO扩展(例如,pdo-mysql,用于Query类)

如何使用

使用此库的最简单方法是使用Composer,它将自动处理依赖项和自动加载。

以下是如何将此软件包添加到您的composer.json文件下的require键的示例

    "require": {
        "firelit/framework": "^2.0"
    }

您也可以从命令行如下添加

php composer.phar require firelit/framework "^2.0"

或者,您可以选择手动方式,设置自己的自动加载器,并将项目文件从lib/复制到您的项目目录。

MVC架构

此框架包含用于支持使用MVC架构构建应用程序的类。

使用这些类在单个入口Web应用程序中的示例实现

<?php

// Setup
$resp = Firelit\Response::init();
$reqs = Firelit\Request::init();
$router = Firelit\Router::init($reqs);

$router->add('GET', '!^/Hello$!', function() {
	// Simple route, you'd go to http://example.com/Hello and get this:
    echo 'World!';
});

$router->add('GET', '!^/redirect$!', function() use ($resp) {
	// Redirect example
    $resp->redirect('/to/here');
});

$router->add('POST', '!^/forms!', function() {
    // Process the POST request in a controller
    Firelit\Controller::handoff('Controller\Forms', 'process');
});

$router->add('GET', '!^/groups/([^0-9]+)$!', function($matches) {
	// Match URL parts with regular expressions to extract information
	echo 'You selected group #'. $matches[0];
});

// You can nest routes to keep things organized
$myNestedRoutes = require_once('routes/api.php');
$router->add('GET', '!^/api/!', $myNestedRoutes);

$router->defaultRoute(function() use ($resp) {
	// A default route is a backstop, catching any routes that don't match
    $resp->code(404);
    echo 'Sorry, no can do';
});

$router->exceptionHandler(function($e) use ($resp) {
    $resp->setCode(500);
    echo $e->getMessage();
    exit;
});

$router->go();

请注意,此设置被认为是单个入口,因此必须在Web服务器上进行轻微修改,以便强制它对所有HTTP请求使用主脚本(例如,index.php)。以下是来自WordPress项目的示例.htaccess,它将配置Apache将所有请求路由到单个入口脚本。

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

包含的类

ApiResponse

API端点的响应处理类。可以处理所有HTTP响应代码和JSON & 有限 XML。设置模板以确保某些字段始终随响应发送。

示例用法

<?php

$resp = Firelit\ApiResponse::init('JSON');

$resp->setTemplate(array(
	'success' => false,
	'message' => ''
));

$resp->code(404);

$resp->respondAndEnd(array(
	'message' => 'Resource could not be located.'
));

缓存

一个缓存类。首先使用php内存缓存(一个全局PHP变量)并可配置为使用memcached第二。在每次缓存检查后设置静态变量$cacheHit$cacheMiss

示例用法

<?php

Firelit\Cache::config(array(
	'memcached' => array(
		'enabled' => true,
		'servers' => array(
			array(
				'host' => 'localhost',
				'port' => 11211,
				'persistent' => true,
				'weight' => 1,
				'timeout' => 1
			)
			/* Multiple servers can be added */
		)
	)
));

$val = Firelit\Cache::get('randomValue', function() {

	// If cache miss, this closure will execute this closure, storing the returned value in cache
	return mt_rand(0, 1000);

});

if (Firelit\Cache::$cacheHit)
	echo 'Cache hit!';

// Set a value to null in order to remove it from cache
Firelit\Cache::set('randomValue', null);

控制器

一个用于包装控制器逻辑的最小类。扩展以添加额外的控制器通用方法和静态数据。它还有一个“交接”功能调用,用于简化对控制器对象的调用。

交接语法:Firelit\Controller::handoff(ControllerClassName [, OptionalMethodName [, MethodParameter1 [, ... ]]])

<?php

class DashboardController extends Firelit\Controller
{

	public function show($userName)
	{
		// This skelton controller method retrieves a view template, populates and renders
		$data = GetMyData::now();

		Firelit\View::quickRender('DashboardView', 'LoggedinLayout', array('name' => $userName));
	}

}

// You could invoke this as you would any class, but the handoff method makes it a one-liner:
Firelit\Controller::handoff('DashboardController', 'show', $userName);

加密类

Crypto、CryptoKey和CryptoPackage是使用OpenSSL(基于此文章)的加密/解密辅助类。这些类可以生成加密安全的密钥,并使用行业标准对称加密(RSA)和私钥加密(AES)方案进行加密和解密。

请注意,由于所需处理能力,AES加密不适用于长字符串(80个字符或更多,取决于密钥位数)——它很快变得效率低下。对于较长的字符串,应使用RSA加密明文,并使用AES加密密钥。这正是CryptoPackage在序列化和反序列化主题以快速存储和检索加密存储中任何类型(字符串、对象、数组等)变量时为您所做的。

示例加密/解密用法

<?php

$mySecret = 'Super secret!';

// Private key encryption
$key = Firelit\CryptoKey::newPrivateKey(); // Can be 1024, 2048 or 3072-bit
$crypto = new Firelit\Crypto($key);

$ciphertext = $crypto->encrypt($mySecret)->with(Firelit\Crypto::PUBLIC_KEY);

$plaintext = $crypto->decrypt($ciphertext)->with(Firelit\Crypto::PRIVATE_KEY);

// Symmetric key encryption
$key = Firelit\CryptoKey::newSymmetricKey(); // Can be 128, 192 or 256-bit
$crypto = new Firelit\Crypto($key);

$ciphertext = $crypto->encrypt($mySecret);

$plaintext = $crypto->decrypt($ciphertext);

// Robust, mixed-type private key encryption
$key = Firelit\CryptoKey::newPrivateKey(); // Can be 1024, 2048 or 3072-bit
$crypto = new Firelit\CryptoPackage($key);

$object = (object) array(
	'test' => true,
	'string' => $mySecret . $mySecret . $mySecret
);

$ciphertext = $crypto->encrypt($object)->with(Firelit\Crypto::PUBLIC_KEY);

$objectBack = $crypto->decrypt($ciphertext)->with(Firelit\Crypto::PRIVATE_KEY);

DatabaseObject

这是一个无模式的、类似活动记录的类,用于创建、检索和操作数据库行作为对象。为了设置它,为每个表扩展类,指定主键行和其他特殊值行(例如,序列化行、日期/时间行等),以启用内置的预存储和检索值操作。

<?php

class Person extends Firelit\DatabaseObject
{

    protected static $tableName = 'People'; // The table name
    protected static $primaryKey = 'id'; // The primary key for table (array for multiple keys, false if n/a)

    // Columns that should be automatically php-serialized when using
    protected static $colsSerialize = array('nicknames');
    // Columns that should be automatically JSON-encoded/decoded when using
    protected static $colsJson = array();
    // Columns that should be a DateTime object when loaded from DB
    protected static $colsDateTime = array('created');

}

// Create a new person
$newPerson = Person::create(array(
	'name' => 'Sally',
	'email' => 'sally@example.com',
	'nicknames' => array('Sal'),
	'created' => new DateTime()
));

// Find by the primary key
$person = Person::find(23);

// Returns FALSE if not found
if (!$person) die('Not found');

// Serialized columns are serialized before being saved and unserialized on retrieval
$person->nicknames = array(
	'Bill',
	'Will',
	'William'
);

// Easily save to database (uses primary key set during retrieval)
$person->save();

// Or find rows by other columns
$persons = Person::findBy('email', 'test@test.com');

// DatabaseObject::findBy returns an iterable object (Firelit\QueryIterator) for search results
foreach ($persons as $person) {
	// DateTime columns are converted to DateTime objects on retrieval
	echo $person->name .' was created '. $person->created->format('n/j/y') . PHP_EOL;
}

HttpRequest

一个用于管理对新HTTP请求和网站的类。包括基于文件的cookie支持。

示例用法

<?php

Firelit\HttpRequest::config(array(
	'userAgent' => 'My little user agent string'
));

$http = new Firelit\HttpRequest();

$http->enableCookies();

// 'get', 'post' and 'other' (for put, delete, etc) are also available methods
$http->get('http://www.google.com/');

// Hmmm, I wonder what cookies Google sets...
echo '<pre>'. file_get_contents($http->cookieFile) .'</pre>';

Query

一个数据库交互类和SQL查询创建器。使数据库连接管理和SQL编写变得稍微容易一些。

示例用法

<?php

// One-time connection setup
Firelit\Registry::set('database', array(
	'type' => 'mysql',
	'name' => 'database',
	'host' => 'localhost', // Hostname or IP acceptable here
	'port' => '3306', // Can be left undefined to use default port
	'user' => 'username',
	'pass' => 'password'
));

// Or specify the DSN string for PDO to connect to other types of databases
Firelit\Registry::set('database', array(
	'type' => 'other',
	'dsn' => 'sqlite::memory:'
));

/* 
Alternatively, database settings can be specified using the following environmental variables:
 - DB_NAME
 - DB_HOST
 - DB_PORT
 - DB_USER
 - DB_PASS
*/

$q = new Firelit\Query();

$q->insert('TableName', array(
	/* columnName => value */
	'name' => $name,
	'state' => $state
));

if (!$q->success()) die('It did not work :(');

$q->query("SELECT * FROM `TableName` WHERE `name`=:name", array('name' => $name));

while ($row = $q->getRow())
	echo $row['name'] .': '. $row['state'] .'<br>';

使用config方法设置数据库连接

  • config( $configArray );

用于构建和执行查询的方法

  • query( $sql, [ $dataArray ]);
  • insert( $tableName, $dataArray );
  • replace( $tableName, $dataArray );
  • select( $tableName, [ $selectFieldsArray, [ $whereStatement, [ $whereDataArray, [ $limit, [ $range ]]]]] );
  • update( $tableName, $dataArray, $whereStatement, [ $whereDataArray, [ $limit, [ $range ]]] );
  • delete( $tableName, $whereStatement, [ $whereDataArray, [ $limit, [ $range ]]] );

用于获取查询状态和/或结果的方法

  • getRes();如果查询成功执行返回true
  • getRow();从成功的select查询返回下一行数据
  • getAll();从成功的select查询返回所有数据行
  • getNewId();从新插入的数据行返回新ID
  • getAffected();返回受查询影响的行数
  • getNumRows();返回select查询返回的数据行数(对于所有数据库可能不可靠)
  • getError();返回错误消息
  • getErrorCode();返回错误代码
  • success();如果查询成功执行返回true
  • logError(LogEntry $logger, $file, $line);是一个辅助方法,用于记录任何查询错误

QueryIterator

一个PHP 迭代器,允许在不实际预检索所有结果的情况下传递Query结果集。QueryIterator对象然后可以在foreach循环中使用,其中它按需获取所需的下一行。

示例用法

<?php

function demo($type)
{

	$q = new Firelit\Query();

	$q->query("SELECT * FROM `TableName` WHERE `type`=:type", array('type' => $type));

	return new Firelit\QueryIterator($q);

}

$results = demo('best_ones');

foreach ($results as $index => $value) {
	// Do something!
}

QueryIterator构造函数接受两个参数,第二个是可选的:Query对象和应从中检索表行的对象。

Request

一个类,它捕获传入的HTTP请求作为一个单一的对象,并执行任何必要的初步工作。围绕请求中的所有重要参数提供了一个很好的类包装,并允许轻松清理。

示例用法

<?php

$req = new Firelit\Request::init( function(&$val) {

	// Remove any invalid UTF-8 characters from $_POST, $_GET and $_COOKIE
	Firelit\Strings::cleanUTF8($val);

});

// Filtered $_POST, $_GET and $_COOKIE parameters can then be accessed via the object
if ($req->get['page'] == '2') showPageTwo();

示例用法

<?php
// Handle JSON body parsing and PUT requests automatically
$req = new Firelit\Request::init(false, 'json');

// Filtered $_POST, $_GET and $_COOKIE parameters can then be accessed via the object
$newName = $req->put['name'];

可用属性

  • cli如果页面是从命令行界面加载的,则返回true
  • cookie返回所有数据(按指定过滤),最初通过$_COOKIE可用
  • get返回所有数据(按指定过滤),最初通过$_GET可用
  • headers返回所有HTTP头部的数组(如果使用Apache作为Web服务器)
  • host设置为HTTP请求中指定的主机
  • method设置为HTTP请求方法(例如,'POST'、'PUT'等)
  • path设置为请求的路径(例如,'/folder/test.php')
  • post 将返回所有通过 $_POST 可用(根据指定过滤)的数据。
  • protocol 将返回请求协议(例如,HTTP 1.0 或 HTTP 1.1)。
  • proxies 将返回一个可能用作代理的 IP 地址数组。
  • put 将返回 HTTP 请求体中所有数据(根据指定过滤)(如果为 PUT 请求)。
  • referer 将返回客户端指定的 HTTP 引用。
  • secure 如果连接是安全的(即,'HTTPS://'),将返回 true。
  • uri 将返回请求的完整 URI,包括 HTTP 或 HTTPS。

响应

一个管理服务器对传入请求的响应的类。默认启用输出缓冲。包括辅助函数,这些函数可以更轻松地更改 HTTP 响应代码和执行重定向。请注意,ApiResponse 类继承自此类,以利用其响应管理。

可用方法

  • contentType() 可以用来设置响应的内容类型(例如,'application/json')。
  • redirect() 可以用来将访客重定向到另一个 URI。
  • setCallback() 可以用来设置一个回调函数,在发送之前处理服务器输出。
  • setCode() 可以用来设置 HTTP 响应代码(例如,404)。

会话

会话管理类,可以使用 PHP 的原生会话功能(以及可选的数据库存储)。您可以为会话对象设置任何属性名,并动态保存(使用魔法获取器和设置器方法)。实现 PHP 原生的 SessionHandlerInterface 以创建自己的会话处理程序或会话存储引擎。此库提供名为 Firelit\DatabaseSessionHandler 的数据库实现。通过实现 SessionHandlerInterface 并在实例化 Session 对象时使用此类对象来创建自己的会话处理程序。或者,不指定此参数,以简单地使用 PHP 内置的基于 cookie 和文件的会话处理。

请注意,如果您使用 Firelit\DatabaseSessionHandler,会话的过期不是由 session.gc_maxlifetime 控制的,就像您在没有使用会话处理程序的情况下使用 Session 类一样。

示例用法

<?php

$sess = new Firelit\Session::init(new Firelit\DatabaseSessionHandler);

$sess->loggedIn = true;
$sess->userName = 'Peter';

echo '<p>Hello '. htmlentities($sess->userName) .'</p>';

字符串

一组字符串辅助函数封装在一个类中。

示例用法

<?php
// Check if an email is valid
$valid = Firelit\Strings::validEmail('test@test.com'); // $valid == true

// Clean the strings in the array for all valid UTF8
Firelit\Strings::cleanUTF8($_POST); // The parameter is passed by reference and directly filtered

// Normalize the formatting on a name or address
$out = Firelit\Strings::nameFix('JOHN P.  DePrez SR'); // $out == 'John P. DePrez Sr.'
$out = Firelit\Strings::addressFix('po box 3484'); // $out == 'PO Box 3484'

// Multi-byte HTML and XML escaping
$out = Firelit\Strings::html('You & I Rock'); // $out == 'You &amp; I Rock'
$out = Firelit\Strings::xml('You & I Rock'); // $out == 'You &#38; I Rock'

// Format the string as a CSV cell value (escaping quotes with a second quote)
$out = Firelit\Strings::csv('John "Hairy" Smith'); // $out == '"John ""Hairy"" Smith"'

// Multi-byte safe string case maniuplation
$out = Firelit\Strings::upper('this started lower'); // $out == 'THIS STARTED LOWER'
$out = Firelit\Strings::lower('THIS STARTED UPPER'); // $out == 'this started upper'
$out = Firelit\Strings::title('this STARTED mixed'); // $out == 'This Started Mixed'
$out = Firelit\Strings::ucwords('this STARTED mixed'); // $out == 'This STARTED Mixed'

变量

一个用于管理应用程序级别持久变量的类。Vars 通过魔法设置器和获取器实现,因此您可以使用任何名称为您的变量,并使用任何类型的持久数据存储。存储可以通过创建自定义获取器和设置器函数(例如,用于将值读取/写入文件)自定义定义,或者您可以将其保留为默认设置(将值存储在数据库中)。

示例用法

<?php
// Configuration
new Firelit\Vars::init(array(
	'table' => 'Vars',
	'col_name' => 'Name',
	'col_value' => 'Value'
));

// Later usage
$vars = new Firelit\Vars::init();

// Set a persistent application variable with any name accepted by your store
$vars->maintenanceMode = true;

// Read a persistent application variable
if ($vars->maintenanceMode) die('Sorry, under construction.');

视图

一个用于管理视图的类:视图模板、视图布局(包裹视图模板)、部分(用于其他地方使用的视图的一部分)和资产管理(自动将所需资产插入到 HTML 中)。

布局类似于视图模板,其中视图模板位于其中。它们通常包含围绕更具体视图元素的重复 HTML 包装器。布局是一个可选组件。如果没有指定布局,则单独渲染视图模板。

以下是一个布局示例,保存为 views\layouts\main.php

<?php if (!is_object($this)) die; ?> <!-- Prevent direct calls to view files -->
<html>
	<head>
		<title>Example Layout</title>
	</head>
	<body>
		<?php $this->yieldNow(); ?> <!-- Firelit\View::yieldNow() specifies the place for the view template -->
	</body>
</html>

现在是一个视图文件示例,保存为 views\templates\dashboard.php

<?php if (!is_object($this)) die; ?> <!-- Prevent direct calls to view files -->
<div id="user-info">
	<?=htmlentities($name); ?>
</div>
<div id="main">
	<h1>Dashboard</h1>
	<p>Lorem Ipsum</p>
	<?php $this->includePart('partials\stuff'); ?> <!-- Firelit\View::includePart() brings in other view templates -->
</div>

当调用视图时,使用在视图中使用的数据(如上例中的 $name 所示)通过关联数组指定。

<?php
// The view folder can be changed with a static property. The php extension is added if not supplied.
$view = new Firelit\View('templates\dashboard', 'layouts\main');

// Here the view is sent to the client
// The data to be available in the view is given as an array
$view->render(array('name' => 'John'));