I am using Laravel resource controller with route model binding in my API development project. I have below code
public function show(Post $post)
{
return $post->comments()->get();
}
I am using below URL
http://127.0.0.1:8000/api/posts/1
I would like to retrieve both post values with comments value.
But I am getting only comments values.
Did you try Eloquent load aka Lazy Eager Loading https://laravel.com/docs/5.6/eloquent-relationships#lazy-eager-loading
Sometimes you may need to eager load a relationship after the parent model has already been retrieved. For example, this may be useful if you need to dynamically decide whether to load related models:
In your case would be something like
$post->load('comments')
You should have your relationship in your models "Post", "Comment" and get of the next shape.
$post->comments;
If you don't have the relationship in your models you should post your models in this answer pls.
If you have the relationships set in both models, just sending the post will load the post and the comments
Related
I am working on a REST-API and have run into an architectural problem.
The model 'Book' represents a single book with properties and CRUD-based functions. It loads itself from a database via a read function.
However, what if I want to get all books in the database? The current book model does not cover this use case.
I have tried several approaches:
1.) A second model called 'Books'. It has a read function which returns a list of book objects.
2.) The model 'Book' itself has a readAll function which loads all books.
3.) The model 'Book' is non-functional, it only has properties. Instead a 'BookStorage' class loads the data and fills one/multiple models.
I am not satisfied with any of these approaches. Is there a best practice for this scenario?
1.) A second model called 'Books'. It has a read function which returns a list of book objects.
This is okay, but users and future developers on the project may be unclear on the fact that you have both Book and Books. So be sure to document the API, and comment the code. Also, you do need to consider input filters to limit down the results, or at least a method to page results. Google once estimated there were 130 million books, so you want to get all of them at once?
e.g. SERVER/Books/?skipRecords=0&limit=100
2.) The model 'Book' itself has a readAll function which loads all books.
This is not ideal as it violates the single responsibility principal. Mostly it just doesn't make a lot of sense in an OO situation to have a single book entity be able to list all of it's sibling entities.
e.g. SERVER/TheHobbit/readAll.... yuck.
3.) The model 'Book' is non-functional, it only has properties. Instead a 'BookStorage' class loads the data and fills one/multiple
models.
If you can expose these functional extension via the API, then that is an fine solution as well. It all comes down to documentation.
Maybe it ends up looking like this
e.g.
SERVER/BookStorage/GetAllBooks?skipRecords=0&limit=100
SERVER/BookStorage/GetBook?title=TheHobbit
3.) The model 'Book' is non-functional, it only has properties. Instead a 'BookStorage' class loads the data and fills one/multiple models.
This approach is similar to the Repository Pattern and is very common. The BookStorage would be a BookRepository with an interface like:
public interface IBookRepository
{
Book GetById(int id);
IEnumerable<Book> GetAll();
// Other methods for creating, updating and deleting books.
}
In your controller you would then have:
public class BooksController: ApiController
{
private readonly IBookRepository _bookRepository;
public BooksController(IBookRepository bookRepository)
{
_bookRepository = bookRepository;
}
[Route("api/books/{id}")]
public IHttpActionResult Get(int id)
{
var book = _bookRepository.GetById(id);
// ...
}
[Route("api/books")]
public IHttpActionResult Get()
{
var books = _bookRepository.GetAll();
// ...
}
}
If you want paging, you would add a filter like Get(int page = 0) and then depending on your page size, use something like bookRepository.GetAll().Skip(PAGE_SIZE * page).Take(PAGE_SIZE).
A model should not load itself as it would violate the Single responsibility principle.
A great resource when designing RESTful webservices is Martin Fowler's article Richardson Maturity Model.
To summarise for your book case:
use POST /book to create a book
use PUT /book to update a book
use GET /book?author=Shakespeare&year=1602&someOtherParam=someValue to find books
use GET /book/:id to retrieve the details of a particular book
use DELETE /book/:id to delete a certain book
Also you might want to follow the HATEOAS principles, so you'll need to include all relevant links for a book into a links property, so that clients of your API will not need to build their own link when they'll want to add/edit/find/delete a book.
Although simple at first sight, designing a good RESTful webservice is not that easy, however HATEOAS helps because url schema changes on the server side don't affect clients as they don't hardcode the URL's needed for the CRUD operations. All you need to do is provide a starting point, e.g. a base url where all contents can be discovered, and clients can start from there navigating through your webservice.
Read the CRUD Operations section here. You will find REST best practices to be followed when designing a REST API
I would like to make an application with backbone.js I understand the basics of backbone however I dont really know what the right approach to my problem might be.
I have a big jsonp file that is being retrieve from the server. So the next step would be to put the data from the jsonp file into a model. The data is bloglike containing a imgurl/title/text.
Now I could start a new model like this:
new modelVar = new BackboneModel;
However would that means that I need to create a new variable for every post I want to retrieve or could I let backbone create a set of models containg the post data.
Any suggestions book / blogs are welcome
Thanks
A quick answer could be "no". You can let Backbone loading data in models using a Backbone Collection.
E.g.
new App.Photos([
{url:"http://(...)_1.png", title:"photo1"},
{url:"http://(...)_2.png", title:"photo2"},
{url:"http://(...)_3.png", title:"photo3"}
]);
You just have to get an array of objects in argument when you create your collection prototype. Backbone will automatically create models based on the model attribute defined into the collection object. It's particularly fitted to your needs because you just have to put in argument the parsed json response and your models will be created.
I suggest you Backbone Marionette which is a good choice to start with Backbone implementation in order to get best practices.
https://github.com/derickbailey/backbone.marionette
I have an Entity called "Product", this entity, through table mapping, merges 6 tables that have a 1 to 1..0 relationship with "Products". This all works wonderfully. There is another property I want to add to "Products", which is sBBR_rate, this value is not in a table that has a direct 1 to 1..0 relationship, it is related through a link table as below:
When I import the two tables into the EDM, I can't see a way in the "Mapping Details" of
"Product" to reference the sBBR_rate. I can reference RatesLink and link that to the "Products" primary key, however, I cannot reference the BBR table.
The methods I can think of to work "around" this is are as follows:
Create a view, reference the view in the EDM.
Create an SP and use a function import to retrieve the BBR when it is required.
Create a "Rates" entity in the EDM that can then draw down the sBBR_rate into it. Navigate to the Products BBR through Product.Rates.sBBR_rate.
Is there a better way I can do this that doesn't feel so much like a fudge? Perhaps by directly editing the XML of the Mapping or Conceptual layers of the EDM?
Thanks for your input.
Because the multiplicities on the Product -> RatesLink and RatesLink -> BBR relationships are 0 to 1, you should be able to access the sBBR_rate from a Product instance like this:
myProductInstance.RatesLink.BBR.sBBR_rate
I can see on the EDM screenshot that RatesLink has a Product and BBR property, which would indicate this should be available - is it?
On a side note, if it makes sense for the sBBR_rate property to commonly be accessed directly from Product, you might want to follow the law of demeter and create a property on Product which returns it directly.
The model we are using is to extend entities by using partial classes which we've found useful so we can get additional properties in the autogenerated classes (we are using a POCO T4 template to autogen but I believe this would work just as well with the default entity object generation).
So we would have
//.. this one is from the T4 template
public partial class Product
{
//.. all the autogenerated methods
}
and in a separate file that isn't autogened
//.. now in a separate file created by me
public partial class Product
{
//.. my custom properties and methods to make the entities more usable
public string BBRRate
{
get {return this.RatesLink.BBR.sBBR_rate; }
}
}
This means that I can just do
myProduct.BBRRte
I know there are other ways to do this by amending the edmx file but this one we found easy to implement. You just need to watch performance because you are potentially loading extra data. Also we did this with LazyLoading turned on but with more work you wouldn't have to
We also experimented with hooking into the ObjectMaterialized event in the ObjectContext class to preload some of these properties. Using a custom interface i.e. IMaterialisable we could check if the object was of that type then call a method (Materialise) to prepopulate some of the properties. This seems like a good idea but we didn't widely use it - it was easy to load up too much stuff. If you do the load on the properties in the partial classes then it becomes more efficient. Just my experience.
Anyway - as always an interesting question and good luck again with your dev.
EDIT
There is a rule that everything in the store layer must be represented some way in your conceptual layer. Therefore removing the tables from the conceptual layer but bring through some of the properties I don't think will work in it's gross form. Therefore I can think of two further options
Create a View on the database and bring that in as you have already mentioned. TBH this is what I would do.
Use the DefiningQuery element directly in your xml (the store layer) and map the query through to a custom entity of your exact design. Julie Lerman describes this as the ultimate escape hatch for Entity Framework.
Remember though - if you manual amend the XML in point 2 then you lose the ability to automatically update the module through the IDE
I ended up creating a view and then linking this view in the EDM, this worked a treat.
Doctrine 2 integration into ZF seems to make simple things very hard and time consuming(At least for me).
I cant just give a submitted form array to doctrine to automatically map key/value pairs to doctrine entities and it gets very complicated if i have a many-to-many entity and submitted form has nested array.
In symfony, submitted form keys/values are easily and AUTOMATICALLY mapped and saved to doctrine tables. I don't know how to do that in ZF especially if I have "Many to Many" and/or "Many to One" doctrine entities and I have **nested form elements which need multi-level iteration.
I don't want to Set every entity explicitly and create every entity object manually**.
Pain would be alot less if i used ZF`s native database architecture.
I have done some coding and now its done half-automatically but is not very useful.
I think the best solution is to use PHP's Reflection API to inject/retrieve values from your entities (using smart get/set detection as well). I started a little library called ObjectSerializer to help with the process but never finished. That said, if you look at the logic contained in these two classes you might get a good idea where to start.
You should program this sort of logic into your models.
I usually add this sort of logic into my form, for example
class Application_Form_SomeModel extends Zend_Form
{
// the usual stuff
public function populateModel(\Entity\Model $model)
{
$model->setSomething($this->getValue('something'));
$subForm = $this->getSubForm('name');
$relatedModel = new \Entity\RelatedModel;
$relatedModel->setSomething($subForm->getValue('something'));
$model->getRelatedModels()->add($relatedModel);
// assuming the related model collection has cascade persist
// otherwise you'll need to pass in the entity manager to persist
// the new model
}
}
I do it this way due to the fact the form's elements are really only known to the form. This allows you to encapsulate everything to do with the form and its element names within the form without having to assume anything else knows this information.
I'm after some opinions \ best practice for handling updates to my repository in the following scenario:
I am using EF 4 with the POCO tt templates which creates nice clean clr objects.
For example's sake lets say I have a POCO object name Customer and a ViewModel called CustomerViewModel. CustomerViewModel has a public property for the Customer object which is populated with the POCO Customer object.The view references the Customer object on the CustomerViewModel. So far so good. Everything is displayed as expected.
When it comes time to update the CustomerViewModel is passed back and only the properties that were bound to the view are populated, fair enough.
What I have now is a POCO object that is missing some of the property values which are needed to update via the EF data context. For example, since I did not display the ID in the view, it was not hydrated back into the view model's Customer property. Not really surprising behaviour but I am wondering what the best way to handle this scenario is.
So here is the question:
Would it be better to map the properties that i don't display into hidden fields so that I have the complete POCO object on postback which is ready for updating to the Repository? (I'm thinking there is needles sending of data to and from the client here)
OR should I do a read of Customer before my update(assuming I have the ID) and then update the properties from my view model object. ( is this a needles read on the database ?).
OR is there another may altogether that I am missing.
I realise that maybe there is no one correct answer for this but I'd be interested to hear how others are handling this scenario.
Thanks
I'm going to answer my own question here... maybe it was a silly question but the act of writing it out has made the answer more obvious..
The first option of populating hidden fields is a bad idea for too many reasons!! So I think I'll have to go with doing a read of the customer object on the post back and calling.
TryUpdateModel(customer, "Customer");
Where customer is the freshly read Customer and "Customer" is the property name on the view model.
It seems that this results in more data access than in a classic ASP where the object could have been shoved (rightly or wrongly) into Session !
Anyone care to add their 2c ?