mbsoft31/graph-core
Lightweight, dependency-free graph library for PHP 8.2+. Build directed/undirected graphs with node and edge attributes, fast adjacency lookups, subgraph views, and export to Cytoscape.js JSON, GraphML, and GEXF (XML exports require ext-dom).
A lightweight, performant, and dependency-free graph data structure library for PHP. This library provides a clean, modern API for working with directed and undirected graphs, with support for node and edge attributes, subgraph views, and multiple export formats.
Install via Composer:
composer require mbsoft/graph-core
use Mbsoft\Graph\Domain\Graph;
// Create a directed graph
$graph = new Graph(directed: true);
// Add nodes with attributes
$graph->addNode('A', ['label' => 'Node A', 'color' => 'red']);
$graph->addNode('B', ['label' => 'Node B', 'color' => 'blue']);
$graph->addNode('C', ['label' => 'Node C', 'color' => 'green']);
// Add edges with weights
$graph->addEdge('A', 'B', ['weight' => 1.5]);
$graph->addEdge('B', 'C', ['weight' => 2.0]);
$graph->addEdge('C', 'A', ['weight' => 0.5]);
// Query the graph
echo count($graph->nodes()); // 3
echo count($graph->edges()); // 3
// Check connections
if ($graph->hasEdge('A', 'B')) {
$weight = $graph->edgeAttrs('A', 'B')['weight'];
echo "Edge A->B has weight: $weight\n";
}
// Get neighbors
$successors = $graph->successors('A'); // ['B']
$predecessors = $graph->predecessors('C'); // ['B']
use Mbsoft\Graph\Domain\Graph;
// Create an undirected graph
$graph = new Graph(directed: false);
$graph->addEdge('A', 'B', ['type' => 'friendship']);
$graph->addEdge('B', 'C', ['type' => 'friendship']);
// In undirected graphs, edges work both ways
$graph->hasEdge('A', 'B'); // true
$graph->hasEdge('B', 'A'); // true (same edge)
// Successors and predecessors are the same (neighbors)
$graph->successors('B'); // ['A', 'C']
$graph->predecessors('B'); // ['A', 'C']
use Mbsoft\Graph\Domain\Graph;
$edges = [
['A', 'B', ['weight' => 1.0]],
['B', 'C', ['weight' => 2.0]],
['C', 'D', ['weight' => 1.5]],
['D', 'A', ['weight' => 3.0]],
];
$graph = Graph::fromEdgeList($edges, directed: true);
Create efficient, read-only views of a subset of nodes:
use Mbsoft\Graph\Domain\Graph;
use Mbsoft\Graph\Domain\SubgraphView;
// Create a graph
$graph = new Graph();
$graph->addEdge('A', 'B');
$graph->addEdge('B', 'C');
$graph->addEdge('C', 'D');
$graph->addEdge('D', 'E');
// Create a view containing only nodes A, B, and C
$subgraph = new SubgraphView($graph, ['A', 'B', 'C']);
// The view only shows edges within the selected nodes
$subgraph->nodes(); // ['A', 'B', 'C']
$subgraph->edges(); // Only A->B and B->C edges
$subgraph->hasEdge('C', 'D'); // false (D not in view)
// Update node attributes (merge with existing)
$graph->addNode('A', ['new_attr' => 'value']);
// Replace all node attributes
$graph->setNodeAttrs('A', ['only' => 'this']);
// Update edge attributes
$graph->setEdgeAttrs('A', 'B', ['weight' => 5.0, 'label' => 'Strong']);
Export graphs for visualization with Cytoscape.js:
use Mbsoft\Graph\IO\CytoscapeJsonExporter;
$exporter = new CytoscapeJsonExporter();
$json = $exporter->export($graph);
// Result structure:
// [
// 'elements' => [
// 'nodes' => [
// ['data' => ['id' => 'A', 'label' => 'Node A', ...]],
// ...
// ],
// 'edges' => [
// ['data' => ['source' => 'A', 'target' => 'B', 'weight' => 1.5]],
// ...
// ]
// ]
// ]
file_put_contents('graph.json', json_encode($json));
Export to GraphML format for use with tools like Gephi, yEd, or NetworkX:
use Mbsoft\Graph\IO\GraphMLExporter;
$exporter = new GraphMLExporter();
$xml = $exporter->export($graph);
file_put_contents('graph.graphml', $xml);
Export to GEXF format for Gephi and other network analysis tools:
use Mbsoft\Graph\IO\GexfExporter;
$exporter = new GexfExporter();
$xml = $exporter->export($graph);
file_put_contents('graph.gexf', $xml);
GraphInterface: Read-only graph operationsMutableGraphInterface: Extends GraphInterface with modification methodsExporterInterface: Common interface for all export formatsGraph: The main mutable graph implementationSubgraphView: Efficient filtered view of a graphNode: Immutable value object for nodesEdge: Immutable value object for edgesIndexMap: Internal bidirectional mapping for performanceRun the test suite:
composer test
Run tests with coverage:
composer test:coverage
Run static analysis:
composer analyse
This library is perfect for:
The library is optimized for performance:
Performance with a 1,000 node graph:
$socialNetwork = new Graph(directed: false);
// Add users
$socialNetwork->addNode('alice', ['name' => 'Alice', 'age' => 28]);
$socialNetwork->addNode('bob', ['name' => 'Bob', 'age' => 32]);
$socialNetwork->addNode('charlie', ['name' => 'Charlie', 'age' => 25]);
// Add friendships
$socialNetwork->addEdge('alice', 'bob', ['since' => '2020']);
$socialNetwork->addEdge('bob', 'charlie', ['since' => '2019']);
// Find friends of friends
$bobsFriends = $socialNetwork->successors('bob'); // ['alice', 'charlie']
$tasks = new Graph(directed: true);
// Add tasks
$tasks->addNode('compile', ['duration' => 30]);
$tasks->addNode('test', ['duration' => 45]);
$tasks->addNode('package', ['duration' => 15]);
$tasks->addNode('deploy', ['duration' => 20]);
// Add dependencies
$tasks->addEdge('compile', 'test');
$tasks->addEdge('test', 'package');
$tasks->addEdge('package', 'deploy');
// Find what needs to be done before deployment
$deployPrereqs = $tasks->predecessors('deploy'); // ['package']
Contributions are welcome! Please feel free to submit a Pull Request.
git checkout -b feature/amazing-feature)git commit -m 'Add some amazing feature')git push origin feature/amazing-feature)This library is open-sourced software licensed under the MIT license.
For bugs and feature requests, please use the GitHub issues page.
How can I help you explore Laravel packages today?