heydyho / plah
PHP小程序助手
Requires
- php: >=7.0.0
- mongodb/mongodb: ^1.8
README
PHP小程序助手(Plah)是一个小型库,包含一些可以作为PHP微框架(如著名的Slim Framework)插件的类。例如,它有一个Config类,可以使用文本文件来配置选项,或者有一个Language类,可以用于多语言设置。还包括一个MongoModel基类,这使得使用MongoDB而不是或与MySQL一起使用模型变得容易。
版本 3
版本 3是为PHP7+创建的。PHP5用户应坚持使用版本 2。
有一些破坏性更改,特别是对于MongoDB助手。因为旧的PHP mongo扩展已被弃用,所以Plah现在使用PHP mongodb扩展和库。尽管如此,像save()
这样的函数已被保留,并且像版本 2 一样工作。
安装
使用Composer将Plah添加到您的项目中。这将使自动加载变得简单。
{
"require": {
"heydyho/plah": "~3.0"
}
}
您也可以通过下载当前master分支的ZIP文件手动安装Plah。您需要将Plah命名空间注册到项目的自动加载程序中,或者您必须手动require/include必要的文件。这不是推荐的方法,因为某些类相互依赖并依赖于自动加载程序。
使用
由于Plah是一个工具集,因此没有单一的入口点,您可以使用它的部分或全部。Plah的每个部分都有自己的配置选项(如果需要)。它们通过一个获取配置选项数组的::config()
函数静态初始化。例如
\Plah\Config::config(array(
'dir' => __DIR__ . '/../myconfig',
'file_default' => 'myconfig-default',
'file_local' => 'myconfig-local'
));
通常您会在项目的index.php
文件或某种初始化文件/类中使用此功能。您不需要设置所有可能的选项,只需为计划使用的Plah部分设置选项即可。甚至不需要为单个部分设置所有选项,只需设置与默认值不同的选项即可。例如
\Plah\Config::config(array(
'dir' => __DIR__ . '/../myconfig'
));
这将仅更改配置目录并保留默认文件名。
组件
配置
Config类可以用于将配置选项放入单个文本文件中。以下格式用于配置文件
; Mailer settings
mail.host = "mail.example.com"
mail.user = "myuser@example.com"
mail.password = "mypassword"
以下是如何获取配置选项的方式
\Plah\Config::getInstance()->get('mail.host');
//You can also use a default value if you are not sure if a config value is set
\Plah\Config::getInstance()->get('mail.host', 'mail.example2.com');
//Another way
$config = new \Plah\Config();
$config->get('mail.host');
//Get all config items as array
$config = \Plah\Config::getInstance()->getAll();
echo $config['mail.host'];
有两个文件,一个默认配置和一个本地配置。本地配置文件中的选项会覆盖默认配置文件中的选项。此功能可以用于在开发设置中具有特殊选项,如其他密码等。请注意:将本地配置文件添加到.gitignore
文件中,以将其从您的存储库中排除。默认文件名为config-default.ini
和config-local.ini
。名称可以由相应的设置更改,.ini文件扩展名是硬编码的,并且必须存在。
设置
\Plah\Config::config(array(
'dir' => '../config',
'file_default' => 'config-default',
'file_local' => 'config-local'
));
平台
平台类可以用作配置类的补充或替代。基本上工作流程是相同的。有两个文件,默认情况下是 platform-default.ini
和 platform-local.ini
,但你也可以添加具有特定平台设置的额外文件。例如,如果你的项目有两个URL,一个用于英文版本,一个用于德文版本,那么新(未配置)的URL默认应该是英文。你可以有如下这样的文件
//platform-default.ini
language = "en"
//myplatform.com.ini
language = "en"
//myplatform.de.ini
language = "de"
代码看起来可能像这样
//Set the platform
$hostname = my_function_for_getting_the_hostname();
\Plah\Platform::getInstance()->set($hostname);
//Get an option
\Plah\Platform::getInstance()->get('language');
//Like with the Config class you can also use a default value
\Plah\Platform::getInstance()->get('language', 'en');
//Another way
$platform = new \Plah\Platform();
$platform->set($hostname);
$platform->get('language');
//Get all platform items as array
$platform = \Plah\Platform::getInstance()->getAll();
echo $platform['language'];
这会加载 platform-default.ini
文件,如果有,还会额外加载 platform-local.ini
文件以及与主机名匹配的 .ini
文件(主机名中不得包含 .ini
扩展名,它会被自动添加)。另一种用例可能是并行使用两个不同的配置文件。可以这样操作
//myconfig1.ini
language = "en"
//myconfig2.ini
language = "de"
$config1 = new \Plah\Platform();
$config2 = new \Plah\Platform();
$config1->set('myconfig1');
$config2->set('myconfig2');
$config1->get('language'); //gives you en
$config2->get('language'); //gives you de
如果你愿意,可以将配置和平台类结合起来,以便通过全局配置文件一次性覆盖特定平台的设置。例如,要在所有平台上关闭一个功能,而无需更改每个平台配置文件中的设置。
//myplatform1.ini
userupload = 1
//myplatform2.ini
userupload = 0
//myplatform3.ini
userupload = 1
//The code to get the userupload setting would look like this
\Plah\Config::getInstance()->get('userupload', \Plah\Platform::getInstance()->get('userupload'));
//To switch of the userupload for all platforms just add it to your config-default.ini (not the platform-default.ini)
userupload = 0
在这个例子中,通过主配置文件请求用户上传设置,作为后备,使用平台配置。这意味着只要主配置文件中没有用户上传选项,就会使用平台设置,一旦将选项添加到 config-default.ini
中,就会覆盖所有平台设置。请注意:platform-default.ini
文件不能覆盖特定平台的文件,它只用作选项的基础,如果特定平台文件中缺少选项。
设置
\Plah\Platform::config(array(
'dir' => '../platform',
'file_default' => 'platform-default',
'file_local' => 'platform-local'
));
语言
语言类可用于处理多语言设置。它与配置和平台类一样使用文本文件,这是对众所周知的但有时有点复杂的 Gettext
实现的替代方案,这些实现使用预编译的文件。
//en.ini
main.hello = "hello"
//de.ini
main.hello = "hallo"
\Plah\Language::getInstance()->set('en');
echo \Plah\Language::getInstance()->get('main.hello'); //hello
\Plah\Language::getInstance()->set('de');
echo \Plah\Language::getInstance()->get('main.hello'); //hallo
//Like with the Config class you can also use a default value
echo \Plah\Language::getInstance()->get('main.hello', 'hello');
//Another way
$language_en = new \Plah\Language();
$language_en->set('en');
$language_en->get('main.hello'); //hello
$language_de = new \Plah\Language();
$language_de->set('de');
$language_de->get('main.hello'); //hallo
//Get all language items as array
$language = \Plah\Language::getInstance()->getAll();
echo $language['main.hello'];
其中并没有多少魔法。选项 file_default
允许你设置默认语言文件。此文件始终被加载。所以如果 en 是你的主要语言,而 de 文件缺少一些文本,则会使用 en 文件中的文本。你应在项目的 index.php
或某种初始化文件/类中选择语言,可能取决于浏览器语言或 URL,就像平台示例中那样。请注意:file_default
选项不应用作你的平台默认语言设置,它只是一个用于后续翻译的基本语言文件。
设置
\Plah\Language::config(array(
'dir' => '../language',
'file_default' => 'en'
));
MongoModel
MongoModel 类可以用作使用 MongoDB 作为存储后端的模型的基础。一个基本模型可能看起来像这样
class User extends \Plah\MongoModel
{
//Basic database settings
protected static $_db = 'mydatabase';
protected static $_collection = 'user';
protected static $_key = '_id';
//Model properties
public $_id = null;
public $email = '';
public $password = '';
public $first_name = '';
public $last_name = '';
public static function createIndexes()
{
self::getCollection()->createIndex(array('email' => 1), array('background' => true));
}
}
$_db
设置数据库,$_collection
设置用于存储数据的 MongoDB 集合(表)。必须设置这些属性才能使模型工作。$_key
可用于设置类似主键的东西,用法可以在下面的示例中找到。模型的所有公共属性是写入集合的字段。createIndexes()
函数定义了你的模型所需的索引。你必须运行它当索引发生变化时。最佳实践是有一个文件运行所有模型的 createIndexes()
函数。
以下是如何使用你的模型的示例
//Create a new user, set some values and save it
$user = new User();
$user->email = 'myaddress@example.com';
$user->password = 'myunencryptedtopsecretpassword';
$user->first_name = 'John';
$user->last_name = 'Doe';
$user-save();
//Another way to set values
$user = new User();
$user->set('email', 'myaddress@example.com');
//Find a user with the email myaddress@example.com, change it and save it
$user = User::getInstance()->findOne(array('email' => 'myaddress@example.com'));
$user->email = 'mynewaddress@example.com';
$user-save();
//Find a user by the primary key (which is a MongoId in this case), change it and save it
try {
$user = new User(new MongoDB\BSON\ObjectId('555ef27165689edd457b23c7'));
$user->first_name = 'Jane';
$user-save();
} catch (\Exception $e) {
}
//Find all users with the first name John, walk over the results in a loop and show the email addresses
$users = User::getInstance()->find(array('first_name' => 'John'));
foreach ($users as $user) {
echo $user->email;
}
//Another way to get values
echo $user->get('email');
echo $user->get('email', 'unknown'); //Gets 'unknown' as default value if the email property doesn't exist
//Find a user with the email myaddress@example.com and remove it from the collection
$user = User::getInstance()->findOne(array('email' => 'myaddress@example.com'));
$user-remove();
//Get a PHP MongoCollection object to use all possible functions
$user_collection = User::getCollection();
函数 findOne()
、find()
、save()
和 remove()
是围绕由 MongoDB\Collection
对象提供的函数的包装器。findOne()
如果没有找到任何内容则返回 null
,就像原始函数一样,如果找到了,则返回你的模型类的实例。原始函数返回 null
或一个数组。find()
返回一个空数组或一个包含你的模型实例的数组,而原始函数返回一个空数组或一个返回数组的 MongoDB\Driver\Cursor
对象。
find()
函数有一些额外的参数用于排序和限制结果。以下是一个示例
//Find users with the first name John, order the results descending by last name and limit the results to the first 10 matching entries
$users = User::getInstance()->find(array('first_name' => 'John'), array(), array('last_name' => -1), 0, 10);
除了对find()
的结果进行排序和限制外,您还可以获取有无限制时找到的元素数量。这在对数据进行分页时很有用。请看以下示例
//Find users with the first name John, order the results descending by last name and limit the results to the first 10 matching entries
$users = User::getInstance()->find(array('first_name' => 'John'), array(), array('last_name' => -1), 0, 10, $count, $found);
echo $count; //This will be the number of all elements with the first name John, maybe 0, 5, 10 or even 100
echo $found; //This will be 10 or less because the result set is limited to max 10
count()
函数是MongoDB\Collection
的count()
函数的包装,但同时也接受查询参数以及跳过和限制参数,就像find()
函数一样。它返回由查询找到的、通过跳过和限制限制的数据集数量。请注意:只有在只关心数据集数量的情况下,这才有用,在所有其他情况下,find()
函数的$count
和$found
参数将做得更好,因为不需要第二次查询来获取数据集。以下是一个仅进行计数查询的示例
//Count the users with first name John
echo User::getInstance()->count(array('first_name' => 'John'));
您可以通过静态config()
函数为MongoDB连接设置一些选项。大多数选项应该是清晰的,auth_db
是用于身份验证的数据库,如果设置了用户名和密码。
设置
\Plah\MongoModel::config(array(
'host' => 'localhost',
'port' => '',
'user' => '',
'password' => '',
'auth_db' => ''
));
MongoAutoIncrement
MongoAutoIncrement类可以用来获取类似于SQL数据库使用的自动递增ID。MongoAutoIncrement需要一个数据库和一个集合,两者默认为autoincrement
,可以更改。内部会创建一个具有特定键的文档,每次尝试为该键获取下一个自动递增值时,序列号都会递增1。以下是一个简短的用法示例
echo \Plah\MongoAutoIncrement::getInstance()->getNext('user'); //1
echo \Plah\MongoAutoIncrement::getInstance()->getNext('user'); //2
echo \Plah\MongoAutoIncrement::getInstance()->getNext('user'); //3
echo \Plah\MongoAutoIncrement::getInstance()->getNext('event'); //1
echo \Plah\MongoAutoIncrement::getInstance()->getNext('event'); //2
echo \Plah\MongoAutoIncrement::getInstance()->getNext('user'); //4
echo \Plah\MongoAutoIncrement::getInstance()->getNext('event'); //3
//Another way
$auto_increment = new \Plah\MongoAutoIncrement();
echo $auto_increment->getNext('user'); //5
echo $auto_increment->getNext('event'); //4
您可以设置一个初始化值,以便在这是对键的第一个请求时,从该值开始计数
echo \Plah\MongoAutoIncrement::getInstance()->getNext('user', 1000); //1000
echo \Plah\MongoAutoIncrement::getInstance()->getNext('event'); //1
echo \Plah\MongoAutoIncrement::getInstance()->getNext('event', 1000); //2 <- Not the first request for 'event', the init value is ignored
您应该运行以下行一次来为集合创建必要的索引。
\Plah\MongoAutoIncrement::createIndexes();
MongoAutoIncrement类扩展了MongoModel类,因此在使用MongoAutoIncrement之前,请确保正确配置MongoModel。
设置
\Plah\MongoAutoIncrement::config(array(
'db' => 'autoincrement',
'collection' => 'autoincrement'
));
MongoSession
MongoSession类可以用于基于MongoDB的会话管理。该类不使用或依赖于PHP会话,但使用相同的流程。首先必须开始会话。如果页面的访问者已经有一个有效的会话ID,则从MongoDB集合中加载相应的数据,否则生成一个新的会话ID。为了“记住”访问者的会话ID,使用cookie。为了防止数据库中充满空会话(例如在DDoS攻击的情况下),不会自动将新会话写入数据库。当通过set()
函数设置第一个值时,以及在每次通过set()
函数设置新值时,会保存会话。会话的数据库和集合可以通过配置选项设置,以及cookie名称和过期时间。过期时间可以是0(这意味着cookie在浏览器关闭时结束),Unix时间戳或字符串如“1天”。以下是一个用法示例
//Configure the sessions to be valid for 1 day
\Plah\MongoSession::config(array(
'expires' => '1 day'
));
//Start the session
\Plah\MongoSession::getInstance()->start();
//Set a session value
\Plah\MongoSession::getInstance()->set('test', 'testvalue');
//Get a session value
echo \Plah\MongoSession::getInstance()->get('test'); //shows testvalue
//Get a session value with a default fallback value
echo \Plah\MongoSession::getInstance()->get('test2', 'testvalue2'); //shows testvalue2 because no other value was set for test2
//Another way
//This is not recommended because you have to make the $session variable globally available or call start() every time you create a new instance of the MongoSession class
$session = new \Plah\MongoSession();
$session->start();
$session->set('test', 'testvalue');
echo $session->get('test');
MongoSession类扩展了MongoModel类,因此在使用MongoSession之前,请确保正确配置MongoModel。MongoModel类的set()
函数被重写和修改,以便在每次更改属性时将对象保存到数据库中。这是为了保持会话数据的一致性,即使请求不能完全处理。
设置
\Plah\MongoSession::config(array(
'db' => 'session',
'collection' => 'session',
'name' => 'session',
'expires' => 0
));
Session
Session类是$_SESSION
超级全局变量的包装。您可以使用它来获取、设置或删除$_SESSION
的值。会话本身不是由Session类存储的。用法如下
//Get the session language
$language = \Plah\Session::getInstance()->get('language');
//Like with the Config class you can also use a default value
$language = \Plah\Session::getInstance()->get('language', 'en');
//Set the session language to en
\Plah\Session::getInstance()->set('language', 'en');
//Delete the language value
\Plah\Session::getInstance()->delete('language');
//Another way
$session = new \Plah\Session();
$language = $session->get('language');
$session->set('language', 'en');
$session->delete('language');
分页
分页类执行必要的计算以显示分页,并返回一个包含相关数字的数组。它需要四个参数:数据总数、每页条目数、当前活动页和所需分页数。返回的数组将包含第一页和最后一页、上一页和下一页、显示的页码、活动页、活动页的条目数、总条目数以及活动页的起始和结束数据。所有数字都不会小于1,以避免除以零的问题。同时,不接受小于1或非整数的数字进行计算。以下是一个示例
//Calculate a pagination
$total = 5;
$entries = 2;
$page = 1;
$pages = 4;
$pagination = \Plah\Pagination::getInstance()->get($total, $entries, $page, $pages);
print_r($pagination);
Array
(
[first] => 1
[last] => 3
[previous] => 1
[next] => 2
[pages] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
[active] => 1
[entries] => 2
[total] => 5
[start] => 1
[end] => 2
)
示例显示,即使需要4页,分页类也会计算出只需要1到3页,第4页将没有数据。
单例
单例类主要在其他Plah类内部使用。如您在上述示例中所见,您可以使用 ::getInstance() 获取类的静态版本。这是通过扩展单例类来实现的。例如
MyClass
{
public function my_function()
{
echo "my_function";
}
}
$myclass = new MyClass();
$myclass->my_function();
//By changing
MyClass
//to
MyClass extends \Plah\Singleton
//you can use your function like this
MyClass::getInstance()->my_function();
请注意:这仅适用于没有特殊设置且不需要不同实例的类。
IniParser
IniParser类由Config、Platform和Language类使用。它解析格式为key = "value"的文本文件,并返回一个关联数组。它主要基于PHP函数parse_ini_file()
,但总是返回一个数组,即使文件无法解析。如果您的项目需要,可以使用IniParser如下
$myoptions = \Plah\IniParser::getInstance()->get('myfile.ini');
//Another way
$parser = new \Plah\IniParser();
$myoptions = $parser->get('myfile.ini');