Graphite PHP Linked Data Library

Introducing Graphite

©2010-2012 by Christopher Gutteridge, University of Southampton. Latest version is 1.5 (2012-03-11)

Graphite is Free, Open Source software and has been developed to make working with RDF easier and more fun.

Graphite is a PHP Library, built on top of ARC2, to make it easy to do stuff with RDF data really quickly, without having to naff around with databases. It is not intended to be scalable, or a way of authoring RDF data. There's plenty of stuff out there already to do that. The new "Resource Description" feature makes it an excellent way to provide a website on top of data in a SPARQL endpoint.

New to Linked Data & RDF?

I've written an Introduction to RDF and Linked Data. It doesn't cover everything, but should be enough to get you started.

Handy Linked Data Tools

Sites using Graphite

Mail me to add your site here!


Also hosted on this site is sparqllib.php, a simple PHP library for querying SPARQL.

Hello World

Here's the minimal example to get started with. Please note, by the way, that the "Output" section of all these examples is being generated on-the-fly from the PHP.

$graph = new Graphite();
$graph->load( "" );
print $graph->resource( "" )->get( "foaf:name" );
University of Southampton


Really quick install

Type this while in the directory you want to write php scripts in:

curl -s | tar xzvf -

The version of ARC which comes with the above already has my patch applied and is distributed with permission of the author. (Although it's GPL so asking was just me being polite)

Longer install

You'll need to Install ARC2 then download the single Graphite.php library and put it in the same directory as /arc/

Patch to ARC2 (optional)

The ARC2 loader does not follow relative redirects, which many servers use in their 303 headers. It also confuses some sites by including the port in the HTTP "Host:" header. I've made a slightly patched version of the ARC2_Reader.php library which works around this. I suggest you use it if you want to use the "sameAs" Graphite method to it's full potential. My added/altered lines are marked with #cjg

Update policy

This library is updated (for now) when I have time or inspiration. If you're using it, let me know (email at bottom of page).


This library is developed on github. The latest development version is at

ARC2 Dependency

Currently Graphite uses the ARC2 library to decode and encode RDF documents. Some concerns have been expressed to me that ARC2 is no longer actively maintained. This is not a big concern as it would only be a couple of hours work to make Graphite work with an alternate RDF library. eg. RAP.


By default, Graphite defines a bunch of common namespaces: foaf, dc, dct, rdf, rdfs, owl, xsd, cc, bibo, skos, geo, sioc. But you can add your own to make your code more readable.

$graph = new Graphite();
$graph->ns( "uosbuilding", "" );
$graph->load( "uosbuilding:32" );
print $graph->resource( "uosbuilding:32" )->label();
EEE Building

You may notice that this would get confused if you made namespaces like "urn" or "http". You're right, don't do it. I considered making a distinction between full URIs and those shortened with an alias, and decided that the point of the library was speed of hacking not semantic perfection.

Tip: To look up the common prefix for a namespace, use

Inspecting a resource

To see all the incoming and outgoing relations from a URI, use the debug method. The left arrows indicate incoming relations. You can also dump the Graphite object to see everything.

$graph = new Graphite();
$uri = "";
$graph->load( $uri );
print $graph->resource( $uri )->dump();
geo:long "-1.395675"^^xsd:decimal
geo:lat "50.934180"^^xsd:decimal
skos:notation "SO17 1BJ"^^
rdfs:label "SO17 1BJ"

Working with Lists

The all() method returns an array of matching values. Using a "-" uses the inverse of the relationship so "-foo:Child" would match the things which this was a child of rather than the things that were a child of it.

$graph = new Graphite();
$graph->ns( "org", "" );
$uri = "";
$graph->load( $uri );
print $graph->resource( $uri )->all( "org:hasSubOrganization" )->sort( "rdfs:label" )->getString( "rdfs:label" )->join( ", " ).".\n";
Aeronautics, Astronautics & Comp. Eng, Civil Maritime & Env. Eng & Sci Unit, Education Hub, Engineering Science Unit, Enterprise, FOS - Engineering & the Environment, Faculty Hub, Foundation Year, Inst. Sound & Vibration Research, Maritime Institute.

Linked data

To follow a link to another datasource is really easy, thanks to the ARC2 library papering over many of the cracks! However, see my note in Installation for a tiny patch to ARC2 to make it follow non-absolute redirects.

$person_uri = "";
$graph = new Graphite();
# this must be a directory the webserver can write to.
$graph->cacheDir( "/home/graphite/" );
$graph->load( $person_uri );
$person = $graph->resource( $person_uri );
print "<h3>".$person->link()."</h3>";
# Show sameAs properties
foreach( $person->all( "owl:sameAs" ) as $sameas ) { print "<div>sameAs: ".$sameas->link()."</div>"; }
# follow the sameAs links and load them into our graph
function showPersonInfo($title,$person)
	print "<h4>$title</h4>";
	print "<div><b>name:</b> ".$person->all( "foaf:name" )->join( ", ")."</div>";
	print "<div><b>phone:</b> ".$person->all( "foaf:phone" )->prettyLink()->join( ", ")."</div>";
	print "<div><b>homepage:</b> ".$person->all( "foaf:homepage" )->link()->join( ", ")."</div>";



name: Christopher Gutteridge, Christopher J. Gutteridge


name: Christopher Gutteridge, Christopher J. Gutteridge
phone: +442380594833

This rather funky example has gone and got information from twitter (via from wikipedia (via and from the FOAF provided by Wendy's school. It uses the cacheDir() method so it does not have to make a bunch of HTTP requests every single time the page is loaded.


Graphite Class

This object represents a set of zero or more bits of RDF data and gives you some functions to start poking them.

$graph = new Graphite();
$graph = new Graphite( $namespace_map );
Create a new instance of Graphite. See the Namespaces example above for how to specify a namespace map and a list of pre-declared namespaces.
$resource = $graph->resource( $uri );
Get the resource with given URI. $uri may be abbreviated to "namespace:value".
$graph->ns( $alias, $namespace );
Add an additional namespace alias to the Graphite instance.
$count = $graph->load( $uri_to_load );
Load the RDF from the given URI or URL. Return the number of triples loaded.
$count = $graph->addTurtle( $base, $data );
Take a base URI and a string of turtle RDF and load the new triples into the graph. Return the number of triples loaded.
$count = $graph->addRDFXML( $base, $data );
As for addTurtle but load a string of RDF XML.
$count = $graph->addTriples( $triples );
Add triples to the graph from an ARC2 datastrcture. This is the inverse of toArcTriples.
$graph->addTriple( $subject,$predicate,$object, [$datatype], [$language] );
$graph->addCompressedTriple( $subject,$predicate,$object, [$datatype], [$language] );
$graph->t( $subject,$predicate,$object, [$datatype], [$language] );
Add a single triple directly to the graph. Only addCompressedTriple accepts shortended URIs, eg foaf:name. t() is an alias for addCompressedTriple as we've found it more readable in big blocks of code.
$count = $graph->loadSPARQL( $endpoint, $query );
Calls the SPARQL query on the endpoint and loads the results into the graph. $query should be a SPARQL "CONSTRUCT" query which returns RDF, rather than a table of resutls. The return value is the number of triples added.
$graph->cacheDir( $dir, [$age] );
$dir should be a directory the webserver has permission to read and write to. Any RDF/XML documents which graphite downloads will be saved here. If a cache exists and is newer than $age seconds then load() will use the document in the cache directory in preference to doing an HTTP request. $age defaults to 24*60*60 - 24 hours. This including this function can seriously improve graphite performance! If you want to always load certain documents, load them before setting the cache.
print $graph->dump( [$options] );
print $graph->dumpText( [$options] );
Returns the entire RDF in memory in nicely formatted HTML so you can see what's going on. Options is an optional array, same parameters as $options on a dump() of an individual resource. dumpText() does the same thing but with ASCII indents rather than HTML markup.
print_r( $graph->toArcTriples() );
Returns the entire RDF in memory in Arc2's internal triples format.
print $graph->serialize( [$serializer="RDFXML"] );
Returns the serialization of the entire RDF graph in memory using one of Arc2's serializers. By default the RDF/XML serializer is used, but others (try passing "Turtle" or "NTriples") can be used - see the Arc2 documentation.
$resource = $graph->primaryTopic();
Utility method (shamelessly ripped off from EasyRDF). Returns the primary topic of the first URL that was loaded. Handy when working with FOAF.
$resources = $graph->allOfType( $type_uri );
Return a list of all resources loaded, with the rdf:type given. eg. $graph->allOfType( "foaf:Person" )
$resources = $graph->allSubjects();
Return a list of all resources in the graph which are the subject of at least one triple.
$resources = $graph->allObjects();
Return a list of all resources in the graph which are the object of at least one triple.
$label_relations_list = $graph->labelRelations();
$graph->labelRelations( $new_list );
Return a list of the relations currently used for $resource->label(), if called with a parameter then this should be an array to replace the current list. To just add additonal relation types to use as labels, use addLabelRelation($relation).
$icon_url = $graph>mailtoURL();
$graph>mailtoURL( $new_icon_url );
$icon_url = $graph>telURL();
$graph>telURL( $new_icon_url );
Get or set the URL of the icon used for mailto: and tel: links in prettyLink(). If set to an empty string then no icon will be shown.
$graph->freeze( $filename );
$graph = Graphite::thaw( $filename );
Graphite uses ARC2 to parse RDF, which isn't as fast as using a compiled library. I may add support for RAP or something similar. When Graphite loads a triple it indexes it by both subject & object, which also takes a little time. To address this issue, freeze and thaw go some way to help speed things up. freeze takes a graph object, including all the namespaces set with ns() and saves it to disk as a serialised PHP object, which is much faster to load then a large RDF file. It's ideal in a situation where you want to build a site from a single RDF document which is updated occasionally. This example is a command line script you can modify to load and freeze a graph.

Resource Class

This represents a single RDF thing, with a URI, or a literal value. If you treat it as a string it will return the URI or the literal, but there's some useful functions you can call on it, too.

$new_resource = $resource->get( $property );
$new_resource = $resource->get( *resource list* );
Get a single resource, related to the current resource by the given property. The property may be a URI or "namespace:value". It may be a literal or a normal resource. If there's no value, it returns a null resource object (not a null value), so your code will muddle through. If you specify multiple properties, then this returns the first resource it finds. To get a value from the inverse of a relationship, prefix the property string with "-". For example, to get the mayor of a city you may need to do $city->get( "-somens:isMayorOf" );
$string = $resource->toString();
Returns the value of a literal, or the URI of a resource as a PHP string.
$datatype = $resource->datatype();
Returns the datatype of a literal, if it has one, otherwise null.
$language = $resource->language();
Returns the language of a literal, if it has one, otherwise null.
$string = $resource->getString( $property );
$string = $resource->getString( *resource list* );
As for get() but return the result's string value. Shortened version of $resource->get( $property )->toString();
$boolean = $resource->has( $property );
$boolean = $resource->has( *resource list* );
Returns true if there this resource has at least one relationship with the given properties (or with any of the given properties)
$resource_list = $resource->all( $property );
$resource_list = $resource->all( *resource list* );
As for get(), but returns a resource list of zero or more matching resources. Resource lists may be treated as arrays, but see below for additional properties.
$resource_list = $resource->allString( $property );
$resource_list = $resource->allString( *resource list* );
As for all(), but returns a resource list the string values of each result.
$relation_list = $resource->relations();
Returns a resource list of the properties relating to this resource, including inverse ones.
$count = $resource->load();
Try and resolve this resource via the web and load the RDF found there into the current Graphite object. Returns the number of triples loaded (zero probably indicates failure).
$count = $resource->loadSameAs( [$prefix] );
Iterate over any owl:sameAs properties this resource has and load them from the web. Any loaded triples with the URI of the resource being loaded will be created with both that URI and the URI of the current resource, causing the linked data to be immediately available via the current resource. A single Graphite instance won't load the same URI more than once, so you can call this function twice to follow first, then second generation sameAs relations, if you want. The 2nd call will return the number of triples it loaded the first time, so don't try looping until it returns zero, rather loop until the number of triples returned does not increase. If $prefix is set then only follow sameAs links to URIs with that prefix.
$resource = $resource->type()
$resources_list = $resource->types()
Handy methods for getting the rdf:type or types of the resource. Use for code readability.
$boolean = $resource->isType( $type );
$boolean = $resource->isType( *resource list* );
Return true if the resource is of the given type, or any of the given list of types.
$boolean = $resource->isNull();
Return true if the resource is a null node, e.g. as the result of $resource->get("something:nonexistent").
$resource = $resource->add( $relation,$object, [$datatype], [$language] );
$resource = $resource->add( $inverse_relation, $subject );
Creates a new triple linked to this resource, and returns a handle on the same resource to allow chaining. This allows for some elegant code to add several triples in very readable way:
$graph->resource( "" )
	->add( "foaf:name", "Marvin Fenderson", "literal" )
	->add( "foaf:phone", "tel:+44123456789" )
	->add( "-foaf:member" "" );
This syntax aims to keep the cut-and-pasted code to a minimum.
$label = $resource->label()
Get a valid label for this resource, tries all of skos:prefLabel, rdfs:label, foaf:name, dct:title, dc:title, sioc:name. Returns "[NULL]" if no label is available. To alter or add to the list of relationships considered to be labels, see $graph->labelRelations($list) and $graph->addLabelRelation($list)
$boolean = $resource->hasLabel()
Returns true if label() would return a valid lable, use it to avoid ugly [NULL]'s appearing.
$htmllink = $resource->link()
Returns <a href='THIS'>THIS</a> - saves time when wanting to link homepages, etc.
$htmllink = $resource->prettyLink()
Similar to link() but is a bit more clever. If the resource has a valid label (according to hasLabel(), above) then it uses that as the link text. If it's a tel: or mailto: URI then it shows the phone number or email address without the prefix, and shows a little email/phone icon. You can alter these icons or prevent them appearing using $graph->telIcon($url) and $graph->mailtoIcon($url)
$dump = $resource->dump( [$options] );
$dump = $resource->dumpText( [$options] );
Create a pretty HTML dump of the current resource. Handy for debugging halfway through hacking something. $options is an optional array of flags to modify how dump() renders HTML. dumpText() does the same think with ASCII indention instead of HTML markup, and is intended for debugging command-line scripts.
"label"=>1 - add a label for the URI, and the rdf:type, to the top of each resource box, if the information is in the current graph.
"labeluris"=>1 - when listing the resources to which this URI relates, show them as a label, if possible, rather than a URI. Hovering the mouse will still show the URI.
"internallinks"=>1 - instead of linking directly to the URI, link to that resource's dump on the current page (which may or may not be present). This can, for example, make bnode nests easier to figure out.
print_r( $resource->toArcTriples() );
Returns all triples of which this resource is the subject in Arc2's internal triples format.
print $graph->serialize( [$serializer="RDFXML"] );
Returns the serialization of the resource including any bnodes it points to (and any those point to). See the serialize method of the Graphite class above.

Experimental Resource Class methods

These do some funky stuff relating to our research at Southampton. They may be modified or removed in later versions of Graphite.

$count = $resource->loadSameAsOrg( $prefix );
Look up this URI in and follow any sameAs URIs from there which match the prefix. $prefix is enforced as may return hundreds of URIs.
$count = $resource->loadDataGovUKBackLinks()
Takes the current resource and attempts to find backlinks via The EnAKTing project. This works rather nicely with dbpedia URIs of British regions, cities etc.

ResourceList Class

This represents a list of RDF things, URIs or literal values. You can just treat it like an array, or you can call methods on it.

$new_resourcelist = $resourcelist->get( $property );
$new_resourcelist = $resourcelist->get( *resource list* );
Call $resource->get(...) on every item in this list and return a resourcelist of the results.
$string = $resource->getString( $property );
$string = $resource->getString( *resource list* );
Call $resource->getString(...) on every item in this list and return a resourcelist of the results.
$new_resourcelist = $resourcelist->all( $property );
$new_resourcelist = $resourcelist->all( *resource list* );
Call $resource->all(...) on every item in this list and return a resourcelist of all the results. Duplicate resources are eliminated.
$resource_list = $resource->allString( $property );
$resource_list = $resource->allString( *resource list* );
Call $resource->allString(...) on every item in this list and return a resourcelist of all the results. As with all(), duplicate resources and eliminated.
$resource_list = $resource->allOfType( $type_uri );
Create a new resource list containing all resources in the current list of the given type.
$new_resourcelist = $resourcelist->label();
Call $resource->label() on every item in this list and return a resourcelist of the results.
$n = $resourcelist->load();
Call $resource->load() on every item in this list and return the total triples from these resources. Careful, this could cause a large number of requests at one go!
$str = $resourcelist->join( $joinstr );
Returns a string of all the items in the resource list, joined with the given string.
$new_resourcelist = $resourcelist->sort( $property );
$new_resourcelist = $resourcelist->sort( *resource list* );
Return a copy of this resource list sorted by the given property or properties. If a resource has multiple values for a property then one will be used, as with $resource->get().
$new_resourcelist = $resourcelist->distinct();
Return a list with any duplicates removed, otherwise preserving current order.
$new_resourcelist = $resourcelist->append( $resource );
$new_resourcelist = $resourcelist->append( *resource list* );
Create a new resource list with the given resource or list of resources appended on the end of the current resource list.
$new_resourcelist = $resourcelist->union( $resource );
$new_resourcelist = $resourcelist->union( *resource list* );
Create a new resource list with the given resource or list of resources merged with the current list. Functionally the same as calling $resourcelist->append( ... )->distinct()
$new_resourcelist = $resourcelist->intersection( $resource );
$new_resourcelist = $resourcelist->intersection( *resource list* );
Create a new resource list with containing only the resources which are in both lists. Only returns one instance of each resource no matter how many duplicates were in either list.
$new_resourcelist = $resourcelist->except( $resource );
$new_resourcelist = $resourcelist->except( *resource list* );
Create a new resource list with containing only the resources which are in $resourcelist but not in the list being passed in. Only returns one instance of each resource no matter how many duplicates were in either list.
$array = $resourcelist->link();
$array = $resourcelist->prettyLink();
Calls link() or prettyLink() on each item in the resource list and returns it as an array. The array is an object which you can call join() on, so you can use:
print $list->sort( "foaf:name" )->prettyLink()->join( ", ").".";
To print a nicely formatted list of names, linking to the URIs.
$dump = $resourcelist->dump( [$options] );
$dump = $resourcelist->dumpText( [$options] );
Returns a string containing a dump of all the resources in the list. Options is an optional array, same parameters as $options on a dump() of an individual resource. dumpText() does the same thing but with ASCII indents rather than HTML markup.

* Note about Graphite methods which can take a list of resources

These methods work in a pretty cool way. To make life easier for you they can take a list of resources in any of the following ways.

$resource->get() is used as an example, it applies to many other methods.

$resource->get( $uri_string )
Such as "".
$resource->get( $short_uri_string )
using any namespace defined with $graph->ns() or just built in. eg. "foaf:name".
$resource->get( $resource )
An instance of Graphite_resource.
$resource->get( $thing, $thing, $thing, ... )
$resource->get( array( $thing, $thing, $thing, ... ) )
Where each thing is any of $uri_string, $short_uri_string or $resource.
$resource->get( $resourcelist )
An instance of Graphite_resourceList.

This should make it quick and easy to write readable code!

Resource Description

Resource descriptions are a powerful new feature added in Graphite v1.5. These let you specify what relationships are needed to describe a resource and then create a new graph from an existing graph, or load the required data from a SPARQL endpoint. No knowledge of SPARQL is required.

It also allows you to output the resulting graph in a number of common formats, including JSON. The JSON is treated as a tree, based on the routes you specify from the starting resource. It is absolutely not JSON LD, although I would be happy to add JSON LD support as an additional output format if there's a demand for it.

A Graphite Resource Description is a quick and easy way to make a linked-data website. You just describe the data you need about a resource, eg. a person, and look at the format suffix of the current page. If it's anything other than HTML you let the resource description object handle it for you, if it's HTML you use normal graphite functions to produce a page.

The following example assumes that the PHP script is aliased to /building and everything after that in the path is a parameter to the script, eg. 59.html or 32.json

list( $id, $format ) = preg_split( "/\./", substr( $_SERVER["PATH_INFO"], 1 ), 2 );
$uri = ''.$id;

$graph = new Graphite();
$graph->ns( "sr", "" );

$rd = $graph->resource( "" )->prepareDescription();

$rd->addRoute( '*' );
$rd->addRoute( '*/rdfs:label' );
$rd->addRoute( '*/rdf:type' );
$rd->addRoute( '-sr:within/rdf:type' );
$rd->addRoute( '-sr:within/rdfs:label' );

$n = $rd->loadSPARQL( "" );

if( $format != "html" ) {
        # Unless this is HTML just let Graphite serve the document.
        if( !$rdesc->handleFormat( $format ) ) { 
		header('HTTP/1.0 404 Not Found');
		print "404 Not Found\n"; 

// output normal HTML page base on $graph...
$rd = $resource->prepareDescription()
Create a fresh resource-description object using the given resource as a "root".
Add a route to the description. The format is a slash-separated list of "hops" from the root resource. Each "hop" is either a short-form predicate, like foaf:name or a "*" indicating all predicates should be followed, prefixing the predicate (or *) with a minus sign "-" indicates that this relation should be followed backwards rather than forward.

So if we wanted all the members of a club:

$rd = $graph->resource( "" )->prepareDescription();
$rd->addRoute( "foaf:member" );
but this only gets their URIs so we probably want their names too:
$rd->addRoute( "foaf:member/foaf:name" );
to add all the people they know (and their names):
$rd->addRoute( "foaf:member/foaf:knows/foaf:name" );
and to add all the people who know members of this club:
$rd->addRoute( "foaf:member/-foaf:knows/foaf:name" );
note that "foaf:member/-foaf:knows/foaf:name" will add "foaf:member/-foaf:knows" and "foaf:member/" automatically.

The most common routes you will want are:

$rd->addRoute( "*" );
$rd->addRoute( "*/rdf:type" );
$rd->addRoute( "*/rdfs:label" );

A richer syntax may be added in a future version, ideally I'd like something which allowed "*/(rdf:type|rdfs:label)".

$formats = $rd->getFormats()
Return an array of the formats handleFormat currently supports, with the format code as keys, and the values are a human-readable name.
$handled = $rd->handleFormat($format)
Send a document based on the resource description, in the format requested. Return true if Graphite understands that format.
  • "json" : JSON structured tree data. Not a formal JSON-LD format as I believe it's too complicated for the requirements of most coders wishing to consume JSON. If ?callback=funcname is specified then the output will be in the form of a JSONP script.
  • "nt" : N-Triples - a list of uncompressed triples. Verbose but easy to parse.
  • "rdf" : RDF+XML - the ubiquitous but heinous XML serialisation of RDF.
  • "ttl" : Turtle - the much nicer Turtle serialisation.
  • "rdf.html" : An HTML description of the data. The results of running $graph->dump(). Really handy for debugging.

I am considering adding some additional formats, including RDFa (as a bunch of <span> elements), KML (find things that have a lat/long etc. basically nicking the code from geo2kml), JSON-LD - which is a lossless way to describe RDF in JSON, .dot - a format used to produce images of graphs. Please drop me a line if any of these, or others, are useful to you.

$count = $rd->loadSPARQL($endpoint)
This uses one or more SPARQL queries to the given endpoint to get all the triples required for the description. The return value is the total number of triples added to the graph.
$new_graph = $rd->toGraph()
In addition to loadSPARQL you can use $rd->toGraph() which creates a new Graphite graph object from the triples in the current graph, using the resource description as the pattern of what to copy. Preferences such as namespaces are not currently copied to the new graph, but may be in a later version of Graphite.


Get in touch with me at and you could have a look at our web team blog.

Known Bugs

Change Log

Version 1.5 (2012-03-11)

Version 1.4 (2010-07-28)

Version 1.3

Version 1.2

Version 1.1 (2010-03-23)

New features: