-
Notifications
You must be signed in to change notification settings - Fork 207
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JsonLd Implementation #1551
Comments
in general: i think the jsonld implementation is very strong argument for using luya, therefore this should be as less pain as possible for developers to integrate. Your solution is very close to what i think should be done. General Elementshortform: $person = new Person(['firstname' => 'John', 'lastname' => 'Doe', 'email' => 'john@luya.io']); which is equals to:
All jsonld items should contain
There for we need a base class like
ChainingA very powerfull option is chaining elements, therefore the element can return the available chain objects (assuming an event can have locations): class Event extends BaseElement
{
// general event attributes ...
private $_locations = [];
// as now $this->locations is an arrayable element, from baseElement
// the group with the attribute key 'locations' should be build correctly.
public function setLocation(array $options = [])
{
$this->_locations[] = return new Location($options);
}
public function setLocations(array $locations)
{
foreach ($locations as $locationData) {
$this->setLocation($locationData);
}
}
public function getLocations()
{
return $this->_locations;
}
// to array implementation would be then:
public function fields()
{
return ['locations'];
}
} So a full example could look like this: $event = new Event();
$event->endDate(strtotime("+3 weeks"));
$event->location()
->address('Bahnhofstrasse 27')
->zip(5000)
->city('Zürich'); or as object array config notation: $event = new Event([
'endDate' => strtotime('+3 weeks'),
'location' => [
'address' => 'Bahnhofstrasse 27',
'zip' => 5000,
'city' => 'Zürich'
]
]); What do you think? |
Okay, I can give it a try in the evening / tomorrow ;) |
@JohnnyMcWeed i just updated the chaining text a bit in order to show the different usage types. |
I changed the code (https://github.com/JohnnyMcWeed/luya/tree/JsonLd/core) Can be used like this (All pass https://search.google.com/structured-data/testing-tool):
What do you think about it? |
@JohnnyMcWeed toArray should be invoken by addGraph. Which should then auto call toArray inside json::encode function: https://github.com/yiisoft/yii2/blob/master/framework/helpers/BaseJson.php#L156 |
General Inputs:
So maybe we should just use: $event = new Event();
$event->setLocation()
->address('Bahnhofstrasse 27')
->zip(5000);
$event->setLocation()
->address('Another Street')
->zip(4600); |
Instead uf override default logic (https://github.com/JohnnyMcWeed/luya/blob/JsonLd/core/base/JsonLdBaseElement.php#L90) why not just return the fields array from arrayable interface? should i make a full example? I think we are very close to a good solution! (btw: here some luya coding rules: https://luya.io/guide/luya-guideline using psr2, etc.) |
So probably misunderstood what you wanted to have. Adjusted the chain a little bit. Before we had a chain on the same element so we could go through it's properties, but not down to newly created child elements. Now the chain takes the newly created objects as return so that they can be filled. Moreover you can set switches to go back to the parent element to set more information. Changed context to get merged in at the end. Do you mean something like that? Example 1: Anna has 2 children So back to your example, we can adjust it so it ends up as something similar to this (or as you mentioned):
|
First of all, thank for taking time helping make luya better! I think you chaining example is far to complex, and hard to understand (with back() function). Of course at some point, chaining does not allow you to get back, but understanding the mechanism you can always go back by using the variabled object: $event = new Event();
$event->setLocation()
->address('Bahnhofstrasse 27')
->zip(5000);
$event->setLocation()
->address('Another Street')
->zip(4600); so $event is variable you can always "go back". I just pushed a commit with the basic implementation and also an unit test, you can now use this as your basic setup and also directly add unit tests |
Hmm... I don't really think it was hard to understand as long as it is well explained, but it enhances the possibility way more on how to use it.
So finally the main difference is that in your case you must have a variabled object, in mine you don't need this. So it's only more flexibility I think. Other point we need to check: How do you want to pass variabled object?
|
Maybe we should not use chaining then and make this possible: $event = new Event();
$location = new Location();
$address1 = new Address();
$address2 = new Address();
// new we have all objects and pass all child infos.
$location->setAddress($address1);
$location->setAddress($address2);
$event->setLocation($location); this way we do not mix up things, and have a straight forward implementation. |
Hmm... Or let's change the function to something like this:
|
Maybe its better to start simple and just allow to the setter for the given object, this is pretty straight forward implementation and also very readable api. public function setEvent(Event $event)
{
$this->_events[] = $event;
} It will also not bloat our classes with if/else codes and follows more the yii 2 philosophy with getter and setters |
The reason why I came up with my switches solution: |
Let's start with the straight forward solution i made, when can then still add a helper class for making complex chainings. Like JsonLd::chain()->event()
-> etc.
-> etc. so we have a small a maintainable code base but can extend dynamic. Why using the straight forward implementation:
|
Sounds good to me. What do you think, should I do it with traits? |
So you mean Organisation and Place would be a trait? Yes good idea, but the trait only contains the getter and setter methods and not the fields defintion. trait PlaceTrait
{
setXYZ($value);
getXYZ();
}
class Place extends BaseGraphElement
{
use PlaceTrait;
public function fields()
{
return ['xyz'];
}
} I also think we should rename Just delete your luya repo and fork again, so you can start straight from my code and send a first PR reference to this issue. |
All methods as traits so they can be reused was my idea. All methods will be stored in traits which are called like the things. Something like that:
I'll leave this branch as it is now.. maybe there's something reusable for the chain helper... Update the repo and start at you point ;) |
Ok, as long as the traits only contains the getter/setter methods and not the fields() defintion. btw: maybe BaseThing could contain some extra variables/methods which have to ensure the |
I'll continue in about two weeks ;) What were you thinking about with the following:
An array with all elements and a check with "in_array()"? |
I was thinking about how to implement @context and @type etc. (https://github.com/luyadev/luya/blob/master/core/web/JsonLd.php#L37-L38) i think @context could be statically added when passing the data to the view, somewhere here: https://github.com/luyadev/luya/blob/master/core/web/JsonLd.php#L109 Maybe i have time to start already with the basics until then, as we would like to introduce the "final" api until 12.12.2017 und release version 1.0.0 |
Alright :) In my last example I did an array_merge($objectArray, ["@context" => "http://schema.org"]), which was working properly. I think @type as property was good before, as it changes with all types. So if you'd like we can make a check if that property is in an array with all possible objects. But I'm not sure if this is really needed, as the user of this class doesn't have to touch that property at all as it is preset by the object. |
Moreover @type could be constants I think.... |
If every BaseThing must implement a type (which i don't know, but i assume this is the case) we could make an abstract method in BaseThing |
@JohnnyMcWeed i implemented the basic json ld usage and tested with unit tests. So now we can proceed implementing traits, things and constants. |
Maybe its a good idea to use an interface for things, for example assume we would have a $model = PersonModel::findOne(1);
JsonLd::person($model); otherwise you have to bind those values like: $model = PersonModel::findOne(1);
JsonLd::person(['firstname' => $model->firstname]); // ... etc. (just thinking loud ;-)) |
Progress looks good, i think only 2 things are missing:
|
Hey
As this part is not implemented yet, I wanted to ask you what you're thinking about the following idea:
Using objects for the schema things and methods to build them, then through JsonLd we can register them. As we can't extend classes, we could use interfaces to make sure all properties are implemented to use.
What do you think?
Had some time to make an example to explain it better ;)
Here is a working example: https://github.com/JohnnyMcWeed/luya/tree/JsonLd/core/web
Could be used like this:
\luya\web\JsonLd::addGraph( (new \luya\web\jsonld\Person())->name("Max")->toArray() );
\luya\web\JsonLd::addGraph( (new \luya\web\jsonld\Organisation("LuyaDev"))->toArray() );
\luya\web\JsonLd::addGraph( (new \luya\web\jsonld\Organisation("Others") )->member( (new \luya\web\jsonld\Person("Moritz"))->toArray() )->toArray());
The text was updated successfully, but these errors were encountered: