kuzdo / mongoyii-php7
PHP7的Yii MongoDB ORM
Requires
- ext-mongodb: *
- mongodb/mongodb: ^1.0.0
README
MongoYii的PHP7版本,专为与新MongoDB驱动程序一起使用而设计
关于本文档
这不是旧文档的完整重写,而是仅详细说明PHP7扩展背后的新功能/想法。
测试应用程序
为此扩展提供了一个新的测试应用程序,它是旧测试应用程序的重新编写。
运行内置测试与之前相同。
问题/错误 & 询问
请使用新的GitHub问题跟踪器来解决您的问题和错误报告。如果您在论坛上发布,请在GitHub问题跟踪器中链接。
版本控制
此扩展,如之前一样,使用语义版本控制2.0.0。
许可证
此扩展的许可证也保持不变,BSD 3条款。简单来说:你可以随意使用它。
关于变更的注意事项
在我详细介绍此扩展的变更之前,值得注意的是,许多变更并非出于我的意愿,而是因为MongoDB驱动程序和PHPLib已从旧驱动程序发生了巨大的变化,我被迫适应这种新的工作标准。
您可能喜欢驱动程序和PHPLib的一些部分,但也可能不喜欢。
安装
所有安装现在都通过composer完成。我绝对不推荐手动安装,因为此扩展需要与MongoDB一起安装的驱动程序和PHPLib(这些也仅在composer上可用)。
要安装,请执行(对于dev-master
)
composer require sammaye/mongoyii-php7:*
命名空间
此扩展完全使用命名空间,如下所示
sammaye\mongoyii
不必担心!这不会给旧应用程序带来太多变化。我花费了大约3个小时来重写我的测试应用程序。
例如,以下是如何在测试应用程序中声明一个新的模型
use MongoDB\BSON\ObjectID; use MongoDB\BSON\UTCDateTime; use sammaye\mongoyii\Document; /** * Represents the article itself, and all of its data */ class Article extends Document { }
这将给您之前所有的相同内容。
现在让我为您展示如何在main.php
中配置session
和cache
组件(同样,来自我的测试应用程序)
'session' => array( 'class' => 'sammaye\mongoyii\util\Session', ), 'cache' => array( 'class' => 'sammaye\mongoyii\util\Cache', ),
您可以看到,命名空间的使用非常容易掌握。
作为一个最终的例子,让我们来看一个行为
public function behaviors() { return [ 'TimestampBehavior' => [ 'class' => 'sammaye\mongoyii\behaviors\TimestampBehavior' // adds a nice create_time and update_time Mongodate to our docs ] ]; }
您可以看到:在此扩展中使用命名空间非常容易。如果您不确定使用哪个命名空间,请查看您项目中的文件,并查看第一行中类似以下内容的地方
namespace sammaye\mongoyii\validators;
将类名添加到其中,您就有命名空间类了。
声明扩展
这部分是变化最大的部分。首先,为什么不展示我使用的示例呢
'mongodb' => [ 'class' => 'sammaye\mongoyii\Client', 'uri' => 'mongodb://sam:blah@localhost:27017/admin', 'options' => [], 'driverOptions' => [], 'db' => [ 'super_test' => [ 'writeConcern' => new WriteConcern(1), 'readPreference' => new ReadPreference(ReadPreference::RP_PRIMARY), ] ], 'enableProfiling' => true ],
现在,让我们分解一下
- 我将类声明为
sammaye\mongoyii\Client
。这是必需的,且不会是变量。 uri
是我的服务器连接字符串,遵循PHP文档中定义的标准- 选项《
options
》与《PHP文档》中的《uri
》选项直接相关,允许连接副本集等。 - 同样,驱动器选项也在《PHP文档》中。
- 《
enableProfiling
》允许您像以前一样分析查询。 - 现在,《
db
》已改为根据您要连接的数据库名称进行索引的数组。每个索引的值是对《PHPLibDatabase
对象》的选项。
基本上就是这样。写关注、读关注和其他属性现在按数据库执行,而不是在客户端级别。
如果您在配置中还有其他数据库,并想将特定一个设为默认,您可以添加如下的《active
》选项。
'super_test' => [ 'writeConcern' => new WriteConcern(1), 'readPreference' => new ReadPreference(ReadPreference::RP_PRIMARY), 'active' => true ]
客户端的 __get
只获取数据库吗?
是的,这是旧驱动器和新驱动器之间最大的变化。
客户端、数据库和集合之间存在清晰的分离。
因此,为了获取数据库,为检索集合做准备,您现在需要这样做:
Yii::$app->mongodb->selectDatabase()
身份验证
在新的PHP驱动器中,没有《auth()
》函数。您必须在《mongodb
》组件的《uri
》中进行身份验证。您将决定如何最好地处理您的身份验证数据库,但我决定将所有用户放入《admin
》数据库。这使得对单个数据库进行身份验证并按需切换变得极其简单。
使用多个数据库
如您所见,此扩展考虑了多个数据库。
如果您正在使用身份验证,请确保您以这种方式安排用户,即只需要一个套接字连接(如我上面所示),或者为每次需要身份验证创建一个新的组件。您不能再在连接后进行身份验证了。
至于重新编码《Document
》的《getDbConnection()
》,您现在可以使用以下方式使用《getCollection()
》(由于我提到的分离)。
public function getCollection() { return $this ->getDbConnection() ->selectDatabase('my_other_db_not_default') ->{$this->collectionName()}; }
您就完成了...
如果您真的知道自己在做什么,实际上可以设置一个数据库为《active
》,使其成为一系列过程默认的数据库。
Yii::$app->mongodb->selectDatabase('my_other_db', ['active' => true]);
但这仅适用于高级用户!
查询
这是与Yii1最大的不同之处。其他一切保持不变,不需要记录。
基本上,由于新的驱动器不再使用游标,而是使用流,我已经将《EMongoDBCriteria
》对象重写为《Query
》(类似于Yii2),并且它的工作方式甚至与Yii2相似。
然而,值得注意的是,《Document
》函数《find()
》和《findOne()
》返回与正常Yii1相同的值。那里没有变化。
值得注意的是,查询方式已更改,这与驱动器一致
Article::find( [ 'title' => 'Test' ], [ 'sort' => ['date_created' => -1], 'limit' => 2 // etc ] )
这是由于MongoDB使用预加载的流。因此,现在必须在形成PHP“游标”对象之前定义整个查询。
了解如何使用新驱动器进行查询的好方法是通过查看《MongoDB PHPLib》的GitHub文档。
作用域
由于《EMongoCriteria
》的变化,您可能需要重新编写模型作用域才能使它们正常工作。一个好例子是:
[ 'condition' => ['deleted' => 0], 'select' => ['_id' => 1], 'sort' => ['date' => -1], 'limit' => 2 'skip' => 1 ]
您在公共场合看不到很多变化,最大的变化是我不再使用SQL中的《project
》词进行《SELECT
》。MongoDB仍然使用,但我没有。
为什么没有EMongoCriteria?
这是一个由产生清洁和可行的查询需求而提出的决策。
我最终决定使我的查询更接近Yii2。这实际上意味着你现在可以这样做了
$docs = new Query([ 'from' => 'colllection', 'condition' => ['what' => 'ever'], 'limit' => 1 ])->all()
所以,这是从Yii1到Yii2的一个转变,但这是一个很好的转变。
查询日志
查询日志现在更加详细。不再是仅仅通过模型记录查询,现在将记录所有查询,这是由于一个小小的重写,这个重写本应该包含在原始扩展中。
现在,每次你从配置中的MongoDB组件获取集合时,它将返回我自定义的具有日志功能的Collection
类。
希望这能减少构建应用程序时的猜测工作。
关于怪癖的说明
子文档
MongoDB驱动程序的PHPLib将子文档作为ArrayObject
返回。这意味着在使用它们进行显示和表单等之前,你需要先通过(array)$subdoc
进行类型转换。
BSON序列化
请确保不要使用ObjectID
作为你的yii会话ID。这是因为存在这个问题:[无法序列化BSON对象](https://jira.mongodb.org/browse/PHPC-460),导致无法序列化BSON对象。
例如,这里是一个可用的UserIdentity
authenticate()
方法(也来自我的示例应用程序)
public function authenticate() { $record=User::model()->findOne(array('username' => $this->username)); if ($record === null) { $this->errorCode = self::ERROR_USERNAME_INVALID; } else if ($record->password !== crypt($this->password, $record->password)) { // check crypted password against the one provided $this->errorCode = self::ERROR_PASSWORD_INVALID; } else { $this->_id = (String)$record->_id; $this->errorCode = self::ERROR_NONE; } return !$this->errorCode; }
注意这一行:$this->_id = (String)$record->_id;
它非常重要,否则将无法正常工作!
DBRef
已弃用
是的,它已经弃用了。如果你在使用它,在使用此扩展之前需要将其删除。新驱动程序中没有处理它的功能。
未完成的工作
GridFS
这不是我的错。实际上,PHPLib中还没有实现这一点!
好了,我们完成了!
这就完了。其他的东西几乎都是一样的,酷吧?
请告诉我,如果我有遗漏或者需要更好地解释某些内容。