biberltd/phporient

PHPOrient 是基于 OrientDB 二进制协议的一个优秀的 PHP 驱动。

v1.2.3 2015-11-09 00:41 UTC

This package is not auto-updated.

Last update: 2022-11-19 01:16:50 UTC


README

Build Status Coverage Status

PHPOrient 是基于 OrientDB 二进制协议的 PHP 驱动。

状态:稳定报告任何您发现的错误,以便我们可以为所有人改进库。

要求

  • PHP 版本 >= 5.4 (启用 Socket 扩展)
  • Orientdb 版本 1.7.4 或更高。
PhpOrient 在 32 位和 64 位平台上都可以运行。
警告:如果您使用 32 位平台,必须在您的应用程序中使用以下库之一,以避免 Java long 整数中丢失有效数字。此外,这些 PHP 模块应被加载以提高这些系统上的驱动程序性能。
在 PhpOrient 中,出于设计考虑,由于 PHP 的平台依赖性,数字始终被视为字符串。在 32 位平台上,数字必须被视为字符串,因为大于 2^32 的值将会丢失,并且必须使用 BCMath/GMP 模块来避免这种情况,以使所有平台(32 位和 64 位)的结果一致,并将如何使用其自身数据的决定权留给用户/开发者(通过手动转换),所有数值数据类型都使用字符串。

安装

PhpOrient 的主要公共仓库托管在 https://github.com/Ostico/PhpOrient.git

要安装库的最新版本,只需输入

git clone https://github.com/Ostico/PhpOrient.git

您希望其文件所在的位置。

如果您尚未全局安装,您必须下载 composer。只需在您的 PhpOrient 目录中运行此命令。

php -r "readfile('https://getcomposer.org.cn/installer');" | php

现在获取与 PhpOrient 一起工作的所需库

php composer.phar --no-dev install
注意

如果您已经安装了Composer或者您的现有项目正在使用它,您可以通过Composer安装或添加 PhpOrient https://packagist.org.cn/packages/ostico/phporient,它与这个GitHub仓库相关联(因此它始终是最新的),并将其添加为项目的依赖项。

php composer.phar require "ostico/phporient:dev-master" --update-no-dev

贡献

  • 分支项目。
  • 做出您的更改。
  • 为它添加测试。这很重要,这样我就不会在未来的版本中无意中破坏它。
  • 向我发送拉取请求(master分支的拉取请求将被拒绝)
  • ???
  • 利润

如何运行测试

  • 使用以下命令获取开发库
php composer.phar install
  • 通过从项目目录运行 ./ci/ci-start.sh 来引导orient,它将下载最新的orient并对测试的配置和数据库进行一些更改
  • 运行:./vendor/bin/phpunit

用法

PhpOrient指定自动加载信息,Composer生成一个vendor/autoload.php文件。您只需包含此文件,即可免费获得自动加载,并使用完全限定名称声明对PhpOrient客户端的使用。

require "vendor/autoload.php";
use PhpOrient\PhpOrient;

完整的phpdoc参考可在此处找到 ApiIndex 或在 PhpOrient Wiki

客户端初始化

有几种方法可以初始化客户端

$client = new PhpOrient( 'localhost', 2424 );
$client->username = 'root';
$client->password = 'root_pass';
$client = new PhpOrient();
$client->hostname = 'localhost';
$client->port     = 2424;
$client->username = 'root';
$client->password = 'root_pass';
$client = new PhpOrient();
$client->configure( array(
    'username' => 'root',
    'password' => 'root_pass',
    'hostname' => 'localhost',
    'port'     => 2424,
) );

连接以执行服务器管理操作

$client = new PhpOrient( 'localhost', 2424 );
$client->username = 'root';
$client->password = 'root_pass';
$client->connect();
$client = new PhpOrient( 'localhost', 2424 );
$client->connect( 'root', 'root_pass' );

创建数据库

$new_cluster_id = $client->dbCreate( 'my_new_database',
    PhpOrient::STORAGE_TYPE_MEMORY,   # optional, default: STORAGE_TYPE_PLOCAL
    PhpOrient::DATABASE_TYPE_GRAPH    # optional, default: DATABASE_TYPE_GRAPH
);

删除数据库

$client->dbDrop( $this->db_name, 
    PhpOrient::STORAGE_TYPE_MEMORY  # optional, default: STORAGE_TYPE_PLOCAL
);

检查数据库是否存在

$client->dbExists( 'my_database', 
    PhpOrient::DATABASE_TYPE_GRAPH   # optional, default: DATABASE_TYPE_GRAPH
);

获取数据库列表

$client->dbList();

打开数据库

$ClusterMap = $client->dbOpen( 'GratefulDeadConcerts', 'admin', 'admin' );

发送命令

这应该仅用于对数据库执行非幂等命令

$client->command( 'create class Animal extends V' );
$client->command( "insert into Animal set name = 'rat', specie = 'rodent'" );

执行查询

$client->query( 'select from followed_by limit 10' );

执行异步查询(回调)

$myFunction = function( Record $record) { var_dump( $record ); };
$client->queryAsync( 'select from followed_by', [ 'fetch_plan' => '*:1', '_callback' => $myFunction ] );

加载记录

$record = $client->recordLoad( new ID( '#3:0' ) )[0];
$record = $client->recordLoad( new ID( 3, 0 ) )[0];
$record = $client->recordLoad( new ID( [ 'cluster' => 3, 'position' => 0 ] ) )[0];

创建记录

$recordContent = [ 'accommodation' => 'houses', 'work' => 'bazar', 'holiday' => 'sea' ];
$rec = ( new Record() )->setOData( $recordContent )->setRid( new ID( 9 /* set only the cluster ID */ ) ); 
$record = $this->client->recordCreate( $rec );

更新记录

更新记录必须有一个。

如果您没有记录,可以指定RID和数据创建一个新的记录

$_recUp = [ 'accommodation' => 'hotel', 'work' => 'office', 'holiday' => 'mountain' ];
$recUp = ( new Record() )->setOData( $_recUp )->setOClass( 'V' )->setRid( new ID( 9, 0 ) );
$updated = $client->recordUpdate( $recUp );

否则,您可以处理之前加载/创建的记录

/*
 Create/Load or Query for a Record
*/
$recordContent = [ 'accommodation' => 'houses', 'work' => 'bazar', 'holiday' => 'sea' ];
$rec = ( new Record() )->setOData( $recordContent )->setRid( new ID( 9 ) );
$record = $client->recordCreate( $rec );

/*
or Query for an existent one
*/
$record = $client->query( "select from V where @rid = '#9:0'" )[0];

/*
 NOW UPDATE
*/
$_recUp = [ 'accommodation' => 'bridge', 'work' => 'none', 'holiday' => 'what??' ];
$recUp = $record->setOData( $_recUp );
$updated = $client->recordUpdate( $recUp );

使用节点深度导航加载记录(回调)

$myFunction = function( Record $record) { var_dump( $record ); };
$client->recordLoad( new ID( "9", "1" ), [ 'fetch_plan' => '*:2', '_callback' => $myFunction ] );

删除记录

$delete = $client->recordDelete( new ID( 11, 1 ) );

执行OrientDB SQL批处理

$cmd = 'begin;' .
       'let a = create vertex set script = true;' .
       'let b = select from v limit 1;' .
       'let e = create edge from $a to $b;' .
       'commit retry 100;';

$lastRecord = $client->sqlBatch( $cmd );

事务

// create some record stuffs
$rec2Create = [ 'oClass' => 'V', 'oData' => [ 'alloggio' => 'albergo' ] ];
$rec        = Record::fromConfig( $rec2Create );
$first_rec  = $client->recordCreate( $rec );

$rec3Create = [ 'oClass' => 'V', 'oData' => [ 'alloggio' => 'house' ] ];
$rec        = Record::fromConfig( $rec3Create );
$sec_rec    = $client->recordCreate();

//get the transaction and start it
$tx = $client->getTransactionStatement();

//BEGIN THE TRANSACTION
$tx = $tx->begin();

//IN TRANSACTION
$recUp = [ 'accommodation' => 'mountain cabin' ];
$rec2 = new Record();
$rec2->setOData( $recUp );
$rec2->setOClass( 'V' );
$rec2->setRid( $first_rec->getRid() );
$rec2->setVersion( $first_rec->getVersion() );

$updateCommand = $client->recordUpdate( $rec2 );

$createCommand = $client->recordCreate(
    ( new Record() )
        ->setOData( [ 'accommodation' => 'bungalow' ] )
        ->setOClass( 'V' )
        ->setRid( new ID( 9 ) )
);

$deleteCommand = $client->recordDelete( $sec_rec->getRid() );

//Attach to the transaction statement, they will be executed in the same order
$tx->attach( $updateCommand );  // first
$tx->attach( $createCommand );  // second
$tx->attach( $deleteCommand );  // third

$result = $tx->commit();

/**
 * @var Record $record
 */
foreach ( $result as $record ){
    if( $record->getRid() == $first_rec->getRid() ){
        $this->assertEquals( $record->getOData(), [ 'accommodation' => 'mountain cabin' ] );
        $this->assertEquals( $record->getOClass(), $first_rec->getOClass() );
    } else {
        $this->assertEquals( $record->getOData(), [ 'accommodation' => 'bungalow' ] );
        $this->assertEquals( $record->getOClass(), 'V' );
    }
}

//check for deleted record
$deleted = $client->recordLoad( $sec_rec->getRid() );
$this->assertEmpty( $deleted );

获取数据库大小(需要打开数据库)

$client->dbSize();

获取集群记录ID的范围

$data = $client->dataClusterDataRange( 9 );

获取一个或多个集群中的记录数量

$client->dataClusterCount( $client->getTransport()->getClusterMap()->getIdList() );

获取打开数据库中的记录数量

$result = $client->dbCountRecords();

重新加载数据库信息

此方法会自动更新客户端集群映射。在创建类或添加/删除数据集群后可以使用。

$reloaded_list = $client->dbReload();  # $reloaded_list === $client->getTransport()->getClusterMap()

创建新的数据集群

$client->dataClusterAdd( 'new_cluster', 
    PhpOrient::CLUSTER_TYPE_MEMORY  # optional, default: PhpOrient::CLUSTER_TYPE_PHYSICAL
);

删除数据集群

$client->dataClusterDrop( 11 );

持久连接(会话令牌)

自版本27引入后,扩展了使用基于令牌的会话的功能。此功能必须在服务器配置中启用。

  • 在第一次协商时,客户端可以使用PhpOrient::setSessionToken方法请求基于令牌的认证。
  • 服务器将回复一个令牌或一个空字符串,表示它不支持基于令牌的会话,并使用旧式会话。
  • 对于每个请求,客户端将发送令牌,并在令牌有效期结束时最终获得新的令牌。

在使用基于令牌的认证时,连接可以由同一服务器的用户共享。

$client = new PhpOrient( 'localhost', 2424 ); 
$client->setSessionToken( true );  // set true to enable the token based authentication
$clusterID = $client->dbOpen( "GratefulDeadConcerts", 'admin', 'admin' );
$sessionToken = $client->getSessionToken(); // store this token somewhere

//destroy the old client, equals to another user/socket/ip ecc.
unset($client);

// create a new client
$client = new PhpOrient( 'localhost', 2424 ); 

// set the previous obtained token to re-attach to the old session
$client->setSessionToken( $sessionToken );  

//now the dbOpen is not needed to perform database operations
$records = $client->query( 'select * from V limit 10' );

//set the flag again to true if you want to renew the token
$client->setSessionToken( true );  // set true
$clusterID = $client->dbOpen( "GratefulDeadConcerts", 'admin', 'admin' );
$new_sessionToken = $client->getSessionToken();

$this->assertNotEquals( $sessionToken, $new_sessionToken );

一个图形示例

require "vendor/autoload.php";
use PhpOrient\PhpOrient;

$client = new PhpOrient();
$client->configure( array(
    'username' => 'admin',
    'password' => 'admin',
    'hostname' => 'localhost',
    'port'     => 2424,
) );

$client->connect();

$client->dbCreate( 'animals', PhpOrient::STORAGE_TYPE_MEMORY );
$client->dbOpen( 'animals', 'admin', 'admin' );

$client->command( 'create class Animal extends V' );
$client->command( "insert into Animal set name = 'rat', specie = 'rodent'" );
$animal = $client->query( "select * from Animal" );


$client->command( 'create class Food extends V' );
$client->command( "insert into Food set name = 'pea', color = 'green'" );

$client->command( 'create class Eat extends E' );

$client->command( "create edge Eat from ( select from Animal where name = 'rat' ) to ( select from Food where name = 'pea' )" );

$pea_eaters = $client->query( "select expand( in( Eat )) from Food where name = 'pea'" );

$animal_foods = $client->query( "select expand( out( Eat )) from Animal" );

foreach ( $animal_foods as $food ) {
    $animal = $client->query(
        "select name from ( select expand( in('Eat') ) from Food where name = 'pea' )"
    )[0];
    $this->assertEquals( 'pea', $food[ 'name' ] );
    $this->assertEquals( 'green', $food[ 'color' ] );
    $this->assertEquals( 'rat', $animal[ 'name' ] );
}

许可证

Apache许可证,版本2.0,见LICENSE.md