Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Graph Core Laravel Package

nexus-scholar/graph-core

Lightweight PHP 8.2+ graph data-structure for directed/undirected graphs with node/edge attributes, fast adjacency via integer indexing, read-only subgraph views, and exporters for Cytoscape.js JSON, GraphML, and GEXF. Ideal base for graph analytics.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require nexus-scholar/graph-core
    

    Ensure PHP 8.2+ and ext-dom are enabled for XML exports.

  2. First Use Case: Model a simple directed graph (e.g., citation network):

    use nexus-scholar\graph_core\Domain\Graph;
    
    $graph = new Graph(directed: true);
    $graph->addNode('paper1', ['title' => 'Research Paper 1']);
    $graph->addEdge('paper1', 'paper2', ['cites' => true]);
    
  3. Where to Look First:

    • Core Classes: Graph (mutable), SubgraphView (read-only), Node, Edge.
    • Exporters: CytoscapeJsonExporter, GraphMLExporter, GexfExporter (for visualization).
    • Documentation: Focus on Domain/ for graph operations and IO/ for exports.

Implementation Patterns

Usage Patterns

  1. Graph Construction:

    • Use Graph::fromEdgeList() for bulk imports (e.g., from CSV/JSON):
      $edges = [['paper1', 'paper2', ['year' => 2020]]];
      $graph = Graph::fromEdgeList($edges, directed: true);
      
    • Prefer addNode() before addEdge() to avoid errors.
  2. Querying:

    • Adjacency: Use successors()/predecessors() for traversal:
      $citations = $graph->successors('paper1', ['cites' => true]);
      
    • Subgraphs: Create lightweight views for filtered analysis:
      $subgraph = new SubgraphView($graph, ['paper1', 'paper2']);
      
  3. Attributes:

    • Store metadata as associative arrays (e.g., ['weight' => 1.0, 'label' => '...']).
    • Access via nodeAttrs()/edgeAttrs():
      $title = $graph->nodeAttrs('paper1')['title'];
      
  4. Exports:

    • Visualization: Export to Cytoscape.js for interactive graphs:
      $exporter = new \nexus-scholar\graph_core\IO\CytoscapeJsonExporter();
      $json = $exporter->export($graph);
      
    • Analysis Tools: Use GraphML/GEXF for Gephi/NetworkX:
      $gexf = (new \nexus-scholar\graph_core\IO\GexfExporter())->export($graph);
      

Workflows

  1. Data Pipeline:

    [CSV/JSON] → Graph::fromEdgeList() → SubgraphView → Export → Visualization
    

    Example: Filter a citation graph by year before exporting:

    $recentPapers = array_filter($graph->nodes(), fn($id) =>
        $graph->nodeAttrs($id)['year'] > 2020
    );
    $subgraph = new SubgraphView($graph, array_keys($recentPapers));
    
  2. Integration with Algorithms:

    • Pair with nexus-scholar/graph-algorithms for pathfinding/centrality:
      $centrality = (new \nexus_scholar\graph_algorithms\Centrality\DegreeCentrality())
          ->calculate($graph);
      
  3. Testing:

    • Use SubgraphView to isolate test cases:
      $testGraph = new SubgraphView($graph, ['paper1', 'paper2']);
      $this->assertTrue($testGraph->hasEdge('paper1', 'paper2'));
      

Integration Tips

  • Laravel Eloquent: Attach graphs to models via JSON columns:
    $paper->graph_data = json_encode($graph->toArray());
    
  • Queue Jobs: Export graphs asynchronously for large datasets:
    GraphExportJob::dispatch($graph, 'gexf')->onQueue('exports');
    
  • Caching: Cache SubgraphView instances for repeated queries:
    $cache->remember("subgraph_{$key}", 3600, fn() =>
        new SubgraphView($graph, $nodeIds)
    );
    

Gotchas and Tips

Pitfalls

  1. Node/Edge Existence:

    • hasEdge()/hasNode() return false for undirected graphs if the edge isn’t explicitly added (even if logically bidirectional).
    • Fix: Always add edges in both directions for undirected graphs:
      $graph->addEdge('A', 'B'); // Undirected: adds A→B and B→A
      
  2. Attribute Overwrites:

    • addEdge()/addNode() overwrite existing attributes if the same key is reused.
    • Fix: Use updateEdgeAttrs()/updateNodeAttrs() for partial updates:
      $graph->updateEdgeAttrs('A', 'B', ['weight' => 2.0]);
      
  3. Subgraph Views:

    • Views are read-only and reflect the parent graph’s state. Modifying the parent affects the view.
    • Fix: Clone the graph if mutations are needed:
      $mutableCopy = clone $graph;
      
  4. Exporter Dependencies:

    • GraphMLExporter/GexfExporter require ext-dom. Use CytoscapeJsonExporter as a fallback:
      if (!extension_loaded('dom')) {
          $exporter = new \nexus-scholar\graph_core\IO\CytoscapeJsonExporter();
      }
      
  5. Performance:

    • Integer indexing is fast, but string node IDs add overhead. Use short, consistent IDs (e.g., p1, p2) for large graphs.

Debugging

  1. Graph State:

    • Dump the graph structure for debugging:
      dd([
          'nodes' => $graph->nodes(),
          'edges' => $graph->edges(),
          'attrs' => $graph->nodeAttrs('paper1'),
      ]);
      
  2. Edge Directionality:

    • Verify directed/undirected behavior:
      $graph = new Graph(directed: false);
      $graph->addEdge('A', 'B');
      var_dump($graph->hasEdge('B', 'A')); // true (undirected)
      
  3. Exporter Issues:

    • Validate XML/JSON output with tools like XMLLint or json_validate():
      if (json_validate($json) === JSON_ERROR_NONE) {
          // Valid JSON
      }
      

Tips

  1. Type Safety:

    • Use PHP 8.2+ typed properties for custom graph classes:
      class CitationGraph extends Graph {
          public function __construct(public array $citationRules = []) {}
      }
      
  2. Serialization:

    • Implement JsonSerializable for easy storage:
      class GraphJsonSerializer implements \JsonSerializable {
          public function jsonSerialize(): array {
              return [
                  'nodes' => $this->graph->nodes(),
                  'edges' => $this->graph->edges(),
              ];
          }
      }
      
  3. Extension Points:

    • Custom Exporters: Implement ExporterInterface for new formats:
      class DotExporter implements ExporterInterface {
          public function export(GraphInterface $graph): string {
              // Custom DOT format logic
          }
      }
      
    • Graph Traits: Extend Graph with domain-specific traits:
      trait CitationGraphTrait {
          public function addCitation(string $from, string $to, int $year): void {
              $this->addEdge($from, $to, ['year' => $year, 'type' => 'citation']);
          }
      }
      
  4. Configuration:

    • Store graph settings (e.g., directed/undirected) in a config file:
      // config/graph.php
      return [
          'default_directed' => env('GRAPH_DIRECTED', true),
      ];
      
      $graph = new Graph(directed: config('graph.default_directed'));
      
  5. Large Graphs:

    • Use SubgraphView to limit memory usage during analysis:
      $view = new SubgraphView($graph, array_slice($nodeIds, 0, 1000));
      
    • Batch exports for graphs >10,000 nodes:
      $exporter->export($subgraph)->writeToFile("part_{$i}.gexf");
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky