Giter VIP home page Giter VIP logo

schema-org's Introduction

A Fluent Builder For Schema.org Types And ld+json Generator

Latest Version on Packagist MIT License GitHub Workflow Status StyleCI Total Downloads

spatie/schema-org provides a fluent builder for all Schema.org types and their properties. The code in src is generated from Schema.org's JSON-LD standards file, so it provides objects and methods for the entire core vocabulary. The classes and methods are also fully documented as a quick reference.

use Spatie\SchemaOrg\Schema;

$localBusiness = Schema::localBusiness()
    ->name('Spatie')
    ->email('[email protected]')
    ->contactPoint(Schema::contactPoint()->areaServed('Worldwide'));

echo $localBusiness->toScript();
<script type="application/ld+json">
{
    "@context": "https:\/\/schema.org",
    "@type": "LocalBusiness",
    "name": "Spatie",
    "email": "[email protected]",
    "contactPoint": {
        "@type": "ContactPoint",
        "areaServed": "Worldwide"
    }
}
</script>

Support us

We invest a lot of resources into creating best in class open source packages. You can support us by buying one of our paid products.

We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on our contact page. We publish all received postcards on our virtual postcard wall.

Installation

You can install the package via composer:

composer require spatie/schema-org

Usage

All types can be instantiated through the Spatie\SchemaOrg\Schema factory class, or with the new keyword.

$localBusiness = Schema::localBusiness()->name('Spatie');

// Is equivalent to:

$localBusiness = new LocalBusiness();
$localBusiness->name('Spatie');

All types also accept arrays of the expected data type, for example sameAs accepts a string or an array of strings.

All types also implement the SPL's ArrayAccess for accessing the properties via array notation:

$anotherLocalBusiness = new LocalBusiness();
var_dump(isset($anotherLocalBusiness['name'])); // => false
$anotherLocalBusiness['name'] = 'Spatie';
var_dump(isset($anotherLocalBusiness['name'])); // => true
var_dump($anotherLocalBusiness['name']); // => 'Spatie'
unset($anotherLocalBusiness['name']);
var_dump(isset($anotherLocalBusiness['name'])); // => false

Types can be converted to an array or rendered to a script.

$localBusiness->toArray();

echo $localBusiness->toScript();

echo $localBusiness; // Same output as `toScript()`

Additionally, all types can be converted to a plain JSON string by just calling json_encode() with your object:

echo json_encode($localBusiness);

I recommend double checking your structured data with Google's structured data testing tool.

Enumerations

As of v1.6.0, all Enumeration child types are available as classes with constants.

Schema::book()->bookFormat(Spatie\SchemaOrg\BookFormatType::Hardcover);

There's no full API documentation for types and properties. You can refer to the source or to the schema.org website.

If you don't want to break the chain of a large schema object, you can use the if method to conditionally modify the schema.

use Spatie\SchemaOrg\LocalBusiness;
use Spatie\SchemaOrg\Schema;

$business = ['name' => 'Spatie'];

$localBusiness = Schema::localBusiness()
    ->name($business['name'])
    ->if(isset($business['email']), function (LocalBusiness $schema) use ($business) {
        $schema->email($business['email']);
    });

Identifier

As of v2.6.0 the identifier key is replaced by @id for simple string identifiers. This is due to the definition for the ld+json syntax.

All schema.org syntaxes already have built-in representation for URIs and URLs, e.g. in Microdata 'itemid', in RDFa 1.1, 'resource', in JSON-LD, '@id'.

โ€” schema.org/docs // PR#102 // PR#157

Advanced Usage

If you'd need to set a custom property, you can use the setProperty method.

$localBusiness->setProperty('foo', 'bar');

If you'd need to retrieve a property, you can use the getProperty method. You can optionally pass in a second parameter to provide a default value.

$localBusiness->getProperty('name'); // 'Spatie'
$localBusiness->getProperty('bar'); // null
$localBusiness->getProperty('bar', 'baz'); // 'baz'

All properties can be retrieved as an array with the getProperties method.

$localBusiness->getProperties(); // ['name' => 'Spatie', ...]

Multiple properties can be set at once using the addProperties method.

$localBusiness->addProperties(['name' => 'value', 'foo' => 'bar']);

Context and type can be retrieved with the getContext and getType methods.

$localBusiness->getContext(); // 'https://schema.org'
$localBusiness->getType(); // 'LocalBusiness'

Graph - multiple items

The Graph has a lot of methods and utilities - the type-safe and simplest way is to use the overloaded methods of the Spatie\SchemaOrg\Schema class itself. These methods will get an already created or new instance of the requested schema.

$graph = new Graph();

// Create a product and prelink organization
$graph
    ->product()
    ->name('My cool Product')
    ->brand($graph->organization());

// Hide the organization from the created script tag
$graph->hide(\Spatie\SchemaOrg\Organization::class);

// Somewhere else fill out the organization
$graph
    ->organization()
    ->name('My awesome Company');

// Render graph to script tag
echo $graph;

With these tools the graph is a collection of all available schemas, can link these schemas with each other and prevent helper schemas from being rendered in the script-tag.

Graph Node identifiers

Sometimes you have to keep track of multiple Graph nodes of the same type - for example multiple Person nodes for different people in your Organization. To do so you are able to use node identifiers on your graph instance. If you don't provide an identifier a reserved keyword default identifier will be used.

use Spatie\SchemaOrg\Graph;
use Spatie\SchemaOrg\Person;

$graph = new Graph();

// add a Person using chaining
$graph->person('freekmurze')
    ->givenName('Freek')
    ->familyName('Van der Herten')
    ->alternateName('freekmurze');

// add a Person using closure
$graph->person('sebastiandedeyne', function(Person $sebastian, Graph $graph): void {
    $sebastian
        ->givenName('Sebastian')
        ->familyName('De Deyne')
        ->alternateName('sebastiandedeyne');
}); 

// add a person using closure and second call with same identifier
$graph->person(
    'gummibeer', 
    fn(Person $gummibeer) => $gummibeer->alternateName('gummibeer')
);
$graph->person('gummibeer')
    ->givenName('Tom')
    ->familyName('Witkowski');

$graph->person('random')->name('Random Person');

// hide the random person from Graph
$graph->hide(Person::class, 'random');

echo json_encode($graph);
{
    "@context":"https:\/\/schema.org",
    "@graph":[
        {
            "@type":"Person",
            "givenName":"Freek",
            "familyName":"Van der Herten",
            "alternateName":"freekmurze"
        },
        {
            "@type":"Person",
            "givenName":"Sebastian",
            "familyName":"De Deyne",
            "alternateName":"sebastiandedeyne"
        },
        {
            "@type":"Person",
            "alternateName":"gummibeer",
            "givenName":"Tom",
            "familyName":"Witkowski"
        }
    ]
}

Multi Typed Entities

Schema.org allows multi typed entities - to use them with this package you can use the MultiTypedEntity class - which works similar to the graph.

$mte = new MultiTypedEntity();
$mte->hotelRoom()->name('The Presidential Suite');
$mte->product()->offers(
    Schema::offer()
        ->name('One Night')
        ->price(100000.00)
        ->priceCurrency('USD')
);
$mte->product(function (Product $product) {
    $product->aggregateRating(
        Schema::aggregateRating()
            ->bestRating(5)
            ->worstRating(4)
    );
});

echo json_encode($mte);
{
   "@context":"https:\/\/schema.org",
   "@type":[
      "HotelRoom",
      "Product"
   ],
   "name":"The Presidential Suite",
   "offers":{
      "@type":"Offer",
      "name":"One Night",
      "price":100000,
      "priceCurrency":"USD"
   },
   "aggregateRating":{
      "@type":"AggregateRating",
      "bestRating":5,
      "worstRating":4
   }
}

There isn't a real rule in place how the properties are merged. It only uses array_merge() behind the scenes. So you should avoid defining the same property on different types in the MTE or be sure that all properties hold the same value that it's not important which property is used at the end.

Known Issues

  • The Float type isn't available since it's a reserved keyword in PHP
  • The Physician type isn't available since it extends a type from the health extension spec

Changelog

Please see CHANGELOG for more information what has changed recently.

Testing

$ composer test

Contributing

Please see CONTRIBUTING for details.

Security

If you've found a bug regarding security please mail [email protected] instead of using the issue tracker.

Postcardware

You're free to use this package, but if it makes it to your production environment we highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using.

Our address is: Spatie, Kruikstraat 22, 2018 Antwerp, Belgium.

We publish all received postcards on our company website.

Credits

License

The MIT License (MIT). Please see License File for more information.

schema-org's People

Contributors

adrianmrn avatar alexbowers avatar alexvanderbist avatar dougblackjr avatar freekmurze avatar graste avatar gummibeer avatar igor-kamil avatar indyjonesnl avatar jazz-man avatar johjohan avatar jose-gomez-evinex avatar korvinszanto avatar mallardduck avatar mvdnbrk avatar neildaniels avatar nielsvanpach avatar olivermack avatar osopolar avatar otsch avatar owljester avatar pascalmoser avatar patinthehat avatar sangnguyenplus avatar sebastiandedeyne avatar smortexa avatar spekulatius avatar thomasredstone avatar tjoosten avatar toflar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

schema-org's Issues

Recipe properties missing

The current schema.org documentation on https://schema.org/Recipe says that Recipe should have properties like prepTime, recipeIngredient, recipeInstructions, recipeYield and so on. They currently aren't generated in Recipe.php.

The source does hold some information about these fields though:

<div typeof="rdf:Property" resource="http://schema.org/recipeYield">
  <span class="h" property="rdfs:label">recipeYield</span>
  <span property="rdfs:comment">The quantity produced by the recipe (for example, number of people served, number of servings, etc).</span>
  <span>Domain: <a property="http://schema.org/domainIncludes" href="http://schema.org/Recipe"> Recipe</a></span>
  <span>Range: <a property="http://schema.org/rangeIncludes" href="http://schema.org/Text"> Text </a></span>
</div>

schema.org repo has dropped most RDFa files

blocking #80 and future type updates.

A benefit if this change is that the files are now part of release folders - so for us it should be easier to decide if a new update is breaking or not.
Following the latest version everything is now released as:

  • JSON-LD
  • NQ
  • NT
  • RDF
  • TTL
  • CSV

Even pending types seem to be versioned. So we could get rid of all the "missing XYZ type" issues.
In my opinion we should decide for the new type to use - for RDF there is a lib easyrdf and it seems similar to RDFa - both are XML, so in worst case we could parse it by our own.
During this I would introduce sub namespaces for Pending and Extensions - so we always parse all available/official types.

Because of the new namespaces, included extension, new major schema version and so on I would say that we should use a new major version for this change.
But it's also a critical one because until this is fixed we can't proceed with #80


Update 2020-08-24: @mallardduck will prepare a JSON-LD parser for current v7 to check if it's working and afterward upgrade it to v8 and v9 in consecutive PRs.
#133 (comment)

create schema instance by ld+json

I have no idea if this is in scope of this package!? But creating an instance of schema, types, graph by ld+json would be great.
This would allow to use this package vice versa and crawl pages and get OOP instances of the available schema. But it would also ok to do this in another package.

Global markup/type

Hello,

How do I set global ld-json type?
For example every page may include local business (site info). Where should I put it?

Regards

Datetime values throws InvalidProperty exceptions

Hi!
Thanks for this great library. I'm using it to generate the schema of some articles and I get an exception using Datetime instances as the value of some properties like dateCreated. Example:

use Spatie\SchemaOrg\Schema;

$schema = Schema::Article()
	->headLine($article->title)
	->author(Schema::Person()
		->name($article->author->name)
	)
	->dateCreated(new Datetime($article->createdDate));

echo $schema->toScript();

The signature of the function accepts DateTimeInterface instances, so in theory this should work.

Schema type Brand

Per the spec the โ€œBrandโ€ is a child of โ€œThing > Intangible > Brandโ€ and as such should accept a Thing, whereas you have the injection dependency โ€œorganizationโ€œ and therefore

Change to Class:

    class Product extends BaseType

Current (From):

	/**
	 * The brand(s) associated with a product or service, or the brand(s)
	 * maintained by an organization or business person.
	 *
         * @param Brand|Brand[]|Organization|Organization[] $brand
	 *
	 * @return static
	 *
	 * @see http://schema.org/brand
	 */
	public function brand($brand)
	{
	    return $this->setProperty('brand', $brand);
	}

Change (To):

	/**
	 * The brand(s) associated with a product or service, or the brand(s)
	 * maintained by an organization or business person.
	 *
	 * @param Brand|Brand[]|Thing|Thing[] $brand
	 *
	 * @return static
	 *
	 * @see http://schema.org/brand
	 */
	public function brand($brand)
	{
	    return $this->setProperty('brand', $brand);
	}

As always a phenomenal library. Thanks!

Graph with multiple instances of same type

The Graph class #62 allows to keep a single instance of each type in the graph. Sometimes I would like to manage multiple instances of the same type in one graph.

Let's say I would like to create a graph for this package - I would have a CreativeWork for the package and would need one Person for every contributor/commenter. These persons I could need again as the author of an issue or whatever.
To do so I will have to keep track of the instances in a custom variable $persons which is filled by Schema::person() and could be reused via $persons['gummibeer']. But this isn't as smooth as the workflow of the graph which could manage types in multiple places via object references and I don't have to fill the person record I reference it the first time.

The idea would be to add an optional string identifier to manage multiple instances of the same type in a single graph.

$graph = new Graph();
$graph->person('gummibeer')->name('Tom Witkowski')->alternateName('Gummibeer');
$graph->person('gummibeer');
$graph->person('gummibeer', function(Person $person, Graph $graph) {
    $person->email('[email protected]');
});

So far I've planned it this wouldn't be a BC so it could be released as a normal MINOR release. The new optional argument would be handled in __call() via checks of is_string is_callable to map the arguments to the right variable and in the other methods add, has and so on it would be added as an optional second argument so it won't change the already implemented method calls.
I would only adjust the behavior of show and hide to allow to show/hide all of a single type and a specific one (with identifier). To do so I would split the values of the identifier

  • null => all of the given type
  • 'default' (default) => the one created if no identifier is given
  • 'xyz' => a specific one

Is it possible to add multiple items of one type?

Hello

I want to add multiple openingHoursSpecification for business hours like this:

"openingHoursSpecification": [
    {
      "@type": "OpeningHoursSpecification",
      "dayOfWeek": [
        "Monday",
        "Tuesday"
      ],
      "opens": "11:30",
      "closes": "22:00"
    },
    {
      "@type": "OpeningHoursSpecification",
      "dayOfWeek": [
        "Wednesday",
        "Thursday",
        "Friday"
      ],
      "opens": "11:30",
      "closes": "23:00"
    },
    {
      "@type": "OpeningHoursSpecification",
      "dayOfWeek": "Saturday",
      "opens": "16:00",
      "closes": "23:00"
    },
    {
      "@type": "OpeningHoursSpecification",
      "dayOfWeek": "Sunday",
      "opens": "16:00",
      "closes": "22:00"
    }
  ],

Is this possible and how? In my case only one item seems to be possible. By adding multiple items only the last will be displayed.

Best regards

How to run generator?

Hi

I've installed the package via composer and notized that some classes are missing. So I've tried to search for the generator command on my projects symfony console. The generator is not listed and I've seen that the generator.php class is not installed by composer at all.

What's the best way to run the generator?

Thanks in advance
Nino

How to use Enumeration

I want to set itemCondition in a product object, but I dont know how to set the Enumeration? I want to set "http://schema.org/NewCondition" as value

                ->name('product name')
                ->image('https://www.domain.com/image.jpg')
                ->description('lorem ipsum dolor sit amet')
                ->offers(
                    \Spatie\SchemaOrg\Schema::offer()
                        ->priceCurrency('EUR')
                        ->price(100)
                        ->itemCondition(
                            $new ? \Spatie\SchemaOrg\Schema::offerItemCondition() : \Spatie\SchemaOrg\Schema::offerItemCondition()
                        )
                        ->availability(
                            $inStock ? \Spatie\SchemaOrg\Schema::itemAvailability() : \Spatie\SchemaOrg\Schema::itemAvailability()
                        )
                )
            ;

I see that exists the class OfferItemCondition extends Enumeration but I can not find how to set values of the enum

Insufficient handling of multitype parameters

The generated code contains wrong type declaration for parameters, if the original type contains alternatives like int|float. Example is the numberOfRooms parameter in Accommodation.php.

Currently, the parameter DocBlock line (line 42) is rendered as

@param float|int|float|int[]|QuantitativeValue|QuantitativeValue[] $numberOfRooms

It should be

@param float|int|float[]|int[]|QuantitativeValue|QuantitativeValue[] $numberOfRooms

Type implementation progress

  • Thing
    • Action
      • AchieveAction
        • LoseAction
        • TieAction
        • WinAction
      • AssessAction
        • ChooseAction
          • VoteAction
        • IgnoreAction
        • ReactAction
          • AgreeAction
          • DisagreeAction
          • DislikeAction
          • EndorseAction
          • LikeAction
          • WantAction
        • ReviewAction
      • ConsumeAction
        • DrinkAction
        • EatAction
        • InstallAction
        • ListenAction
        • ReadAction
        • UseAction
          • WearAction
        • ViewAction
        • WatchAction
      • ControlAction
        • ActivateAction
        • DeactivateAction
        • ResumeAction
        • SuspendAction
      • CreateAction
        • CookAction
        • DrawAction
        • FilmAction
        • PaintAction
        • PhotographAction
        • WriteAction
      • FindAction
        • CheckAction
        • DiscoverAction
        • TrackAction
      • InteractAction
        • BefriendAction
        • CommunicateAction
          • AskAction
          • CheckInAction
          • CheckOutAction
          • CommentAction
          • InformAction
            • ConfirmAction
            • RsvpAction
          • InviteAction
          • ReplyAction
          • ShareAction
        • FollowAction
        • JoinAction
        • LeaveAction
        • MarryAction
        • RegisterAction
        • SubscribeAction
        • UnRegisterAction
      • MoveAction
        • ArriveAction
        • DepartAction
        • TravelAction
      • OrganizeAction
        • AllocateAction
          • AcceptAction
          • AssignAction
          • AuthorizeAction
          • RejectAction
        • ApplyAction
        • BookmarkAction
        • PlanAction
          • CancelAction
          • ReserveAction
          • ScheduleAction
      • PlayAction
        • ExerciseAction
        • PerformAction
      • SearchAction
      • TradeAction
        • BuyAction
        • DonateAction
        • OrderAction
        • PayAction
        • QuoteAction
        • RentAction
        • SellAction
        • TipAction
      • TransferAction
        • BorrowAction
        • DownloadAction
        • GiveAction
        • LendAction
        • ReceiveAction
        • ReturnAction
        • SendAction
        • TakeAction
      • UpdateAction
        • AddAction
          • InsertAction
            • AppendAction
            • PrependAction
        • DeleteAction
        • ReplaceAction
    • CreativeWork
      • Article
        • NewsArticle
        • Report
        • ScholarlyArticle
        • SocialMediaPosting
          • BlogPosting
            • LiveBlogPosting
          • DiscussionForumPosting
        • TechArticle
          • APIReference
      • Blog
      • Book
      • Clip
        • MovieClip
        • RadioClip
        • TVClip
        • VideoGameClip
      • Comment
        • Answer
      • Conversation
      • CreativeWorkSeason
        • RadioSeason
        • TVSeason
      • CreativeWorkSeries
        • BookSeries
        • MovieSeries
        • Periodical
        • RadioSeries
        • TVSeries
        • VideoGameSeries
      • DataCatalog
      • Dataset
        • DataFeed
      • DigitalDocument
        • NoteDigitalDocument
        • PresentationDigitalDocument
        • SpreadsheetDigitalDocument
        • TextDigitalDocument
      • Episode
        • RadioEpisode
        • TVEpisode
      • Game
        • VideoGame
      • Map
      • MediaObject
        • AudioObject
        • DataDownload
        • ImageObject
          • Barcode
        • MusicVideoObject
        • VideoObject
      • Message
        • EmailMessage
      • Movie
      • MusicComposition
      • MusicPlaylist
        • MusicAlbum
        • MusicRelease
      • MusicRecording
      • Painting
      • Photograph
      • PublicationIssue
      • PublicationVolume
      • Question
      • Recipe
      • Review
      • Sculpture
      • Series
      • SoftwareApplication
        • MobileApplication
        • VideoGame
        • WebApplication
      • SoftwareSourceCode
      • TVSeason
      • TVSeries
      • VisualArtwork
      • WebPage
        • AboutPage
        • CheckoutPage
        • CollectionPage
          • ImageGallery
          • VideoGallery
        • ContactPage
        • ItemPage
        • ProfilePage
        • QAPage
        • SearchResultsPage
      • WebPageElement
        • SiteNavigationElement
        • Table
        • WPAdBlock
        • WPFooter
        • WPHeader
        • WPSideBar
      • WebSite
    • Event
      • BusinessEvent
      • ChildrensEvent
      • ComedyEvent
      • DanceEvent
      • DeliveryEvent
      • EducationEvent
      • ExhibitionEvent
      • Festival
      • FoodEvent
      • LiteraryEvent
      • MusicEvent
      • PublicationEvent
        • BroadcastEvent
        • OnDemandEvent
      • SaleEvent
      • ScreeningEvent
      • SocialEvent
      • SportsEvent
      • TheaterEvent
      • VisualArtsEvent
    • Intangible
      • AlignmentObject
      • Audience
        • BusinessAudience
        • EducationalAudience
        • PeopleAudience
          • ParentAudience
      • BedDetails
      • Brand
      • BroadcastChannel
        • RadioChannel
        • TelevisionChannel
      • BusTrip
      • ComputerLanguage
      • DataFeedItem
      • Demand
      • DigitalDocumentPermission
      • EntryPoint
      • Enumeration
        • ActionStatusType
        • BoardingPolicyType
        • BookFormatType
        • BusinessEntityType
        • BusinessFunction
        • ContactPointOption
        • DayOfWeek
        • DeliveryMethod
          • LockerDelivery
          • ParcelService
        • DigitalDocumentPermissionType
        • EventStatusType
        • GamePlayMode
        • GameServerStatus
        • GenderType
        • ItemAvailability
        • ItemListOrderType
        • MapCategoryType
        • MusicAlbumProductionType
        • MusicAlbumReleaseType
        • MusicReleaseFormatType
        • OfferItemCondition
        • OrderStatus
        • PaymentMethod
          • PaymentCard
            • CreditCard
        • PaymentStatusType
        • QualitativeValue
          • DriveWheelConfigurationValue
          • SteeringPositionValue
        • ReservationStatusType
        • RestrictedDiet
        • RsvpResponseType
        • Specialty
        • WarrantyScope
      • Flight
      • GameServer
      • Invoice
      • ItemList
        • BreadcrumbList
        • OfferCatalog
      • JobPosting
      • Language
      • ListItem
      • Offer
        • AggregateOffer
      • Order
      • OrderItem
      • ParcelDelivery
      • Permit
        • GovernmentPermit
      • ProgramMembership
      • PropertyValueSpecification
      • Quantity
        • Distance
        • Duration
        • Energy
        • Mass
      • Rating
        • AggregateRating
      • Reservation
        • BusReservation
        • EventReservation
        • FlightReservation
        • FoodEstablishmentReservation
        • LodgingReservation
        • RentalCarReservation
        • ReservationPackage
        • TaxiReservation
        • TrainReservation
      • Role
        • OrganizationRole
          • EmployeeRole
        • PerformanceRole
      • Seat
      • Service
        • BroadcastService
        • CableOrSatelliteService
        • FinancialProduct
          • BankAccount
            • DepositAccount
          • CurrencyConversionService
          • InvestmentOrDeposit
            • DepositAccount
          • LoanOrCredit
            • CreditCard
          • PaymentCard
          • PaymentService
        • FoodService
        • GovernmentService
        • TaxiService
      • ServiceChannel
      • StructuredValue
        • ContactPoint
          • PostalAddress
        • EngineSpecification
        • GeoCoordinates
        • GeoShape
          • GeoCircle
        • InteractionCounter
        • MonetaryAmount
        • NutritionInformation
        • OpeningHoursSpecification
        • OwnershipInfo
        • PriceSpecification
          • CompoundPriceSpecification
          • DeliveryChargeSpecification
          • PaymentChargeSpecification
          • UnitPriceSpecification
        • PropertyValue
          • LocationFeatureSpecification
        • QuantitativeValue
        • TypeAndQuantityNode
        • WarrantyPromise
      • Ticket
      • TrainTrip
    • Organization
      • Airline
      • Corporation
      • EducationalOrganization
        • CollegeOrUniversity
        • ElementarySchool
        • HighSchool
        • MiddleSchool
        • Preschool
        • School
      • GovernmentOrganization
      • LocalBusiness
        • AnimalShelter
        • AutomotiveBusiness
          • AutoBodyShop
          • AutoDealer
          • AutoPartsStore
          • AutoRental
          • AutoRepair
          • AutoWash
          • GasStation
          • MotorcycleDealer
          • MotorcycleRepair
        • ChildCare
        • Dentist
        • DryCleaningOrLaundry
        • EmergencyService
          • FireStation
          • Hospital
          • PoliceStation
        • EmploymentAgency
        • EntertainmentBusiness
          • AdultEntertainment
          • AmusementPark
          • ArtGallery
          • Casino
          • ComedyClub
          • MovieTheater
          • NightClub
        • FinancialService
          • AccountingService
          • AutomatedTeller
          • BankOrCreditUnion
          • InsuranceAgency
        • FoodEstablishment
          • Bakery
          • BarOrPub
          • Brewery
          • CafeOrCoffeeShop
          • FastFoodRestaurant
          • IceCreamShop
          • Restaurant
          • Winery
        • GovernmentOffice
          • PostOffice
        • HealthAndBeautyBusiness
          • BeautySalon
          • DaySpa
          • HairSalon
          • HealthClub
          • NailSalon
          • TattooParlor
        • HomeAndConstructionBusiness
          • Electrician
          • GeneralContractor
          • HVACBusiness
          • HousePainter
          • Locksmith
          • MovingCompany
          • Plumber
          • RoofingContractor
        • InternetCafe
        • LegalService
          • Attorney
          • Notary
        • Library
        • LodgingBusiness
          • BedAndBreakfast
          • Campground
          • Hostel
          • Hotel
          • Motel
          • Resort
        • MedicalBusiness(https://health-lifesci.schema.org/MedicalBusiness "Extended schema: health-lifesci.schema.org")
          • Dentist
          • Pharmacy
          • Physician
        • ProfessionalService
        • RadioStation
        • RealEstateAgent
        • RecyclingCenter
        • SelfStorage
        • ShoppingCenter
        • SportsActivityLocation
          • BowlingAlley
          • ExerciseGym
          • GolfCourse
          • HealthClub
          • PublicSwimmingPool
          • SkiResort
          • SportsClub
          • StadiumOrArena
          • TennisComplex
        • Store
          • AutoPartsStore
          • BikeStore
          • BookStore
          • ClothingStore
          • ComputerStore
          • ConvenienceStore
          • DepartmentStore
          • ElectronicsStore
          • Florist
          • FurnitureStore
          • GardenStore
          • GroceryStore
          • HardwareStore
          • HobbyShop
          • HomeGoodsStore
          • JewelryStore
          • LiquorStore
          • MensClothingStore
          • MobilePhoneStore
          • MovieRentalStore
          • MusicStore
          • OfficeEquipmentStore
          • OutletStore
          • PawnShop
          • PetStore
          • ShoeStore
          • SportingGoodsStore
          • TireShop
          • ToyStore
          • WholesaleStore
        • TelevisionStation
        • TouristInformationCenter
        • TravelAgency
      • MedicalOrganization
        • Dentist
        • Hospital
        • Pharmacy
        • Physician
      • NGO
      • PerformingGroup
        • DanceGroup
        • MusicGroup
        • TheaterGroup
      • SportsOrganization
        • SportsTeam
    • Person
    • Place
      • Accommodation
        • Apartment
        • CampingPitch
        • House
          • SingleFamilyResidence
        • Room
          • HotelRoom
          • MeetingRoom
        • Suite
      • AdministrativeArea
        • City
        • Country
        • State
      • CivicStructure
        • Airport
        • Aquarium
        • Beach
        • Bridge
        • BusStation
        • BusStop
        • Campground
        • Cemetery
        • Crematorium
        • EventVenue
        • FireStation
        • GovernmentBuilding
          • CityHall
          • Courthouse
          • DefenceEstablishment
          • Embassy
          • LegislativeBuilding
        • Hospital
        • MovieTheater
        • Museum
        • MusicVenue
        • Park
        • ParkingFacility
        • PerformingArtsTheater
        • PlaceOfWorship
          • BuddhistTemple
          • CatholicChurch
          • Church
          • HinduTemple
          • Mosque
          • Synagogue
        • Playground
        • PoliceStation
        • RVPark
        • StadiumOrArena
        • SubwayStation
        • TaxiStand
        • TrainStation
        • Zoo
      • Landform
        • BodyOfWater
          • Canal
          • LakeBodyOfWater
          • OceanBodyOfWater
          • Pond
          • Reservoir
          • RiverBodyOfWater
          • SeaBodyOfWater
          • Waterfall
        • Continent
        • Mountain
        • Volcano
      • LandmarksOrHistoricalBuildings
      • LocalBusiness
      • Residence
        • ApartmentComplex
        • GatedResidenceCommunity
      • TouristAttraction
    • Product
      • IndividualProduct
      • ProductModel
      • SomeProducts
      • Vehicle
        • Car

PHP 7.4 compatibility issue

I'm currently migrating to PHP7.4 (GA release will be on November, 28th) on my dev environment.
I get an error :
Function ReflectionType::__toString() is deprecated thrown on a $graph->organization() call

I think I've found a fixe, but not sure about this enough to make a PR :

$this->getOrCreate($type);

=>

$this->getOrCreate($type ? $type->getName() : null);

(in Spatie\SchemaOrg\Graph)

Build and release if rdfa changes

The package should get a new patch release everytime the rdfa changes. This could be done by hand but I think that it would be better to have a cronjob/CI doing the job.
It could be discussed that it should be a minor release instead of a patch one. Otherwise it could be an idea to use composer hooks to generate the types during local package installation and on composer update.

Make generator extensible for other Schema definitions

Not so much an issue, just a question.

I'd love to use this package but without the health-lifesci.schema.org extension I might need to roll my own. Is there a way for me to add schema extensions so I can benefit from using the MedicalOrganization type "Physician"?

Is it possible to somehow run your generator against that health-lifesci schema extension and generate a library of files in my project to augment your core files?

How do you fill a mainEntity array?

I'm following the example for an faq page: https://developers.google.com/search/docs/data-types/faqpage

The mainEntity here is an array with multiple definitions, How can I achieve this using the mainEntity function on the faqPage, in short how can I work with array data?

    <script type="application/ld+json">
    {
      "@context": "https://schema.org",
      "@type": "FAQPage",
      "mainEntity": [{
        "@type": "Question",
        "name": "What is the return policy?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "answer"
        }
      }, {
        "@type": "Question",
        "name": "How long does it take to process a refund?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "answer"
        }
      }

Type inheritance

https://github.com/spatie/schema-org#type-inheritance

Since the methods are callable and it's possible to know which methods are also available - wouldn't it be cool to have the methods from another type mentioned in the doc-tag?

Let's take the LocalBusiness in this package it extends the Organization but it should also extend Place this isn't possible without a massive refactoring but the place methods could be listed as @method.

/**
 * @method publicAccess(bool $value)
 * ...
 */
class LocalBusiness extends Organization
{
    // ...
}

Is this something you want to implement or do you want this to keep it like it is?

Graphing Multiple Schemas

First thank you for an excellent library. I cannot tell you what a help this has been. One item I don't see that you might want to consider is graphing of multiple schemas according to the JSON LD spec. Ive included very basic example, which btw works fine. I think that the ""@context":"http://schema.org"" context needs to moved up to the @graph level but you get the idea.

    /**
     * * Return string stripped of script tags
     * 
     * @param $string
     * @return string
     */
    public function stripScriptTags($string) :string 
    {
        return substr($string, 35, strlen($string)-44);
    }

    /**
     * Return string appended with script tags
     * 
     * @param $string
     * @return string
     */
    public function appendScriptTags($string) : string 
    {
        return "<script type=\"application/ld+json\">" . $string . "</script>";
    }

    /**
     * @param array $schemas
     * @param string $schemaString
     * @return string
     */
    public function makeGraph($schemas = [], $schemaString = "") : string 
    {
        foreach ($schemas as $key => $schema) {
            $schemaString = $schemaString .  
                // strip the scrip tags 
                $this->stripScriptTags($this->$schema()->toScript()) . 
                // append seperator unless last item 
                ( (count($schemas)-1) !== $key ?  ",": "");
        }
        
        return  $this->appendScriptTags('{"@graph":[' . $schemaString  ."]}");
    }

    /**
     * @return string
     */
    public function graphMultipleSchemas() : string 
    {
        return $this->makeGraph([
            'orgExample',
            'blogExample'
        ]);
    }

    /**
     * Example org schema
     * 
     * @return mixed
     */
    public function orgExample()
    {
        return Schema::organization()
             (...);
    }

    /**
     * Example blog schema 
     * 
     * @return mixed
     */
    public function blogExample()
    {
        return Schema::blog()
        (...);
    }

PHP 7.0 requirement is holding back some people form using this library

PHP 7.0 requirement is holding back some people from using this library.

We have almost .5GB of PHP source and upgrading to PHP 7.0 will probably take months of conversion that we simply cannot afford at this time.

I know sometimes developers get focused on new shiny objects and want the latest and greatest version but many of us running apps in a business cannot simply upgrade to newer version easily.

Is PHP 7.0 really necessary for a simple library to generate Schema?

disable StyleCI auto-fix PRs

@freekmurze it would make it easier if StyleCI doesn't auto PR fixes. These PRs are always closed but consume TravisCI builds and just bloat the repo.
Could you disable them in the StyleCI WebUI?

Use contracts in params

PHPStan sometimes gives errors like:

  31     Parameter #1 $provider of method Spatie\SchemaOrg\Course::provider()     
         expects                                                                  
         array<Spatie\SchemaOrg\Organization|Spatie\SchemaOrg\Person>|Spatie\Sch  
         emaOrg\Organization|Spatie\SchemaOrg\Person,                             
         Spatie\SchemaOrg\EducationalOrganization given.  

In this case EducationalOrganization is correct and implements OrganizationContract
It could be posible to change doc params to use Contracts instead?

drop unsupported PHP version support

@sebastiandedeyne Atm we support PHP >=7.0 but official only PHP >=7.2 is fully supported and 7.1 is in security only phase. So we could at least drop PHP7.0 support. And plan to drop PHP7.2 support end of the year.

Or should we support the lowest possible version for all times? This would increase the TravisCI build duration over time.

Breadcrumb listitem added twice

foreach($row['breadcrumb'] as $breadcrumb) {
       $arrTemp[] = Schema::listItem()
              ->addProperties(['position' => $i])
              ->item(
                     Schema::webPage()
                            ->name($breadcrumb['title'])
                            ->url($breadcrumb['url'])
                            ->addProperties(['@id' => $breadcrumb['url']])
              );
       $i++;
}
$this->objSchema->breadcrumblist()->itemListElement($arrTemp);

When I try to add itemListElement to the breadcrumbs with the code above it seems to be listed twice. Am I using the code wrong or is there some sort of bug?

Type inheritance hints via interfaces to allow type hinting in projects

I know, I'm late on the 2.x BC about type inheritance: I e.g. typehinted SchemaOrgEvent on some methods and now that e.g. a SchemaOrgLiteraryEvent is no longer of type SchemaOrgEvent the php typehinting breaks. Good you chose 2.0 release. ;-)

I wonder what your stance is on generating interfaces for the previously subclassed classes so code that is using this lib can typehint IsEvent (or similar) instead of deciding between nothing or BaseType.

I had a look at the old issues but am not sure whether this was an option. I understand there might be problems with the LocalBusiness having (some?) stuff from Organization and Place.

Errors with old style autoloading in legacy projects

Hello,

when using old style autoloaders in legacy projects Schema generating fails - reason: autoload fail. The problem lies in method_exists search from __toString method. method_exists() triggers autoload. In modern application based on composer autoload it is no problem. But in legacy projects with custom autoloaders it is huge problem.

Sample example:

<?php
use Spatie\SchemaOrg\Schema;

require_once './../vendor/autoload.php';

spl_autoload_register(function ($class) {

   require $class.'.php';

});

$localBusiness = Schema::localBusiness()->name('Spatie');

print_r($localBusiness->toArray());
Warning: require(Spatie.php): failed to open stream: No such file or directory

I understand that this autoloader is rather stupid example, but it shows the problem. This worked fine in version 2.0.* - method_exists was used only for objects (https://github.com/spatie/schema-org/blob/2.0.3/src/BaseType.php#L105)

The other solution would be to simple return string values at beginning. All those matches for interfaces for string are waste of time.

@id on BreadcrumbList

Hi!

Great package!
I've found one thing to consider. If you want to build a BreadcrumbList schema, it's not valid by Google because they want a @id parameter in the ListItem.

See: https://developers.google.com/search/docs/data-types/breadcrumb

<script type="application/ld+json">
{
  "@context": "http://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [{
    "@type": "ListItem",
    "position": 1,
    "item": {
      "@id": "https://example.com/books",
      "name": "Books",
      "image": "http://example.com/images/icon-book.png"
    }
  },{
    "@type": "ListItem",
    "position": 2,
    "item": {
      "@id": "https://example.com/books/authors",
      "name": "Authors",
      "image": "http://example.com/images/icon-author.png"
    }
  },{
    "@type": "ListItem",
    "position": 3,
    "item": {
      "@id": "https://example.com/books/authors/annleckie",
      "name": "Ann Leckie",
      "image": "http://example.com/images/author-leckie-ann.png"
    }
  },{
    "@type": "ListItem",
    "position": 4,
    "item": {
      "@id": "https://example.com/books/authors/ancillaryjustice",
      "name": "Ancillary Justice",
      "image": "http://example.com/images/cover-ancillary-justice.png"
    }
  }]
}
</script>

I did not want to create a PR, because I do not exactly where this @id element should be assigned. It's not documented in schema.org, I think.

Possible solution is to add a method on Thing.php:

    /**
     * id parameter for BreadcrumbList for example
     *
     * @param string $id
     *
     * @return static
     */
    public function id($id)
    {
        return $this->setProperty('@id', $id);
    }

Other solution is to create a new schema class BreadcrumbListItem::class and put the @id property in there with extension of ListItem::class

Looking forward to your answer and happy coding! ๐Ÿ‘

Possible to adapt logo json markup according to Google guidlines?

Hello,

today I ran into an issue with the json markup from a news article. Google testing tool complains about the logo because the type "@type": "ImageObject" will not be set.

This is what I get as output:

"logo":"http:www.xxxxxxxxxxxxx.png"

but Google wants it in that kind of format:

"logo": {
      "@type": "ImageObject",
      "url": "https://google.com/logo.jpg"
    }

I add the logo to the Schema.org type like this:

->logo("http:www.xxxxxxxxxxxxx.png")

So is it possible to enrich the logo markup with the type attribute and how?

Best regards

Implementation of schema.org/Date

Hey,

First of all, thanks for the lib! :)
Now, I'm curious if there's a special reason why the Date object has not yet been implemented. If there's no reason I'm happy to contribute that because I could make use of it in my project.

Best

[RFC] Do not generate null values

Introduction

I suggest we make a simple change in the library (maybe even with a flag?) where BaseType during dump (or even in setProperty()) simply ignores null values or

Current status

As of now setting a null value on a field will cause the field to appear in the JSON-LD with null value.

Reasoning

Mainstream tools seems blind to nulled fields like they never existed:
image (2)

This change would greatly improve DX, so that setters can be blindly called without ->if()ing for everything. Such code as below:

$mapLink = $this->gmapsFactory->linkFromGeo($company->getGeolocation());
$schema->if($mapLink !== null, function(LocalBusiness $schema) use ($mapLink): void {
    $schema->hasMap($mapLink);
});

Could be reduced to:

$schema->hasMap($this->gmapsFactory->linkFromGeo($company->getGeolocation()));

WDYT?

Instantiate classes with array of properties

Either I'm missing it or it doesn't exist; it'd be nice to instantiate the classes with an array or properties which are then mapped to the class properties, for example:

$brand = Schema::Brand([
            'name' => "The name of this brand",
            'slogan' => "All the branding all the time.",
            'description' => "We're not the best brand but by god we get results.",
        ]);

or..

$brand = new Graph();
        $brand->brand([
            'name' => "The name of this brand",
            'slogan' => "All the branding all the time.",
            'description' => "We're not the best brand but by god we get results.",
        ]);

Field geo for Hotel missing

Although https://schema.org/Hotel has a field "geo" it does not exist in this library (comes from Place). Is it because of PHP not supporting Multi Inheritance? If yes, perhaps traits could be used to better reflect schema.org's structure.

PS: Also applies for smokingAllowed.

Array type hints

Not a bug, but a suggestion:

"SameAs" should accept an array (which does work) but the property should be changed in the php doc block to reflect this. Currently it says this type is not expected but it still outputs properly.

            ->sameAs([
                    "https://www.facebook.com",
                    "https://twitter.com"
            ])

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.