cloudcreativity/laravel-json-api

Override model save method

ale1981 opened this issue · 15 comments

I need to use a stored procedure to save records to the database, which method should I override and how do I access the attributes from the POST route?

You'll need to look at the adapter class. The entry points are the create() and update() methods. However if you look at the implementation in the parent classes, you might find there's an internal method that you can override depending on your use case. E.g. both those methods end up calling persist() internally.

The JSON document is passed to those methods so you have access to it. If you need anything else from the request, use Laravel's request() helper.

Hi @lindyhopchris, thanks for the reply.

Looking at the adapter class, persist() just calls the model save()?

Yes, but it's in there as a separate method so developers can overload it if required.

Yes. In the persist() method I am struggling to get the attributes from the $record as they seem to be empty?

Does anything need to be returned from the persist() method, once it runs I get an empty record returned by the API.

The attributes are filled into the model by that point. So you should be able to get them from the record. If you're not, you'll need to investigate what about your set up is causing the attributes to not be filled. For instance, they need to be fillable on the model.

Thanks, it seems I needed to alter $guarded in the Adapter.

I now have the stored procedure working and the record is being created in the database, however the API response shows an empty record, what could be causing that?

Don't know - you'd need to debug. By empty, if you mean the data member is null then it isn't being returned from somewhere. If you mean the attributes are empty, then that might be down to your persistence implementation. Can't really say for sure, depends on your implementation which is why you'd need to debug.

I am struggling to debug.

The data member is populated, just all the attributes are empty, it's like the newly created record hasn't been loaded in the response but I have no idea where this is set.

The newly created record is returned from the create method on the adapter. It obviously works normally, so my guess would be that it's related to whatever this other stored procedure method is that you have? You'd need to make sure the correctly persisted model is returned from the adapter's create() method.

Sorry to not be more help - it's impossible for me to provide detailed guidance as I don't know what you've changed and don't have access to your application to debug.

The created record is obtained in the controller here:

$record = $store->createRecord(

That's getting it via the store, but all the store does is call the method on the correct adapter. So you need to make sure a fully completed and persisted model is returned from your adapter's create() method.

I appreciate your help.

I tried this from a different angle and left the JSON API methods alone and tried to override the insertAndSetId() method on the Laravel model, all that does as far as I can tell is insert in to the DB and set the returned ID, which I did, but get the same result, the returned model has empty attributes.

Is there a requirement to set every attribute via the data object when calling the POST route or can some be omitted?

Have no idea what you mean by the data object? Obviously the attributes would need to be set on the model, otherwise they won't appear when your schema serializes the attributes in its getAttribute() method.

Are the attributes fillable on your model? Have you debugged what happens when the adapter fills them?

Does the model have the attributes set when it is being serialized in the schema's getAttribute() method? Is the model in that method the one that has been saved to the database?

I really can't help much more I'm afraid. The package obviously works, it's used in production applications. So not sure what is going on with yours - and without access to the application, I can't really help. (To be clear, I'm not asking for access to the application - it's more that I'm reliant on what you can debug.)

Thanks for your help. I managed to debug and get this working.

The issue was the $attributes names being populated by the model in uppercase but the adapter was expecting them in lowercase, hence why they were null.

One last question...! Is there a way to manually raise an error in the API response, the stored procedure can return some different errors and wondered if I can display these to the user?

Great, glad you got it sorted.