Manage many to many relations in FosRest Bundle - rest

I am using FosRest Bundle with symfony and I have a many to many relations between two tables.
For example:
class Site
{
/** ManyToMany **/
protected $languages;
}
class Language
{
/** ManyToMany **/
protected $sites;
}
I had records previously saved in each table separately but now I want to add relations between them in my new table site_language but I am not sure how to do it.
In SiteController I have these methods:
getSitesAction()
getSiteAction()
postSiteAction()
putSiteAction()
patchSiteAction()
deleteSiteAction()
Should I create a new method like postSiteLanguagesAction()?
Or modify the existing postSiteAction()?

Sort answer: probably both, kinda.
There are two separate concerns here:
altering the languages, that the site has ... though, I probably would just call it postLanguagesAction() instead
adding new sites
There are are actually two other methods, taht you forgot about: putSiteAction() and patchSiteAction() (TBH, I am not sure why you support both). When you update the existing site configuration, you will also need to have an ability to update its available language set.
P.S.
Regarding names, since you controller is most likely already called "Sites", I would have called the methods postResourceAction(), getResourceAction(), getCollectionAction(), etc., because it is kinda hard to see the difference between "posts" and "post" at a glance. And it would also make the "specialized methods" more noticeable.

Related

Entity Framework & WPF Application Design Guidance

Entity Framework Layer Guidance
I'm in the design stage of a WPF business application. The first stage of this application will be a WPF/Desktop application. Later iterations may include a browser based mini version.
I envision creating a dll or 2 that contain the domain model & dbcontext that all applications(Desktop or Browser) will use.
My intention is to ride or die with EF. I'm not worried about using DI/Repository patterns etc for flexibility. The benefits of using them don't outweigh the added complexity in my opinion for this project. My plan is to use a model, and a derived dbcontext.
Having said that, I'm looking for input on where to put certain types of method code.
An example will hopefully make my question more clear:
Let's say I have the following two entities..
Entity: Employee
Entity: PermissionToken
Inside of these two entities I have a ManyToMany relationship resulting in me creating another entity for the relationship:
EmployeesPermissionTokens
For clarity, the PermissionToken Entity's Primary Key is an Enum representing the permission..
In the application, lets say the current user is Administering Employees and wants to grant a permission to an Employee.
In the app, I could certainly code this as:
var e = dbcontext.Employees.Find(1);
var pt = new PermissionToken
{
PermissionID=PermissionTypeEnum.DELETEUSER";
...
}
e.PermissionTokens.Add(pt)
But it seems to me that it would be more convenient to wrap that code in a method so that one line of code could perform those actions from whatever application chooses to do so. Where would a method like that live in all of this?
I've thought about adding a static method to the EF Entity:
In The employee class:
public static void GrantPermission(PermissionToken token)
{
e.PermissionTokens.Add(token);
}
Going further, what would be really convenient for the app would be the ability to write a line like this:
Permissions.GrantToEmployee(EmployeeID employeeId, PermissionTypeEnum
permissionId);
Of course that means that the method would have to be able to access the DbContext to grab the Employee Object and the PermissionObject by ID to do its work. I really want to avoid my entities knowing about/calling DbContext because I feel long term the entities get stuffed full of dbcontext code which in my opinion shouldn't even be in the Model classes.
So Where would a method like this go?
My gut tells me to put these sorts of code in my derived DbContext since in order to do these sorts of things, the method is going to need access to a DbContext anyway.
Does this make sense, or am I missing something? I hate to write oodles of code and then figure out 3 months later that I went down the wrong road to start with. Where should these types of methods live? I know there is probably a purist answer to this, but I'm looking for a clean, real world solution.
First of all you are making a good decision to not abstract EF behind a repository.
With the EF Context you have a class supporting the Unit Of Work pattern which is handling your data access needs.No need to wrap it up in repository.
However this does not mean you should call the Context directly from your controller or viewmodel.
You could indeed just extend the DbContext however I suggest to use services to mediate between your controllers/view models and your dbcontext.
If e.g. in your controller you are handling a user request (e.g. the user has clicked a button) then your controller should call a service to archive what ever "Use Case" is behind the button.
In your case this could be a PermissionService, the PermissionService would be the storage for all operations concerning permission.
public class PermissionService
{
PermissionService(DbContext context)
{
}
public bool AddPermission(Employee e, PermissionType type) { }
public bool RemovePermission(Employee e, PermissionType type) {}
}
Your service ofcourse needs access to the DbContext.
It makes sense to use DI here and register the DbContext with a DI Container.
Thus the context will be injected into all your services. This is pretty straight forward and I do not see any extra complexity here.
However, if you don't want to do this you can simply new up up the Db Context inside your services. Of course this is harder / impossible to mock for testing.

Can Not Set Protected Members on Zend View

I had convenience methods littered all over the place. I have now pushed these in to a couple of helper classes and I made the helper classes protected members of my layer supertypes.
Everything was going along swimmingly until I came to Zend View. I have extended Zend View to make my layer supertype but when I try to attach a protected member it throws a:
Zend View Exception: Setting private or protected class members is not
allowed.
Firstly, why would such members not be allowed? Any ideas? Secondly, have you circumvented it in the past? And how did that go? (It seems that the framework detects protected members by the presence of a leading underscore. This seems a bit hit-and-miss, and also easy to get around).
Note - I'm not saying that I would circumvent it. I'm just trying to find out what others have done in the past (since it seems an odd constraint).
It's an important point for me since I am using traits to bring the helpers and associated proxy methods into each superclass. I don't want to maintain a separate trait just for the View. Alternatively, I don't want to make the helpers public members of each superclass.
Thank you!
Data encapsulation.
Underscore properties are not allowed primarily so that the developer can't accidentally overwrite View properties that are part of the framework.
This essentially protects all of the framework's View properties and allows you, the developer, free rain over any public properties you wish to set.
The authors of Zend View can then be sure of two things: (1) they control (and author) the private and protected class properties and (2) you control the public properties. This makes for logical data encapsulation and maintainable class overloading.

EF: In search of a design strategy for DatabaseFirst DbContext of a Modular Application

I'm looking for suggestions on how to approach using an ORM (in this case, EF5) in the design of modular Non-Monolithic applications, with a Core part and 3rd party Modules, where the Core has no direct Reference to the 3rd party Modules, and Modules only have a reference to Core/Common tables and classes.
For arguments sake, a close enough analogy would be DNN.
CodeFirst:
With CodeFirst, the approach I used was to build up the model of the Db was via reflection: in the Core's DbContext's DbInitialation phase, I used Reflection to find any class in any dll (eg Core or various Modules) decorated with IDbInitializer (a custom contract containing an Execute() method) to define just the dll's structure. Each dll added to the DbModel what it knew about itself.
Any subsequent Seeding was also handled in the same wa (searching for a specific IDbSeeder contract, and executing it).
Pro:
* the approach works for now.
* The same core DbContext can be used across all respositories, as long as each repo uses dbContext.GetSet(), rather than expecting it to be a property of the dbContext. No biggie.
Cons:
* it only works at startup (ie, adding new modules would require an AppPool refresh).
* CodeFirst is great for a POC. But in EF5, it's not mature enough for Enterprise work yet (and I can't wait for EF6 for StoredProcs and other features to be added).
* My DBA hates CodeFirst, at least for the Core, wanting to optimize that part with Stored Procs as much as as possible...We're a team, so I have to try to find a way to please him, if I can find a way...
Database-first:
The DbModel phase appears to be happening prior to the DbContext's constructor (reading from embedded *.edmx resource file). DbInitialization is never invoked (as model is deemed complete), so I can't add more tables than what the Core knows about.
If I can't add elements to the Model, dynamically, as one can with CodeFirst, it means that
* either the Core DbContext's Model has to have knowledge of every table in the Db -- Core AND every 3rd party module. Making the application Monolithic and highly coupled, defeating the very thing I am trying to achieve.
* Or each 3rd party has to create their own DbContext, importing Core tables, leading to
* versioning issues (module not updating their *.edmx's when Core's *.edmx is updated, etc.)
* duplication everywhere, in different memory contexts = hard to track down concurrency issues.
At this point, it seems to me that the CodeFirst approach is the only way that Modular software can be achieved with EF. But hopefully someone else know's how to make DatabaseFirst shine -- is there any way of 'appending' DbSet's to the model created from the embedded *.edmx file?
Or any other ideas?
I would consider using a sort of plugin architecture, since that's your overall design for the application itself.
You can accomplish the basics of this by doing something like the following (note that this example uses StructureMap - here is a link to the StructureMap Documentation):
Create an interface from which your DbContext objects can derive.
public interface IPluginContext {
IDictionary<String, DbSet> DataSets { get; }
}
In your Dependency Injection set-up (using StructureMap) - do something like the following:
Scan(s => {
s.AssembliesFromApplicationBaseDirectory();
s.AddAllTypesOf<IPluginContext>();
s.WithDefaultConventions();
});
For<IEnumerable<IPluginContext>>().Use(x =>
x.GetAllInstances<IPluginContext>()
);
For each of your plugins, either alter the {plugin}.Context.tt file - or add a partial class file which causes the DbContext being generated to derive from IPluginContext.
public partial class FooContext : IPluginContext { }
Alter the {plugin}.Context.tt file for each plugin to expose something like:
public IDictionary<String, DbSet> DataSets {
get {
// Here is where you would have the .tt file output a reference
// to each property, keyed on its property name as the Key -
// in the form of an IDictionary.
}
}
You can now do something like the following:
// This could be inside a service class, your main Data Context, or wherever
// else it becomes convenient to call.
public DbSet DataSet(String name) {
var plugins = ObjectFactory.GetInstance<IEnumerable<IPluginContext>>();
var dataSet = plugins.FirstOrDefault(p =>
p.DataSets.Any(ds => ds.Key.Equals(name))
);
return dataSet;
}
Forgive me if the syntax isn't perfect - I'm doing this within the post, not within the compiler.
The end result gives you the flexibility to do something like:
// Inside an MVC controller...
public JsonResult GetPluginByTypeName(String typeName) {
var dataSet = container.DataSet(typeName);
if (dataSet != null) {
return Json(dataSet.Select());
} else {
return Json("Unable to locate that object type.");
}
}
Clearly, in the long-run - you would want the control to be inverted, where the plugin is the one actually tying into the architecture, rather than the server expecting a type. You can accomplish the same kind of thing using this sort of lazy-loading, however - where the main application exposes an endpoint that all of the Plugins tie to.
That would be something like:
public interface IPlugin : IDisposable {
void EnsureDatabase();
void Initialize();
}
You now can expose this interface to any application developers who are going to create plugins for your architecture (DNN style) - and your StructureMap configuration works something like:
Scan(s => {
s.AssembliesFromApplicationBaseDirectory(); // Upload all plugin DLLs here
// NOTE: Remember that this gives people access to your system!!!
// Given what you are developing, though, I am assuming you
// already get that.
s.AddAllTypesOf<IPlugin>();
s.WithDefaultConventions();
});
For<IEnumerable<IPlugin>>().Use(x => x.GetAllInstances<IPlugin>());
Now, when you initialize your application, you can do something like:
// Global.asax
public static IEnumerable<IPlugin> plugins =
ObjectFactory.GetInstance<IEnumerable<IPlugin>>();
public void Application_Start() {
foreach(IPlugin plugin in plugins) {
plugin.EnsureDatabase();
plugin.Initialize();
}
}
Each of your IPlugin objects can now contain its own database context, manage the process of installing (if necessary) its own database instance / tables, and dispose of itself gracefully.
Clearly this isn't a complete solution - but I hope it starts you off in a useful direction. :) If I can help clarify anything herein, please let me know.
While it's a CodeFirst approach, and not the cleanest solution, what about forcing initialization to run even after start up, as in the answer posted here: Forcing code-first to always initialize a non-existent database? (I know precisely nothing about CodeFirst, but seeing as this is a month old with no posts it's worth a shot)

Zend Framework Models and Doctrine 2 Entities

I've recently integrated Doctrine 2 into my ZF app, using the method introduced here:
http://www.zendcasts.com/unit-testing-doctrine-2-entities/2011/02/
I really like the way it works, however I'm confused a little bot on how this will affect the way I used to have my Models and Mappers.
Let me explain the confusion by an example,
Let's say we have User entities and Purchases as in the example given in ZendCast
Right now I have these entities that Doctrine uses
/library/ZC/Entity
User.php
Purchase.php
Before I used to have
application/models/
User.php (Application_Model_User)
Purchase.php (Application_Model_Purchase)
In classes in application/models/ I used to write functions to act on entities, (Fat model thin controller principle), for example if I wanted to send an email to a user, I would create a method named sendMail in Application_Model_User.
Now I'm not sure if I can add methods to files in /library/ZC/Entity, or if it's a good idea at all since Doctrine uses those files to manage database.
I rather have a separate model file, I also used to have mapper files which worked on more than one Model, for example if I wanted to email all inactive users I would create a method emailInactiveUsers to Application_Model_UserMapper.
How would I do that now?
I also googled a little bit and I found this:
http://net.tutsplus.com/tutorials/php/zend-framework-from-scratch-models-and-integrating-doctrine-orm/
It says
A scaffolding tool, called Doctrine_Cli that creates models from the database very quickly
However the command "generate-models-db" does not exist in my scripts/doctrine.php file. I'm not sure if this is something that Doctrine has stopped supporting in version 2 or what.
Adding methods and properties to your models which are not managed by Doctrine should be no problem. When it comes to mappers, you do not need them with Doctrine. Doctrine already takes care of mappings (e.g. via Annotations in your Entity-class) and for (complex) queries you have the EntityManager/Repositories.
I would place emailInactiveUsers() in a Service, which has access to the EntityManager, e.g.:
class UserMailService
{
private $em;
// Inject EntityManager, e.g. via setEntityManager() or __construct()
public function emailInactiveUsers()
{
$mail = new \Zend_Mail();
$users = $this->em->getRepository('User')->findBy(array('isActive' => false));
foreach ($users as $user) {
$mail->addTo($user->getEmail());
}
// And so on...
}
}
Something like sendMail() in my opinion belongs into a Service as it acts on a User-entity and requires a dependency to a Mailer, which should not be coupled with the model.
If a User does something it belongs in the model. If something acts on the User - in your case a Mailer, which takes the email-address from the user and sends out an email - it does not.

Doctrine 2, Need to execute code pre-persist/post-persist

I am using Doctrine 2 entities. We have some entities which have to update related items when they are saved to the database. For example, when a user record is modified, we save it as a new record, with the "inactive" field set to 'false'. However, we have to set the the 'inactive' field for all previous record for that user to 'true'. This is done to keep an audit history. It is a Legacy database, so changing the structure is not an option.
Since Doctrine saves objects by passing them to a persister object (persist::($thisObj)), rather than the object having a save method ($thisObj->save()), we can't just extend a 'save' method from a parent object. The only option I see here is to try to extend the 'persist' object, but that sounds like a goose gaggle, just waiting to happen.
I found some information on events, but do not see how to add them to make events fire a particular function when a particular entity is persisted.
How do I add pre-save/post-save functionality to some of my entities ?
So, you probably already know http://www.doctrine-project.org/docs/orm/2.1/en/reference/events.html right?
You add an annotation that the entity contains callbacks and then create specific functions (which need to be public) on that entity and also annotate them with #PrePersist or #PostPersist or whatever.
The other way is creating an event subscriber, register that one with the doctrine event manager and implement methods called prePersist, postPersist etc. They get passed an EventArguments object which contains the entity relevant for the occurred event.
I know this is a very general answer to your question, but you need to be a bit more specific where your problem lies.
Please dont exend the entity manager and overwrite the persist method, there are way cleaner methods for doing what you need as far as I can tell.
It's actually quite simple to do what you want to do. It does not require dorking with the event manager, or anything complex like that. You use something called "Lifecycle callbacks". These are functions that Doctrine automatically runs during the "lifecycle" of the entity, ie: prePersist, postPersist, preUpdate, postUpdate, etc. You can find the complete list here: http://www.doctrine-project.org/docs/orm/2.0/en/reference/events.html
The process of adding this functionality to your entities is very simple.
In the Annotations section of your entity, include the following tag: "#HasLifecycleCallbacks". This tells Doctrine that it should search the entity for functions to run upon various events
Write a public function in your entity that you would like to fire upon a specific event.
Put an annotation above the function indicating which event it should be used to handle.
For example, look at the following code:
/** #PostPersist */
public function doSPostPersist() {
$this->tester = 'Value changed by post-persist';
}
I have found that sometimes the events simply refuse to fire, and I don't yet know why. But when they do fire, they will fire reliably.
Don't forget to enable Lifecycle Callbacks in your class annotation :
/**
* Report\MainBundle\Entity\Serveur
* #ORM\HasLifecycleCallbacks
*/
class Serveur {