I'm new to cakePHP and trying to get my head around when something is best developed as a Model/Behavior or Controller/Component.
I have an athletics scheduling system where various types of data, such as Venues, Schools, and Divisions get assigned to Sports. Taking Venues as an example: Venue and Sport have a HABTM association. I will be building a tool which allows users to select a Sport, and in so doing, view the Venues assigned to the Sport (list A), as well as the Venues that have not been assigned to the Sport (list B). They can then delete assigned venues (from list A) or add unassigned venues (from list B). A pretty basic tool which I know how to code in PHP. I have several of these same "assignment" tools throughout the app, which is why I want to abstract out.
I originally thought of building a Component, allowing me to get the two lists, and perform the adds & deletes, but am now wondering whether I can fatten my Models by creating a Behavior. I'm just a little lost conceptually, and would appreciate any clarification.
CakePHP has the "Fat models, skinny controllers" motto. Your models/behavior should do all the heavy lifting and take care of all data manipulations. What you explain definitely belongs in a a custom model function or behavior.
Related
We have a WPF desktop application that uses MVVM pattern and DDD (well, let's say that at least my model classes that store data named by entities taken from the real world). APP uses several microservices through REST API. And it worked perfectly. Until we thought that it's time to use some facade for back-end part to unite all those microservices and get only data that we need for particular screen.
BUT. The question is, how to make them live together.
On the one hand, we have dynamically returned data from graphql. It
means that, for example, if we have list of people on the one screen,
we will request id, name, surname and role of the person. On the
different screen for dropdown of people we will request the same data
but without role.
On the other hand we have class Person that has static set of fields Name, Surname, Role and Id, which person has in "real life"
If we use the same Person class with graphql, converting data from JSON to model Person, both screens will work fine, but behind the scene one screen that doesn't need Role wouldn't request it from graphQL. And we will have a situation when model class Person will have field Role but it will be just empty (which is i believe is kind of smells. At least I don't feel like it would be easy to maintain such a code. Developer needs to add some information to the screen, opens model, sees that Role is there, bind the field to the screen and goes to drink cofee. And then oops, there is the fields but there was no data assigned ).
Two variants I have on my mind are:
either to not use models and DDD and map data directly to ViewModel
(which personally feels like ruining everything we had before).
or we map that dynamic data to our existing models and different field for different screens (for the same class Person e.g.) will be
empty (because not requested).
Maybe somebody has already used such a combination. How do you use it and what pros and cons are?
It's a fairly common situation where you have a data layer returns many columns but only some are used in a given view.
There is no absolute "best" solution independent of how much impact the full set of columns will have on performance. Which might in turn be linked to things like caching.
You could write services that return subsets of data and then you only use the necessary bandwidth. Sort of a CQRS pattern but with maybe more models than just read + write.
Often this is unnecessary and the complications introduced do not compensate for the increased cost of maintenance.
What is often done is just to map from model to viewmodel (and back). The viewmodel that needs just 4 columns just has 4 properties and any more returned by the model are not copied. The viewmodel that needs 5 has 5 properties and they are copied from the model.
I'm struggling to understand the different types of data bindings in ExtJS and I couldn't figure this out:
What is the difference between "hasMany" and "field.reference" when defining associations on two models?
When should I use "hasMany" and when is "reference" better?
For example, if I want to define multiple email addresses to one user, what is the best practice so I can use the email model elsewhere too?
I'm aware that I have 3 questions, but these seem to belong together.
Thanks!
One of the best breakdowns on this I've seen is here:
https://moduscreate.com/blog/associations-in-ext-js-5/
It goes into a lot of detail, and specifically addresses your third question regarding email addresses - because the association is now defined on the child model rather than parent model, you have to have a different email model if you want to attach it to a different parent, i.e. a CustomerEmail class to attach to Customer and an AdminEmail class to attach to Admin.
There's a bit of detail for the reason for the change here:
http://www.sencha.com/blog/deep-dive-into-ext-js-5-data
Declaring associations is another area in Ext JS 5 where we have
reduced boilerplate code requirements. In previous releases, the
hasMany, hasOne and belongsTo configs required that you manually
maintain symmetric declarations on both “sides” of an association.
This is no longer the case. You can declare an association in either
of the associated classes (though typically on the “many” side).
I'm using CakePHP2.3 and my app has many associations between models. It's very common that a controller action will involve manipulating data from another model. So I start to write a method in the model class to keep the controllers skinny... But in these situations, I'm never sure which model the method should go in?
Here's an example. Say I have two models: Book and Author. Author hasMany Book. In the /books/add view I might want to show a drop-down list of popular authors for the user to select as associated with that book. So I need to write a method in one of the two models. Should I...
A. Write a method in the Author model class and call that method from inside the BooksController::add() action...
$this->Author->get_popular_authors()
B. Write a method in the Book model class that instantiates the other model and uses it's find functions... Ex:
//Inside Book::get_popular_authors()
$Author = new Author();
$populars = $Author->find('all', $options);
return $populars;
I think my question is the same as asking "what is the best practice for writing model methods that primarily deal with associations between another model?" How best to decide which model that method should belong to? Thanks in advance.
PS: I'm not interested in hearing whether you thinking CakePHP sucks or isn't "true" MVC. This question is about MVC design pattern, not framework(s).
IMHO the function should be in the model that most closely matches the data you're trying to retrieve. Models are the "data layer".
So if you're fetching "popular authors", the function should be in the Author model, and so on.
Sometimes a function won't fit any model "cleanly", so you just pick one and continue. There are much more productive design decisions to concern yourself with. :)
BTW, in Cake, related models can be accessed without fetching "other" the model object. So if Book is related to Author:
//BooksController
$this->Book->Author->get_popular_authors();
//Book Model
$this->Author->get_popular_authors();
ref: http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#relationship-types
Follow the coding standards: get_popular_authors() this should be camel cased getPopularAuthors().
My guess is further that you want to display a list of popular authors. I would implement this using an element and cache that element and fetching the data in that element using requestAction() to fetch the data from the Authors controller (the action calls the model method).
This way the code is in the "right" place, your element is cached (performance bonus) and reuseable within any place.
That brings me back to
"what is the best practice for writing model methods that primarily
deal with associations between another model?"
In theory you can stuff your code into any model and call it through the assocs. I would say common sense applies here: Your method should be implement in the model/controller it matches the most. Is it user related? User model/controller. Is it a book that belongs to an user? Book model/controller.
I would always try to keep the coupling low and put the code into a specific domain. See also separation of concerns.
I think the key point to answer your question is defined by your specifications: "... popular authors for the user to select as associated with that book.".
That, in addition to the fact that you fetch all the authors, makes me ask:
What is the criteria that you will use to determine which authors are popular?
I doubt it, but if that depends on the current book being added, or some previous fields the user entered, there's some sense in adopting solution B and write the logic inside the Book model.
More likely solution A is the correct one because your case needs the code to find popular authors only in the add action of the Book controller. It is a "feature" of the add action only and so it should be coded inside the Author model to retrieve the list and called by the add action when preparing the "empty" form to pass the list to the view.
Furthermore, it would make sense to write some similar code inside the Book model if you wanted, e.g., to display all the other books from the same author.
In this case you seem to want popular authors (those with more books ?), so this clearly is an "extra feature" of the Author model (That you could even code as a custom find method).
In any case, as stated by others as well, there's no need to re-load the Author model as it is automatically loaded via its association with Books.
Look out for Premature Optimization. Just build your project till it works. You can always optimize your code or mvc patterns after you do a review of your code. And most important after your project is done most of the time you will see a more clear or better way to do it faster/smarter and better than you did before.
You can't and never will build a perfect mvc or project in one time. You need to find yourself a way of working you like or prefer and in time you'll learn how to improve your coding.
See for more information about Premature Optimization
I'm working on a personal project using WPF with Entity Framework and Self Tracking Entities. I have a WCF web service which exposes some methods for the CRUD operations. Today I decided to do some tests and to see what actually travels over this service and even though I expected something like this, I got really disappointed. The problem is that for a simple update (or delete) operation for just one object - lets say Category I send to the server the whole object graph, including all of its parent categories, their items, child categories and their items, etc. I my case it was a 170 KB xml file on a really small database (2 main categories and about 20 total and about 60 items). I can't imagine what will happen if I have a really big database.
I tried to google for some articles concerning traffic optimization with STE, but with no success, so I decided to ask here if somebody has done something similar, knows some good practices, etc.
One of the possible ways I came out with is to get the data I need per object with more service calls:
return context.Categories.ToList();//only the categories
...
return context.Items.ToList();//only the items
Instead of:
return context.Categories.Include("Items").ToList();
This way the categories and the items will be separated and when making changes or deleting some objects the data sent over the wire will be less.
Has any of you faced a similar problem and how did you solve it or did you solve it?
We've encountered similiar challenges. First of all, as you already mentioned, is to keep the entities as small as possible (as dictated by the desired client functionality). And second, when sending entities back over the wire to be persisted: strip all navigation properties (nested objects) when they haven't changed. This sounds very simple but is not at all trivial. What we do is to recursively dig into the entities present in trackable collections of say the "topmost" entity (and their trackable collections, and theirs, and...) and remove them when their ChangeTracking state is "Unchanged". But be carefull with this, because in some cases you still need these entities because they have been removed or added to trackable collections of their parent entity (so then you shouldn't remove them).
This, what we call "StripEntity", is also mentioned (not with any code sample or whatsoever) in Julie Lerman's - Programming Entity Framework.
And although it might not be as efficient as a more purist kind of approach, the use of STE's saves a lot of code for queries against the database. We are not in need for optimal performance in a high traffic situation, so STE's suit our needs and takes away a lot of code to communicate with the database. You have to decide for your situation what the "best" solution is. Good luck!
You can find an Entity Framework project item at http://selftrackingentity.codeplex.com/. With version 0.9.8, I added a method called GetObjectGraphChanges() that returns an optimized entity object graph with only objects that have changes.
Also, there are two helper methods: EstimateObjectGraphSize() and EstimateObjectGraphChangeSize(). The first method returns the estimate size of the whole entity object along with its object graph; and the later returns the estimate size of the optimized entity object graph with only object that have changes. With these two helper methods, you can decide whether it makes sense to call GetObjectGraphChanges() or not.
I have a model Fix with a relationship HABTM Device model.
Device model has a belongsTo to Device_type model, like this, for only getting the device type name:
var $belongsTo = array('Device_type'=>array('fields'=>'name'));
So, I need every Fix, its devices and its Device_types. When I make a Fix->find('all', array('recursive' => 2))
I expect to get every Device related to Fix (this works ok) and ALSO for every device, its Device_type.name (which is not working).
This is what I get instead for every Device in the result (an empty array):
["Device_type"]=>
array(0) {
}
Besides this, when I make this query for testing: Fix->Device->find('all'), it returns the current Device_type.names for every device related to fixes, which means models are related propertly.
Any help? Thanks.
First thing I notice, is your naming conventions should be lower case under_score for your multi-word table names.
And its also apparent your relationships most likely are not set up correctly if you are not getting the data on a recursive 2.
It's kind of hard to make more judgement with your limited code.
If you are new to CakePHP and MVC, it would be really best to follow the blog tutorial on the CakePHP web site. From that, you will learn the basics of building a CakePHP app and in the end have working application which you can "play" with and modify to learn how MVC ticks. You can experiment and learn a lot from this : )