Pour des articles plus détaillés, vous pouvez vous référer à ces blogs:
Ou regardez l'une de ces vidéos.
composer require laudis/neo4j-php-clientTrouvez plus de détails ici
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 ();Vous avez maintenant créé un client avec des pilotes Bolt, HTTPS et NEO4J . Le pilote par défaut que le client utilisera est le boulon .
En savoir plus sur les URL et comment les utiliser pour configurer les pilotes ici.
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' Vous pouvez contrôler le conducteur à l'aide de trois approches différentes:
Les requêtes engagées automatiquement sont les plus simples et les plus intuitives, mais ont de nombreux inconvénients lors de l'exécution de la logique métier complexe ou dans un environnement à haute disponibilité.
$ 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 ' ); La méthode runStatements exécutera toutes les instructions à la fois. Cette méthode est un outil essentiel pour réduire le nombre d'appels de base de données, en particulier lors de l'utilisation du protocole 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] ' ])
]);Les fonctions de transaction sont la norme de facto lors de l'utilisation du pilote. Il est le plus portable car il résiste à de nombreux pièges lors du développement avec des solutions de haute disponibilité telles que l'aura Neo4j ou un cluster.
Le pilote gère les fonctions de transaction:
ATTENTION: En raison de la fonctionnalité de réessayer automatique, la fonction doit produire le même résultat sur les rappels ultérieurs, ou en termes plus techniques: devrait être idempotent . N'oubliez pas cela lors de la conception de la logique d'exécution dans la fonction.
Quelques exemples:
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 ();Si vous avez besoin d'un accès de niveau inférieur aux capacités des pilotes, vous voulez des transactions non gérées. Ils permettent des commits et des reculs complètement contrôlables.
La méthode beginTransaction lancera une transaction avec le pilote concerné.
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
);Notez que
beginTransactionrenvoie uniquement l'objet de transaction, pas les résultats des instructions fournies.
La transaction peut exécuter des instructions comme l'objet client tant qu'elle est toujours ouverte.
$ 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 ' )]);Rollback une transaction:
$ tsx -> rollback ();Engager une transaction:
$ tsx -> commit ([Statement:: create ( ' MATCH (x) RETURN x LIMIT 100 ' )]);Les résultats sont renvoyés dans un format standard de lignes et de colonnes:
// 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 ' );
}Les valeurs et types de cypher mappent ces types et classes PHP:
| Zéro | Php |
|---|---|
| nul | * null |
| chaîne | * string |
| entier | * int |
| flotter | * float |
| booléen | * bool |
| Carte | * LaudisNeo4jTypesCypherMap |
| Liste | * LaudisNeo4jTypesCypherList |
| Indiquer | * LaudisNeo4jContractsPointInterface ** |
| Date | * LaudisNeo4jTypesDate |
| Temps | * LaudisNeo4jTypesTime |
| Temps local | * LaudisNeo4jTypesLocalTime |
| DateTime | * LaudisNeo4jTypesDateTime |
| Datetimezoneid | * LaudisNeo4jTypesDateTimeZoneId |
| Localdatetime | * LaudisNeo4jTypesLocalDateTime |
| Durée | * LaudisNeo4jTypesDuration |
| Nœud | LaudisNeo4jTypesNode |
| Relation | LaudisNeo4jTypesRelationship |
| Chemin | LaudisNeo4jTypesPath |
(*) Ces éléments peuvent également être utilisés comme paramètres dans le protocole de boulon et seront automatiquement convertis par le conducteur, afin qu'ils puissent être utilisés dans Cypher.
Outre ces exemples, DateTimeInterface mappera à DateTimeZoneId dans Cypher. Un array de type vide ou de liste sera converti en List Cypher, et un associative array sera converti en map .
(**) Un point peut être l'un des quatre types implémentant PointInterface: LaudisNeo4jTypesCartesianPoint LaudisNeo4jTypesCartesian3DPoint LaudisNeo4jTypesWGS84Point LaudisNeo4jTypesWGS843DPoint
Cypher a des listes et des cartes. Cette notion peut être problématique car les réseaux PHP standard encapsulent les deux. Lorsque vous fournissez un tableau vide en tant que paramètre, il sera impossible de déterminer une liste ou une carte vide.
La classe ParameterHelper est le compagnon idéal pour ceci:
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| Version du conducteur | Version PHP | Version néo4j |
|---|---|---|
| ^ 2.8 | 7.4, ^ 8.0 | ^ 3.5, ^ 4.0 |
| ^ 3.0 | ^ 8.0 | ^ 4.0, ^ 5.0 |
| Fonctionnalité | Soutenu? |
|---|---|
| Authentification | Oui |
| Transactions | Oui |
| Protocole HTTP | Oui |
| Protocole de verrouillage | Oui |
| Grappe | Oui |
| Aura | Oui |
| Protocole de secousse | Oui |
| Signets | Oui |
(*) Nécessaire pour implémenter le protocole de boulon
(**) nécessaire pour implémenter le protocole HTTP
(***) peut être installé pour des performances de protocole de boulon optimal
Si vous prévoyez d'utiliser les pilotes HTTP, assurez-vous que les implémentations PSR-7, PSR-17 et PSR-18 incluent dans le projet. Si vous n'en avez pas, vous pouvez les installer via Composer:
composer require nyholm/psr7 nyholm/psr7-server kriswallsmith/buzzAfin de faire les résultats du protocole de boulon et de l'uniforme HTTP, le conducteur fournit des formateurs de résultats (aka hydrators). Le client est configurable avec ces formateurs. Vous pouvez même implémenter le vôtre.
Le formateur par défaut est le LaudisNeo4jFormattersOGMFormatter , qui est expliqué largement dans la section du format de résultat.
Le pilote fournit trois formateurs par défaut, qui se trouvent tous dans l'espace de noms de format:
LaudisNeo4jFormatterBasicFormatter qui efface tous les types de chiffre d'affaires et renvoie simplement chaque valeur dans la carte résultante en tant que valeur scalaire, nulle ou de tableau.LaudisNeo4jFormatterOGMFormatter qui mappe les types de cypher aux types de php comme expliqué ici.LaudisNeo4jFormatterSummarizedResultFormatter qui décore n'importe quel formateur et ajoute un résumé de résultat étendu.Le Client Builder fournit un moyen facile de modifier le formateur:
$ client = Laudis Neo4j ClientBuilder:: create ()
-> withFormatter ( Laudis Neo4j Formatter SummarizedResultFormatter:: create ())
-> build ();
/**
* The client will now return a result, decorated with a summary.
*
* @var LaudisNeo4jDatabagsSummarizedResult $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 (); Afin d'utiliser un formateur personnalisé, implémentez le LaudisNeo4jContractsFormatterInterface et fournissez-le lors de l'utilisation du constructeur de clients.
L'API du conducteur décrit ici est la cible principale du conducteur. Pour cette raison, le client n'est rien de plus qu'un gestionnaire de pilotes. Le conducteur crée des sessions. Une session exécute des requêtes via une transaction.
En raison de ce comportement, vous pouvez accéder à chaque concept à partir du client comme ceci:
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) ' );Si vous avez besoin d'un contrôle complet, vous pouvez contrôler chaque objet avec des objets de configuration personnalisés.
Un client gère les pilotes et achemine les requêtes vers les pilotes appropriés en fonction des alias préconfigurés.
L'objet pilote est l'épine dorsale en filetage qui donne accès à Neo4j. Il possède un pool de connexions et peut engendrer des séances pour effectuer des travaux.
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 ' )
);Les séances sont des conteneurs légers pour les séquences de transactions à chaîne causalement. Ils empruntent des connexions au pool de connexions selon les besoins et les transactions en chaîne à l'aide de signets .
use Laudis Neo4j Databags SessionConfiguration ;
use Laudis Neo4j Enum AccessMode ;
$ session = $ driver -> createSession (SessionConfiguration:: create ()
-> withDatabase ( ' my-database ' )
-> withAccessMode (AccessMode:: READ ())
);Les transactions sont des unités de travail atomiques qui peuvent contenir une ou plusieurs requêtes . Chaque transaction est liée à une seule connexion et est représentée dans la chaîne causale par un signet .
Les requêtes sont des unités exécutables dans les transactions et consistent en une chaîne Cypher et un ensemble de paramètres à clé. Chaque requête sortira un résultat qui peut contenir des enregistrements zéro ou plus.
Un résultat contient la sortie d'une requête , composée de métadonnées d'en-tête, d'enregistrements de contenu et de métadonnées sommaires. Dans NEO4J 4.0 et supérieur, les applications ont un contrôle sur le flux des données de résultat.
Le schéma d'URL est le moyen le plus simple de configurer le pilote.
Format de configuration:
'<scheme>://<user>:<password>@<host>:<port>?database=<database>'
Configuration par défaut:
bolt://localhost:7687?database=neo4j
Cette bibliothèque prend en charge trois pilotes: Bolt, HTTP et NEO4J. La partie du schéma de l'URL détermine le conducteur.
| conducteur | schème | certificat valide | certificat auto-signé | fonction |
|---|---|---|---|---|
| néo4j | néo4j | NEO4J + S | NEO4J + SSC | Routage côté client sur le boulon |
| boulon | boulon | boulon + s | boulon + ssc | Serveur unique sur le boulon |
| http | http | https | configuré via l'implémentation du client PSR | Serveur unique sur http |
Un pilote, une session et une transaction peuvent être configurés à l'aide d'objets de configuration. Un aperçu des options de configuration peut être trouvé ici:
| nom | concept | description | classe |
|---|---|---|---|
| agent utilisateur | conducteur | L'agent utilisateur a utilisé pour identifier le client sur le serveur NEO4J. | DriverConfiguration |
| Liaisons HTTP PSR | conducteur | L'implémentation PSR pertinente utilisée par le pilote lors de l'utilisation du protocole HTTP. | DriverConfiguration |
| base de données | session | La base de données à laquelle se connecter. | SessionConfiguration |
| Taille de récupération | session | La quantité de lignes à récupérer à la fois. | SessionConfiguration |
| Mode d'accès | session | Le mode par défaut lors de l'accès au serveur. | SessionConfiguration |
| signets | session | Les signets utilisés dans la session. (expérimental) | SessionConfiguration |
| métadonnées | transaction | Les métadonnées utilisées pendant la transaction. (expérimental) | TransactionConfiguration |
| temps mort | transaction | La durée maximale avant de synchroniser. | TransactionConfiguration |
Exemple de code:
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 ();