Guest User

Untitled

a guest
Jul 24th, 2012
1,543
0
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.72 KB | None | 0 0
  1. Everyman Software Musings on software development, open source, PHP and current projects. 2011-11-05 Development
  2. Setup for Neo4j and PHP: Part 2 This is Part 2 of a series on setting up a development environment for building
  3. projects using the graph database Neo4j and PHP. In Part 1 of this series, we set up unit test and development
  4. databases. In this part, we'll build a skeleton project that includes unit tests, and a minimalistic user interface.
  5. All the files will live under a directory on our web server. In a real project, you'll probably want only the user
  6. interface files under the web server directory and your testing and library files somewhere more protected. Also, I
  7. won't be using any specific PHP framework. The principles in the code below should apply equally to any framework you
  8. decide to use. Create the Project and Testing HarnessCreate a project in a directory on your web server. For this
  9. project, mine is "/var/www/neo4play" on my local host. We'll also need our Neo4j client library. > cd
  10. /var/www/neo4play > mkdir -p tests/unit > mkdir lib > cp ~/Downloads/neo4jphp.phar lib/ > echo "<?php phpinfo(); ?>"
  11. > index.php Test the setup by browsing to http://localhost/neo4play. You should see the output of `phpinfo`. Now
  12. we'll create a bootstrap file that we can include to do project-wide and environment specific setup. Call this file
  13. "bootstrap.php" in the root project directory. <?php require_once(__DIR__.'/lib/neo4jphp.phar'); error_reporting(-1);
  14. ini_set('display_errors', 1); if (!defined('APPLICATION_ENV')) { define('APPLICATION_ENV', 'development'); } $host =
  15. 'localhost'; $port = (APPLICATION_ENV == 'development') ? 7474 : 7475; $transport = new
  16. Everyman\Neo4j\Transport($host, $port); $client = new Everyman\Neo4j\Client($transport); The main point of this file
  17. at the moment is to differentiate between our development and testing environments, and set up our connection to the
  18. correct database. We do this by attaching the database client to the correct port based on an application constant.
  19. We'll use the bootstrap file to setup a different, unit testing specific bootstrap file. Create the following file as
  20. "tests/bootstap-test.php": <?php define('APPLICATION_ENV', 'testing'); require_once(__DIR__.'/../bootstrap.php');
  21. $transport->delete('/cleandb/secret-key'); The purpose of this file to to tell our application bootstrap that we are
  22. in the "testing" environment. Then it cleans out the database so that our tests run from a known state. Make sure
  23. "secret-key" in the `delete()` call is whatever you set in the Neo4j config file from Part 1. Tell PHPUnit to use our
  24. test bootstrap with the following config file, called "tests/phpunit.xml": <phpunit colors="true"
  25. bootstrap="./bootstrap-test.php"> <testsuite name="Neo4j Play Test Results"> <directory>./unit</directory>
  26. </testsuite> </phpunit> And because we're following TDD, we'll create our first test file,
  27. "tests/unit/ActorTest.php": <?php class ActorTest extends PHPUnit_Framework_TestCase { public function
  28. testCreateActorAndRetrieveByName() { $actor = new Actor(); $actor->name = 'Test Guy '.rand(); Actor::save($actor);
  29. $actorId = $actor->id; self::assertNotNull($actorId); $retrievedActor = Actor::getActorByName($actor->name);
  30. self::assertInstanceOf('Actor', $retrievedActor); self::assertEquals($actor->id, $retrievedActor->id);
  31. self::assertEquals($actor->name, $retrievedActor->name); } public function testActorDoesNotExist() { $retrievedActor
  32. = Actor::getActorByName('Test Guy '.rand()); self::assertNull($retrievedActor); } } So we know we want a domain
  33. object called "Actor" (apparently we're building some sort of movie application) and that Actors have names and ids.
  34. We also know we want to be able to look up an Actor by their name. If we can't find the Actor by name, we should get
  35. a `null` value back. Run the tests: > cd tests > phpunit Excellent, our tests failed! If you've been playing along,
  36. they probably failed because the "Actor" class isn't defined. Our next step is to start creating our domain objects.
  37. Defining the Application DomainSo far, we only have one domain object, and a test that asserts its behavior. In order
  38. to make the test pass, we'll need to connect to the database, persist entities to it, and then query it for those
  39. entities. For persisting our entities, we'll need a way to get the client connection in our "Actor" class and any
  40. other domain object classes we define. To do this, we'll create an application registry/dependency-injection
  41. container/pattern-buzzword-of-the-month class. Put the following in the file "lib/Neo4Play.php": <?php class Neo4Play
  42. { protected static $client = null; public static function client() { return self::$client; } public static function
  43. setClient(Everyman\Neo4j\Client $client) { self::$client = $client; } } Now our domain objects will have access to
  44. the client connection through `Neo4Play::client()` when we persist them to the database. It's time to define our
  45. actor class, in the file "lib/Actor.php": <?php use Everyman\Neo4j\Node, Everyman\Neo4j\Index; class Actor { public
  46. $id = null; public $name = ''; public static function save(Actor $actor) { } public static function
  47. getActorByName($name) { } } Requiring our classes and setting up the client connection is part of the bootstrapping
  48. process of the application, so we'll need to add some thing to "bootstrap.php": <?php
  49. require_once(__DIR__.'/lib/neo4jphp.phar'); require_once(__DIR__.'/lib/Neo4Play.php');
  50. require_once(__DIR__.'/lib/Actor.php'); // ** set up error reporting, environment and connection... **//
  51. Neo4Play::setClient($client); We have a stub class for the domain object. The tests will still fail when we run them
  52. again, but at least all the classes should be found correctly. Let's start with finding an Actor by name. With our
  53. knowledge of graph databases, we know this will involve an index lookup, and that we will get a Node object in
  54. return. If the lookup returns no result, we'll get a `null`. If we do get a Node back, we'll want to hold on to it,
  55. for updating the Actor later. Modify the Actor class with the following contents: class Actor { // protected $node =
  56. null; // public static function getActorByName($name) { $actorIndex = new Index(Neo4Play::client(), Index::TypeNode,
  57. 'actors'); $node = $actorIndex->findOne('name', $name); if (!$node) { return null; } $actor = new Actor(); $actor->id
  58. = $node->getId(); $actor->name = $node->getProperty('name'); $actor->node = $node; return $actor; } } The main thing
  59. we're trying to accomplish here is keeping our domain classes as Plain-Old PHP Objects, that don't require any
  60. special class inheritance or interface, and that hide the underlying persistence layer from the outside world. The
  61. tests still fail. We'll finish up our Actor class by saving the Actor to the database. class Actor { // public static
  62. function save(Actor $actor) { if (!$actor->node) { $actor->node = new Node(Neo4Play::client()); }
  63. $actor->node->setProperty('name', $actor->name); $actor->node->save(); $actor->id = $actor->node->getId();
  64. $actorIndex = new Index(Neo4Play::client(), Index::TypeNode, 'actors'); $actorIndex->add($actor->node, 'name',
  65. $actor->name); } // } Run the tests again. If you see all green, then everything is working properly. To double
  66. check, browse to the testing instance webadmin panel http://localhost:7475/webadmin/#. You should see 2 nodes and 1
  67. property (Why 2 nodes? Because there is a node 0 -- the reference node -- that is not deleted when the database is
  68. cleaned out.) Build Something UsefulIt's time to start tacking on some user functionality to our application. Thanks
  69. to our work on the unit tests, we can create actors in the database and find them again via an exact name match.
  70. Let's expose that functionality. Change the contents of "index.php" to the following: <?php
  71. require_once('bootstrap.php'); if (!empty($_POST['actorName'])) { $actor = new Actor(); $actor->name =
  72. $_POST['actorName']; Actor::save($actor); } else if (!empty($_GET['actorName'])) { $actor =
  73. Actor::getActorByName($_GET['actorName']); } ?> <form action="" method="POST"> Add Actor Name: <input type="text"
  74. name="actorName" /> <input type="submit" value="Add" /> </form> <form action="" method="GET"> Find Actor Name: <input
  75. type="text" name="actorName" /> <input type="submit" value="Search" /> </form> <?php if (!empty($actor)) : ?> Name:
  76. <?php echo $actor->name; ?><br /> Id: <?php echo $actor->id; ?><br /> <?php elseif (!empty($_GET['actorName'])) : ?>
  77. No actor found by the name of "<?php echo $_GET['actorName']; ?>"<br /> <?php endif; ?> Browse to your index file.
  78. Mine is at http://localhost/neo4play/index.php. You should see the page you just created. Enter a name in the "Add
  79. Actor Name" box and click the "Add" button. If everything went according to plan, you should see the actor name and
  80. the id assigned to the actor by the database. Try finding that actor using the search box. Note the actor's id.
  81. Browse to http://localhost:7474/webadmin/# and click the "Data browser" tab. Enter the actor id in the text box at
  82. the top. The node you created when you added the actor should show up. The interesting thing is that our actual
  83. application doesn't know anything about how the Actors are stored. Nothing in "index.php" references graphs or nodes
  84. or indexes. This means that, in theory, we could swap out the persistence layer for a SQL databases later, or
  85. MongoDB, or anything else, and nothing in our application would have to change. If we started with a SQL database, we
  86. could easily transition to a graph database. Explore the Wonderful World of GraphsYour development environment is now
  87. set up, and your application is bootstrapped. There's a lot more to add to this application, including creating
  88. movies, and linking actors and movies together. Maybe you'll want to add a social aspect, with movie recommendations.
  89. Graph databases are powerful tools that enable such functionality to be added easily. Go ahead and explore the rest
  90. of the Neo4jPHP library (wiki and API). Also, be sure to checkout the Neo4j documentation, especially the sections
  91. about the REST API, Cypher and Gremlin (two powerful graph querying and processing languages.) All the code for this
  92. sample application is available as a gist: http://gist.github.com/1341833. Happy graphing! by Josh Adell on
  93. 11/05/2011 Email ThisBlogThis!Share to TwitterShare to Facebook Labels: everyman, graph, neo4j, php 5 comments:
  94. Daniel3dFebruary 24, 2012 11:24 AMHi i get this error when i try to add some node whit the index.php" Fatal error:
  95. Uncaught exception 'Everyman\Neo4j\Exception' with message 'Unable to search index [500]: Headers: Array ( ) Body:
  96. Array ( [error] => Couldn't resolve host 'xubuntu' [6] ) ' in
  97. phar:///var/www/neo4play/lib/neo4jphp.phar/lib/Everyman/Neo4j/Command.php:116 Stack trace: #0
  98. phar:///var/www/neo4play/lib/neo4jphp.phar/lib/Everyman/Neo4j/Command/SearchIndex.php(95):
  99. Everyman\Neo4j\Command->throwException('Unable to searc...', 500, Array, Array) #1
  100. phar:///var/www/neo4play/lib/neo4jphp.phar/lib/Everyman/Neo4j/Command.php(69):
  101. Everyman\Neo4j\Command\SearchIndex->handleResult(500, Array, Array) #2
  102. phar:///var/www/neo4play/lib/neo4jphp.phar/lib/Everyman/Neo4j/Client.php(571): Everyman\Neo4j\Command->execute() #3
  103. phar:///var/www/neo4play/lib/neo4jphp.phar/lib/Everyman/Neo4j/Client.php(513):
  104. Everyman\Neo4j\Client->runCommand(Object(Everyman\Neo4j\Command\SearchIndex)) #4
  105. phar:///var/www/neo4play/lib/neo4jphp.phar/lib/Everyman/Neo4j/Index.php(77):
  106. Everyman\Neo4j\Client->searchIndex(Object(Everyman\Neo4j\Index), 'name',
  107. inphar:///var/www/neo4play/lib/neo4jphp.phar/lib/Everyman/Neo4j/Command.php on line 116
  108. "ReplyDeleteDaniel3dFebruary 24, 2012 11:29 AMSorry this one is when i try to save. another one is when i search
  109. Please help .AND THANKS JOSH ADELL GREAT JOB." Fatal error: Uncaught exception 'Everyman\Neo4j\Exception' with
  110. message 'Unable to create node [500]: Headers: Array ( ) Body: Array ( [error] => Couldn't resolve host 'xubuntu' [6]
  111. ) ' in phar:///var/www/neo4play/lib/neo4jphp.phar/lib/Everyman/Neo4j/Command.php:116 Stack trace: #0
  112. phar:///var/www/neo4play/lib/neo4jphp.phar/lib/Everyman/Neo4j/Command/CreateNode.php(68):
  113. Everyman\Neo4j\Command->throwException('Unable to creat...', 500, Array, Array) #1
  114. phar:///var/www/neo4play/lib/neo4jphp.phar/lib/Everyman/Neo4j/Command.php(69):
  115. Everyman\Neo4j\Command\CreateNode->handleResult(500, Array, Array) #2
  116. phar:///var/www/neo4play/lib/neo4jphp.phar/lib/Everyman/Neo4j/Client.php(571): Everyman\Neo4j\Command->execute() #3
  117. phar:///var/www/neo4play/lib/neo4jphp.phar/lib/Everyman/Neo4j/Client.php(478):
  118. Everyman\Neo4j\Client->runCommand(Object(Everyman\Neo4j\Command\CreateNode)) #4
  119. phar:///var/www/neo4play/lib/neo4jphp.phar/lib/Everyman/Neo4j/Node.php(94):
  120. Everyman\Neo4j\Client->saveNode(Object(Everyman\Neo4j\Node)) #5 /var/www/neo4
  121. inphar:///var/www/neo4play/lib/neo4jphp.phar/lib/Everyman/Neo4j/Command.php on line 116"ReplyDeleteJosh AdellFebruary
  122. 24, 2012 12:10 PMIf you are using the example scripts from the Gist, you will need to change the $host variable in
  123. bootstrap.php to be 'localhost' or whatever the hostname of your Neo4j instance is.ReplyDeleteDaniel3dFebruary 29,
  124. 2012 4:49 PMThanks work...ReplyDeleteKarthikbaluJuly 21, 2012 3:21 PMWow ur awesomeReplyDeleteAdd commentLoad more...
  125. Newer Post Older Post Home Subscribe to: Post Comments (Atom) Josh Adell Durham, NC Software developer, tinkerer,
  126. armchair philosopher View my complete profile Home Projects About Me Labels php everyman neo4j javascript nodejs
  127. graph box2d unit test agile rest canvas git jaded websockets zend best practice citizen cloud codeigniter composer
  128. design pattern dropbox gearman gremlin json packaging phar phing phpfog prenup scrum silex targetprocess tropo vows
  129. zombie Blog Archive ? 2012 (8) ? July (1) No Best Practices Yet ? May (1) Neo4jPHP Available as a Composer Package
  130. ? April (2) Runtime Expectations Javascript Throwdown Data Mapper Injection in PHP Objects ? March (1) GetSet
  131. Methods vs. Public Properties ? February (1) Similarity-based Recommendation Engines ? January (2) Command Invoker
  132. Pattern with the Open/Closed Princ... Funkatron's MicroPHP Manifesto ? 2011 (24) ? December (3) PHP Fog Quickstart
  133. Decode JSON in Bash with PHP Codeworks '11 Raleigh Rundown ? November (2) Development Setup for Neo4j and PHP: Part
  134. 2 Development Setup for Neo4j and PHP: Part 1 ? October (1) A Humbling Reference ? September (1) Phar Flung Phing
  135. ? August (1) Getting Neo4jPHP working with CodeIgniter 2 ? July (4) Performance of Graph vs. Relational Databases
  136. TriPUG Meetup slides agile Adoption on a Non-Technical Team Neo4jPHP beta released ? June (2) Path finding with
  137. Neo4j Neo4j for PHP ? May (2) Logging User Sessions Across Requests Interview with Bulat Shakirzyanov ? April (5)
  138. Tropo-Turing Collision: Voice Chat Bots with Tropo... Syntactic sugar for Vows.js Dynamic Assets: Part III - Entry
  139. Forms Dynamic Assets: Part II - Construction Dynamic Assets: Part I - Definition ? March (2) Undead Wedding Bash
  140. sockets ? February (1) Jaded available on GitHub ? 2010 (19) ? December (3) The Goal Git, TargetProcess and
  141. Hashtags Private Git repository with Dropbox ? November (3) JadedPHP controllers New domains Models can be so Jaded
  142. ? October (2) Box2dnode Available via npm Global Pub-Sub ? August (2) Mocking built-in functions in PHP Josh's
  143. Modest Proposals ? July (2) A Helpful Analogy, or, Why You Should Be Testing Y... Parallel Testing in the Cloud with
  144. Feature Branche... ? June (6) Emitting Physics Events with Box2d and Node Canvas Transforms and Origin Re-Mapping
  145. Real-time Multi-player In-Browser Gaming: Air Hock... Blog Title Change box2dnode available Nodejs and Physics ? May
  146. (1) Copyright © 2010 Josh Adell. Simple template. Powered by Blogger.
Advertisement
Comments
  • mudasir5454
    2 years
    # text 0.31 KB | 0 0
    1. Thank you for some other informative website. The place else may just I get that kind of information written in such a perfect method? I have a venture that I am simply now running on, and I’ve been at the glance out for such info. <a href="https://assumeworld.com/gta-6-trailer-what-we-know-so-far/">GTA 6</a>
    2.  
Add Comment
Please, Sign In to add comment