Coder Social home page Coder Social logo

Comments (12)

GregPeden avatar GregPeden commented on July 20, 2024

Okay, so first of all... DERP. I was using a performance-saving tip from the demo project which requires a Larvel belongsTo relationship. Obviously this is not that!

So the 'address' and 'addressable' relationship data should just reference the Laravel relationship directly.

Now I am working on a new error:

InvalidArgumentException: Schema is not registered for a resource at path 'building.address'. in /home/vagrant/Code/hoistway-cms/vendor/neomerx/json-api/src/Encoder/Parser/Parser.php:271

Error occurs here:
https://github.com/neomerx/json-api/blob/9acd6091fb74c9a2376ff8cd1a9613b89be353eb/src/Schema/Container.php#L146

from laravel-json-api.

lindyhopchris avatar lindyhopchris commented on July 20, 2024

hi. that new error you are getting indicates that whatever your buildings resource is returning in the data of its address relationship isn't an object class that has a schema registered. do you know what class of object it is returning?

from laravel-json-api.

GregPeden avatar GregPeden commented on July 20, 2024

Well the relationship is "morphOne" intended for polymorphic relationships. The object returned is an Address. Does it have something to do with the relationship being nested?

Here is a log dump.

[2017-04-23 16:44:02] local.INFO: Building relationship: {"building":"[object] (App\Models\Building\Building: {"id":2,"name":"Fake Building"})","address_relationship":"[object] (Illuminate\Database\Eloquent\Relations\MorphOne: {})","address":"[object] (App\Models\Address\Address: {"id":16,"addressable_id":2,"addressable_type":"buildings","city_id":10344,"street":null,"street_extra":null,"postal_code":null,"email":null,"phone_mobile":null,"phone_desk":null,"phone_company":null,"phone_fax":null,"latitude":"51.0486151","longitude":"-114.0708459","place_id":"ChIJ1T-EnwNwcVMROrZStrE7bSY","created_at":"2017-02-19 17:57:26","updated_at":"2017-02-19 17:57:26","city":{"id":10344,"country_id":"CA","country_division_id":1,"name":"Calgary"},"country":{"id":"CA","name":"Canada","division_title":"Province","postal_code_title":"Postal Code"},"division":{"id":1,"country_id":"CA","code":"AB","name":"Alberta"}})"}

from laravel-json-api.

lindyhopchris avatar lindyhopchris commented on July 20, 2024

I'm not totally sure I understand the log dump. Isn't that saying thataddress_relationship is a MorphOne object?

from laravel-json-api.

GregPeden avatar GregPeden commented on July 20, 2024

Yes that is correct. That is how a one-for-one polymorphic relationship is defined.

from laravel-json-api.

lindyhopchris avatar lindyhopchris commented on July 20, 2024

Sorry, probably wasn't clear from my answer! Are you returning the MorphOne object as the data element of the relationship? The exception is saying that there is no schema registered for the value that is being returned... so you're returning something that isn't an address model.

Do you get the same error if the address relationship in the buildings schema is changed from this:

            'address' => [
                self::SHOW_SELF => true,
                self::SHOW_RELATED => true,
                self::DATA => isset($includeRelationships['address']) ?
                    $resource->address : $this->createBelongsToIdentity($resource, 'address'),
            ],

to this:

            'address' => [
                self::SHOW_SELF => true,
                self::SHOW_RELATED => true,
                self::DATA => $resource->address,
            ],

I'll be honest, this is a little bit difficult to debug from afar!

from laravel-json-api.

GregPeden avatar GregPeden commented on July 20, 2024

I apologize for misunderstanding. Your first version above is how I had it in the first place which created the first error. I changed it to the second example of yours, which led to the second error - it seems like progress, but not enough.

From the event that is fired when a Device is created/updated/deleted, this is where the logging is occurring.

    public function broadcastWith()
    {
        Log::info('Device event:', ['class' => self::class, 'data' => $this->device]);
        Log::info('Building relationship:', ['building' => $this->device->building, 'address_relationship' => $this->device->building->address(), 'address' => $this->device->building->address]);

        $this->device->load('building', 'type');
        $output = Encoder::instance([
            Device::class => Devices\Schema::class,
            Building::class => Buildings\Schema::class,
            DeviceType::class => DeviceTypes\Schema::class
        ])->serializeData($this->device, new EncodingParameters(['building', 'device-type']));
        Log::info('Output:', ['response' => $output]);
        return $output;
    }

And Devices\Schema, this is the root of this request. So, the device Broadcast event is including Building, and implicitly checking the Address relationship. If I just remove the Building relationship include, then the event broadcast works.

<?php

namespace App\JsonApi\Devices;

use App\Models\Building\Device;
use CloudCreativity\JsonApi\Exceptions\RuntimeException;
use CloudCreativity\LaravelJsonApi\Schema\EloquentSchema;

class Schema extends EloquentSchema
{

    /**
     * @var string
     */
    const RESOURCE_TYPE = 'devices';

    /**
     * @var array
     */
    protected $attributes = [
        'designation',
        'group',
        'licence',
        'slug'
    ];

    /**
     * @return string
     */
    public function getResourceType()
    {
        return self::RESOURCE_TYPE;
    }


    /**
     * @param object $resource
     * @param bool $isPrimary
     * @param array $includeRelationships
     * @return array
     */
    public function getRelationships($resource, $isPrimary, array $includeRelationships)
    {
        if (!$resource instanceof Device) {
            throw new RuntimeException('Expecting a Device model.');
        }
        return [
            'building' => [
                self::SHOW_SELF => true,
                self::SHOW_RELATED => true,
                self::DATA => $resource->building,
            ],
            'device-type' => [
                self::SHOW_SELF => true,
                self::SHOW_RELATED => true,
                self::DATA => isset($includeRelationships['device-type']) ?
                    $resource->type : $this->createBelongsToIdentity($resource, 'type'),
            ],
        ];
    }
}

from laravel-json-api.

GregPeden avatar GregPeden commented on July 20, 2024

I added a log output to Buildings\Schema to make sure it can access the address relationship properly, which it can. I also wondered if maybe it had to do with pluralization of "address" as it is an odd case, but it seems to work, at least on Laravel's end.

As you would expect, If I comment out the data input like then it completes execution without an error.

    public function getRelationships($resource, $isPrimary, array $includeRelationships)
    {
        if (!$resource instanceof Building) {
            throw new RuntimeException('Expecting a Building model.');
        }

        Log::info('Address test:', ['address' => $resource->address, 'plural' => str_plural('address'), 'singular' => str_singular('addresses')]);

        return [
            'address' => [
                self::SHOW_SELF => true,
                self::SHOW_RELATED => true,
                //self::DATA => $resource->address,
            ],
            'devices' => [
                self::SHOW_SELF => true,
                self::SHOW_RELATED => true,
                self::DATA => function () use ($resource) {
                    return $resource->devices;
                },
            ]
        ];
    }

[2017-04-24 05:04:58] local.INFO: Address test: {"address":"[object] (App\Models\Address\Address: {"id":16,"addressable_id":2,"addressable_type":"buildings","city_id":10344,"street":null,"street_extra":null,"postal_code":null,"email":null,"phone_mobile":null,"phone_desk":null,"phone_company":null,"phone_fax":null,"latitude":"51.0486151","longitude":"-114.0708459","place_id":"ChIJ1T-EnwNwcVMROrZStrE7bSY","created_at":"2017-02-19 17:57:26","updated_at":"2017-02-19 17:57:26","city":{"id":10344,"country_id":"CA","country_division_id":1,"name":"Calgary"},"country":{"id":"CA","name":"Canada","division_title":"Province","postal_code_title":"Postal Code"},"division":{"id":1,"country_id":"CA","code":"AB","name":"Alberta"}})","plural":"addresses","singular":"address"}

from laravel-json-api.

GregPeden avatar GregPeden commented on July 20, 2024

Closed by mistake only.

from laravel-json-api.

lindyhopchris avatar lindyhopchris commented on July 20, 2024

So your error is in your broadcaster. When creating the Encoder, there's no schema for the address model in the array you're passing in.

from laravel-json-api.

GregPeden avatar GregPeden commented on July 20, 2024

OOHHHHHHHHHHH! Got it. Thanks for your help!

To keep things simpler, I have just used the config file as so:

return Encoder::instance(Config::get('json-api.schemas.defaults'))->serializeData($this->device, new EncodingParameters(['building', 'device-type']));

Maybe the Encoder constructor could default to just looking up the schemas from the config file?

from laravel-json-api.

lindyhopchris avatar lindyhopchris commented on July 20, 2024

I'm going to do a broadcaster trait that allows you to load the encoder using the api name that's in the config file. That should make it easier. Glad we got your immediate problem solved!

from laravel-json-api.

Related Issues (20)

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.