kitlabs / neo4j-php-client
Neo4j-PHP-Client 是最先进的 Neo4j PHP 客户端
Requires
- php: ^8.0
- ext-json: *
- laudis/typed-enum: ^1.3
- php-http/discovery: ^1.13
- php-http/message: ^1.0
- psr/http-client: ^1.0
- psr/http-factory: ^1.0
- psr/http-message: ^1.0|^2.0
- psr/simple-cache: >=2.0
- stefanak-michal/bolt: ^5.1
- symfony/polyfill-php80: ^1.2
Requires (Dev)
- cache/integration-tests: dev-master
- friendsofphp/php-cs-fixer: 3.15.0
- kriswallsmith/buzz: ^1.2
- kubawerlos/php-cs-fixer-custom-fixers: 3.13.*
- monolog/monolog: ^2.2
- nyholm/psr7: ^1.3
- nyholm/psr7-server: ^1.0
- phpunit/phpunit: ^9.0
- psalm/plugin-phpunit: ^0.18
- psr/log: ^1.1
- symfony/uid: ^5.0
- symfony/var-dumper: ^5.0
- vimeo/psalm: ^5.0
Suggests
- composer-runtime-api: Install composer 2 for auto detection of version in user agent
- ext-bcmath: Needed to implement bolt protocol
- ext-sysvsem: Needed for enabling connection pooling between processes
Provides
- psr/simple-cache-implementation: 2.0|3.0
README
控制世界上功能最强大的图数据库
- 轻松配置选择您的驱动程序
- 直观的 API
- 可扩展
- 在官方 neo4j 驱动程序团队的紧密监督下设计、构建和测试
- 通过 testkit 进行验证
- 使用 psalm 完全类型化
- 提供 Bolt、HTTP 和自动路由的驱动程序
查看驱动程序的实际操作
- 电影数据库类的实现。它使用 Slim 和 neo4j-php-client 构建经典电影的 neo4j 示例 API。
- 现实世界示例的完整实现。它使用 Laravel 实现 现实世界示例 项目,所有演示应用之母。
- 朋友 API,利用 Neo4j 的力量,为世界上最具讽刺性的示例项目提供支持。
有关更详细的说明,您可以参考以下博客文章
- 如何使用 Neo4j、PHP 和 Open API 构建 JSON RESTful API
- 使用 Neo4j、AuraDB 和 PHP 构建 Web 应用程序
- 使用 PHP 连接到 Neo4j
- 企业级 PHP 和 Neo4j
或者观看这些视频中的任何一个。
通过三个简单步骤开始您的驾驶体验
步骤 1:通过 composer 安装
composer require laudis/neo4j-php-client
更多详细信息在这里
步骤 2:创建一个客户端
use Laudis\Neo4j\Authentication\Authenticate; use Laudis\Neo4j\ClientBuilder; $client = ClientBuilder::create() ->withDriver('bolt', 'bolt+s://user:password@localhost') // creates a bolt driver ->withDriver('https', 'https://test.com', Authenticate::basic('user', 'password')) // creates an http driver ->withDriver('neo4j', 'neo4j://neo4j.test.com?database=my-database', Authenticate::oidc('token')) // creates an auto routed driver with an OpenID Connect token ->withDefaultDriver('bolt') ->build();
您现在已创建了一个包含 bolt、HTTPS 和 neo4j 驱动程序 的客户端。客户端将默认使用 bolt 驱动程序。
有关 URL 的更多信息以及如何使用它们来配置驱动程序在这里。
步骤 3:运行一个事务
use Laudis\Neo4j\Contracts\TransactionInterface; $result = $client->writeTransaction(static function (TransactionInterface $tsx) { $result = $tsx->run('MERGE (x {y: "z"}:X) return x'); return $result->first()->get('x')['y']; }); echo $result; // echos 'z'
决定如何发送您的 Cypher 查询
您可以使用三种不同的方法来控制驱动程序
- 自动提交查询(最简单、最直观)
- 事务函数(最便携)
- 非管理事务(以获得最高程度的控制)
自动提交查询
自动提交查询是最直接和最直观的,但在运行复杂业务逻辑或在高可用性环境中存在许多缺点。
运行一个简单的 Cypher 查询
$client->run( 'MERGE (user {email: $email})', //The query is a required parameter ['email' => '[email protected]'], //Requests can be optionally added 'backup' //The default connection can be overridden );
运行语句对象
use Laudis\Neo4j\Databags\Statement; $statement = new Statement('MERGE (user {email: $email})', ['email' => '[email protected]']); $client->runStatement($statement, 'default');
同时运行多个查询
使用 runStatements
方法可以一次性运行所有语句。此方法是减少数据库调用次数的必要工具,尤其是在使用 HTTP 协议时。
use Laudis\Neo4j\Databags\Statement; $results = $client->runStatements([ Statement::create('MATCH (x) RETURN x LIMIT 100'), Statement::create('MERGE (x:Person {email: $email})', ['email' => '[email protected]']) ]);
事务函数
事务函数是使用驱动程序时的实际标准。它是最便携的,因为它能够抵抗在首次使用高可用性解决方案(如Neo4j aura或集群)时遇到的大部分陷阱。
驱动程序管理事务函数
- 如果发生暂时性错误,它会重新执行该函数。
- 在成功执行后,它会提交事务。
- 如果发生超时,它会回滚事务。
- 当启用Neo4j协议时,它会路由执行到相关的跟随者或领导者服务器。
注意:由于自动重试功能,函数应在后续召回时产生相同的结果,或者更技术地说:应该是幂等的。在设计和函数中的执行逻辑时,请始终记住这一点。
一些示例
use Laudis\Neo4j\Contracts\TransactionInterface; // Do a simple merge and return the result $result = $client->writeTransaction(static function (TransactionInterface $tsx) { $result = $tsx->run('MERGE (x {y: "z"}:X) return x'); return $result->first()->get('x')['y']; }); // Will result in an error $client->readTransaction(static function (TransactionInterface $tsx) { $tsx->run('MERGE (x {y: "z"}:X) return x'); }); // This is a poorly designed transaction function $client->writeTransaction(static function (TransactionInterface $tsx) use ($externalCounter) { $externalCounter->incrementNodesCreated(); $tsx->run('MERGE (x {y: $id}:X) return x', ['id' => Uuid::v4()]); }); // This achieves the same effect but is safe in case it should be retried. The function is now idempotent. $id = Uuid::v4(); $client->writeTransaction(static function (TransactionInterface $tsx) use ($id) { $tsx->run('MERGE (x {y: $id}:X) return x', ['id' => $id]); }); $externalCounter->incrementNodesCreated();
未管理的事务
如果您需要访问驱动程序的低级别功能,那么您需要未管理的事务。它们允许完全控制提交和回滚。
开启事务
beginTransaction
方法将使用相关驱动程序启动一个事务。
use Laudis\Neo4j\Databags\Statement; $tsx = $client->beginTransaction( // This is an optional set of statements to execute while opening the transaction [Statement::create('MERGE (x:Person({email: $email})', ['email' => '[email protected]'])], 'backup' // This is the optional connection alias );
请注意,
beginTransaction
只返回事务对象,而不返回提供的语句的结果。
在事务中运行语句
只要事务仍然打开,事务就可以像客户端对象一样运行语句。
$result = $tsx->run('MATCH (x) RETURN x LIMIT 100'); $result = $tsx->runStatement(Statement::create('MATCH (x) RETURN x LIMIT 100')); $results = $tsx->runStatements([Statement::create('MATCH (x) RETURN x LIMIT 100')]);
完成事务
回滚事务
$tsx->rollback();
提交事务
$tsx->commit([Statement::create('MATCH (x) RETURN x LIMIT 100')]);
访问结果
结果以行和列的标准格式返回
// Results are a CypherList $results = $client->run('MATCH (node:Node) RETURN node, node.id AS id'); // A row is a CypherMap foreach ($results as $result) { // Returns a Node $node = $result->get('node'); echo $node->getProperty('id'); echo $result->get('id'); }
Cypher值和类型映射到这些PHP类型和类
(*) 这些项也可以用作bolt协议的参数,并且将由驱动程序自动转换,以便可以在Cypher中使用。
除了这些示例外,\DateTimeInterface
将映射到Cypher中的DateTimeZoneId
。空或列表类型的array
将转换为Cypher的List
,而关联数组将转换为map
。
(**) 一个点可以是实现PointInterface的四种类型之一:\Laudis\Neo4j\Types\CartesianPoint
、\Laudis\Neo4j\Types\Cartesian3DPoint
、\Laudis\Neo4j\Types\WGS84Point
、\Laudis\Neo4j\Types\WGS843DPoint
。
深入了解
区分参数类型
Cypher有列表和映射。这种概念可能存在问题,因为标准的PHP数组封装了这两者。当你提供一个空数组作为参数时,将无法确定它是空列表还是空映射。
ParameterHelper
类是这一点的理想伴侣
use Laudis\Neo4j\ParameterHelper; $client->run('MATCH (x) WHERE x.slug in $listOrMap RETURN x', ['listOrMap' => ParameterHelper::asList([])]); // will return an empty CypherList $client->run('MATCH (x) WHERE x.slug in $listOrMap RETURN x', ['listOrMap' => ParameterHelper::asMap([])]); // will error $client->run('MATCH (x) WHERE x.slug in $listOrMap RETURN x', ['listOrMap' => []]); // will return an empty CypherList
版本兼容性矩阵
Neo4j功能支持
深入要求
- PHP >= 7.4
- Neo4j数据库(最低版本3.5)
- ext-bcmath *
- ext-json **
- ext-sockets ***
(*) 需要实现bolt协议
(**) 需要实现http协议
(***) 可以安装以获得最优bolt协议性能
如果您计划使用HTTP驱动程序,请确保项目中包含了psr-7、psr-17和psr-18的实现。如果您没有,您可以通过composer安装它们。
composer require nyholm/psr7 nyholm/psr7-server kriswallsmith/buzz
结果格式/湿化
为了使bolt协议和http的结果统一,驱动程序提供了结果格式化程序(又称湿化器)。客户端可以使用这些格式化程序进行配置。您甚至可以自己实现。
默认格式化程序是\Laudis\Neo4j\Formatters\OGMFormatter
,在结果格式部分中有详细说明。
驱动程序默认提供了三个格式化程序,它们都位于Formatter命名空间中
\Laudis\Neo4j\Formatter\BasicFormatter
将删除所有Cypher类型,并将结果映射中的每个值简单地返回为标量、null或数组值。\Laudis\Neo4j\Formatter\OGMFormatter
将Cypher类型映射到PHP类型,具体说明见这里。\Laudis\Neo4j\Formatter\SummarizedResultFormatter
任何格式化器装饰并添加详细的结果摘要。
客户端构建器提供了一种轻松更改格式化器的方法。
$client = \Laudis\Neo4j\ClientBuilder::create() ->withFormatter(\Laudis\Neo4j\Formatter\SummarizedResultFormatter::create()) ->build(); /** * The client will now return a result, decorated with a summary. * * @var \Laudis\Neo4j\Databags\SummarizedResult $results */ $summarisedResult = $client->run('MATCH (x) RETURN x'); // The summary contains extensive information such as counters for changed values in the database, // information on the database, potential notifications, timing, a (profiled) plan, the type of query // and information on the server itself. $summary = $summarisedResult->getSummary(); // The result is exactly the same as the default. $result = $summarisedResult->getResult();
为了使用自定义格式化器,实现Laudis\Neo4j\Contracts\FormatterInterface
并提供它,当使用客户端构建器时。
概念
如此处所述的驱动程序API是驱动程序的主要目标。因此,客户端只是一个驱动程序管理器。驱动程序创建会话。会话通过事务运行查询。
因此,您可以像这样从客户端访问每个概念
use Laudis\Neo4j\ClientBuilder; // A builder is responsible for configuring the client on a high level. $builder = ClientBuilder::create(); // A client manages the drivers as configured by the builder. $client = $builder->build(); // A driver manages connections and sessions. $driver = $client->getDriver('default'); // A session manages transactions. $session = $driver->createSession(); // A transaction is the atomic unit of the driver where are the cypher queries are chained. $transaction = $session->beginTransaction(); // A transaction runs the actual queries $transaction->run('MATCH (x) RETURN count(x)');
如果您需要完全控制,您可以使用自定义配置对象控制每个对象。
客户端
客户端管理驱动程序,并根据预先配置的别名将查询路由到正确的驱动程序。
驱动程序
驱动程序对象是线程安全的骨干,提供对Neo4j的访问。它拥有连接池,并且可以生成用于执行工作的会话。
use Laudis\Neo4j\Basic\Driver; use Laudis\Neo4j\Databags\DriverConfiguration; $driver = Driver::create( uri: 'neo4j://user:mypassword@Localhost:7687', configuration: DriverConfiguration::create()->withUserAgent('MyApp/1.0.0') );
会话
会话是轻量级的容器,用于因果链中的连续序列的事务。它们根据需要从连接池借用连接,并使用书签链接事务。
use Laudis\Neo4j\Databags\SessionConfiguration; use Laudis\Neo4j\Enum\AccessMode; $session = $driver->createSession(SessionConfiguration::create() ->withDatabase('my-database') ->withAccessMode(AccessMode::READ()) );
事务
事务是包含一个或多个查询的工作的原子单元。每个事务绑定到一个单个的连接,并由一个书签在因果链中表示。
语句
查询是事务内的可执行单元,由Cypher字符串和键控参数集组成。每个查询输出一个可能包含零个或多个记录的结果。
结果
结果包含来自查询的输出,由标题元数据、内容记录和摘要元数据组成。在Neo4j 4.0及以上版本中,应用程序可以控制结果数据的流动。
深入配置
URL方案
URL方案是配置驱动程序的简单方法。
配置格式
'<scheme>://<user>:<password>@<host>:<port>?database=<database>'
默认配置
bolt://localhost:7687?database=neo4j
方案配置矩阵
此库支持三种驱动程序:bolt、HTTP和neo4j。URL方案部分决定了驱动程序。
配置对象
可以使用配置对象配置驱动程序、会话和事务。配置选项的概述可在此处找到
代码示例
use \Laudis\Neo4j\Databags\DriverConfiguration; use Laudis\Neo4j\Databags\SessionConfiguration; use Laudis\Neo4j\Databags\TransactionConfiguration; $client = \Laudis\Neo4j\ClientBuilder::create() ->withDefaultDriverConfiguration(DriverConfiguration::default()->withUserAgent('MyApp/1.0.0')) ->withDefaultSessionConfiguration(SessionConfiguration::default()->withDatabase('app-database')) ->withDefaultTransactionConfiguration(TransactionConfiguration::default()->withTimeout(5.0)) ->build(); // The client will run the query on a driver with the provided config, // which spawns a session with the provided session config // and runs the query in a transaction with the provided transaction config $client->run('MATCH (x) RETURN count(x) AS count'); // More granular control can be achieved by requesting the concepts yourself: $tsx = $client->getDriver('default') ->createSession(SessionConfiguration::default()->withDatabase('management-database')) ->beginTransaction(null, TransactionConfiguration::default()->withTimeout(200)); $tsx->run('SOME REALLY LONG MANAGEMENT QUERY'); $tsx->commit();