spatie/schema-org
Fluent PHP builder for the full Schema.org vocabulary. Create Schema.org types and properties via chainable methods and output valid JSON-LD/ld+json scripts for SEO. Auto-generated from Schema.org standards for complete coverage.
Installation:
composer require spatie/schema-org
No additional configuration is required—just autoload the package.
First Use Case:
Generate a basic LocalBusiness schema for SEO/rich snippets:
use Spatie\SchemaOrg\Schema;
$business = Schema::localBusiness()
->name('Acme Corp')
->description('Innovative solutions since 2023')
->telephone('+1234567890');
echo $business->toScript(); // Outputs <script type="application/ld+json">...</script>
Where to Look First:
src/ for generated classes (e.g., LocalBusiness.php, Product.php).Schema::TYPE() (e.g., Schema::localBusiness()) for autocompletion.$product = Schema::product()
->name('Premium Widget')
->brand('Acme')
->offers(Schema::offer()->price(99.99)->currency('USD'));
if() to avoid breaking chains:
$business = Schema::localBusiness()
->name('Acme')
->if($hasEmail, fn($b) => $b->email('contact@acme.com'));
Graph to link entities (e.g., Organization ↔ Product):
$graph = new \Spatie\SchemaOrg\Graph();
$graph->organization()->name('Acme Corp');
$graph->product()->name('Widget')->brand($graph->organization());
echo $graph; // Renders all linked entities
$graph->hide(\Spatie\SchemaOrg\Organization::class);
setProperty() for non-standard fields:
$product->setProperty('customField', 'value');
addProperties() for multiple fields:
$product->addProperties(['sku' => 'ABC123', 'weight' => '1.5kg']);
HotelRoom + Product):
$mte = new \Spatie\SchemaOrg\MultiTypedEntity();
$mte->hotelRoom()->name('Suite');
$mte->product()->offers(Schema::offer()->price(500));
echo json_encode($mte);
$schema['name'] = 'Acme'; // Equivalent to ->name('Acme')
unset($schema['description']); // Remove property
echo $schema->toScript(); // <script type="application/ld+json">...</script>
echo json_encode($schema);
$data = $schema->toArray();
HTML Injection in toScript():
<script> or </script> may break the output.htmlspecialchars() on user-provided data or rely on the package’s auto-escaping (v4.0.2+):
$schema->description('<b>Safe</b> text'); // Escaped automatically
@id vs. identifier:
identifier was replaced with @id in v2.6.0 for JSON-LD compliance.identifier will fail. Update to:
$schema->setProperty('@id', 'https://example.com/id');
Floating-Point Precision:
Float type is reserved in PHP. Use strings or integers for numeric properties:
$schema->price('99.99'); // String to avoid precision loss
Graph Node Conflicts:
Graph may overwrite nodes.$graph->person('user1', fn($p) => $p->name('Alice'));
$graph->person('user2', fn($p) => $p->name('Bob'));
Multi-Typed Entity (MTE) Merges:
setProperty() to disambiguate:
$mte->setProperty('name', 'Suite'); // Overrides both types
Missing Types:
Physician) are excluded due to extension conflicts.Validate Output:
Inspect Properties:
print_r($schema->getProperties());
Check for Deprecated Methods:
php artisan vendor:publish --tag=schema-org-config to review changes in newer versions.Handle Enumerations:
BookFormatType::Hardcover):
$book->bookFormat(\Spatie\SchemaOrg\BookFormatType::Hardcover);
Custom Schema Types:
\Spatie\SchemaOrg\Types\Type to add new types:
class CustomType extends Type {
public function customMethod() { ... }
}
Modify Generated Classes:
app/Spatie/SchemaOrg/ to add methods/properties.Hook into Graph Rendering:
\Spatie\SchemaOrg\Graph to filter or transform nodes before output.Add Validation:
How can I help you explore Laravel packages today?