I am using Money/Money with Symfony and doctrine, but I am not sure how I should perform the mapping. Currently I use the following, resulting in this error message;
Error:
Money\Money could not be converted to string
Mapping:
/**
* #Groups({"group1"})
* #ORM\Column(type="string", nullable=true)
* #var Money
*/
private $price;
Internally Money/Money uses String as representation, thus I thought I could use it as well.
This happens because of doctrine type conversion. Before persisting, doctrine takes the values of your properties and transform them to SQL values using the type you specify in the column annotation. Since the type you are using for your price property is string, doctrine is trying to cast your Money object into a string.
You have many options to fix this, some of them simple and others not that much.
Simple but not optimal: Create a new Money class that will extend from the original one, and create __toString method. This will solve your problem persisting, but the property you'll get from the db will be a string, not an object. If you want to improve that, put some custom logic in your setter so you can create an instance of money from that value. Simple, but dirty.
Medium complex, but might not be what you need: You need to use a doctrine custom type. Is really not that hard. People get scared of this, but jump into the docs and you'll see how simple it is. It consists of basically creating a type, like "money" that contains instructions for doctrine on what to do before persisting properties of that type, and what to do after the value is fetched from the db. So you'll save it as a string in your database still, but you will also control the fetching, being able to create the Money instance. Now, depending on the structure of your money class, this might not be what you need.
Probably your best take: I imagine that your money class not only has the actual value, but maybe a currency type property. If that's the case, probably a Doctrine Embeddable is your best solution. With that you will be able to kinda separate the actual value and the currency code as separate fields in the database. Map your money class to be a Doctrine Embeddable (since is a class that lives outside of your domain logic, in vendor, you will have to use yaml or xml, and not annotations). When the object is fetched from the db, it will be an instance of the Money class. But for that to happen, you need to have proper getters and setters that the property access component can use. Best thing about embeddables, is that they are reusable with other entities.
Hope this info helps! Happy coding!
Related
According to doctrine documentation am reading, it says concerning using
Entity classes
that all of the fields should be protected or private (not public) and this is the quote.
When creating entity classes, all of the fields should be protected or
private (not public ), with getter and setter methods for each one
(except $id ). The use of mutators allows Doctrine to hook into calls
which manipulate the entities in ways that it could not if you just
directly set the values with entity#field = foo;
While the 6th edition of an advanced PHP book(One of the best selling books on PHP and other programming books out there are being written by this company) I just read says this
In most cases, private properties are strongly preferred over public
ones. However, in the case of entity classes, you should use public
properties. The sole purpose of an entity class is to make some data
available. It’s no good having a class representing an author if you
can’t even read the author’s name!
I understand that the pattern used by doctrine might slightly be different from the book approach but when you see statements like this, you get to wonder which is which. Which of the statement is wrong and which of the statement is right
The entire house should please enlighten me
While designing a class I assumed that having an $id property will make that class Entity rather than a value object.
I also have a toArray() method which converts the object to associative array and that response is send to post and patch api's.
Now I have the following questions:
POST works,
since I’m not sending the id in the body. But for PATCH is it fine if I set the property dynamically after object creation? For Ex:
$redCircle = new Circle(“red”);
$redCircle->id = 10;
$api->patch($redCircle->toArray());
Your point of view is very technical, as opposed to DDD.
You should design your Aggregates and nested Entities according to the business rules (the invariants).
While designing a class I assumed that having an $id property will make that class Entity rather than a value object.
This is not true. There are cases when a local Value object (that comes from a remote Aggregate, in another Bounded context) needs an ID property in order to be kept up-to-date (i.e. by background tasks). The Anti-corruption layer would need this property, so the reasons are pure technical.
POST works, since I’m not sending the id in the body. But for PATCH is it fine if I set the property dynamically after object creation?
Again, this is not a DDD view of the problem. In DDD, an Aggregate execute commands: one does not simply update its internal state directly; this would break its encapsulation.
But to answer your question, considering that you have a CRUD app: In order to mutate parts of an Entity you would need to load it from the Repository before mutation. The Repository would set the ID along with the other properties.
One of the best ways to locate entities is to use a RESTful API, so the client would not need to construct the URLs for the PATCH operation.
i want to create a forms with only getter methods in the entity... Since I am working on already existing database which does not require to store or manipulate the data.
Hence I have created Entities for the products with only Getter methods and no Setter method.
However when i create form( like search query with some dropdowns etc) it always looking for set or Add methods. Is there a possibility if i can only use getters to get the data from the database.
And I do not want data to be modified at anytime in the future.
i tried with "read_only" but it still gives an error about setter and addMethod()
http://symfony.com/doc/current/reference/forms/types/form.html#read-only
EDIT:
I want to create a drop down ProductGroupcategory-> productSubcategory -> Product
like this(advance search): http://www.buycarspares.co.uk/
Complete Code:
https://gist.github.com/anonymous/8b2e576e69b1588e4f21
Relationships require add- and get-methods simply because it is about an array or arrayCollection of an object and not about the getters or setters for normal entity properties like strings.
Yes you can though some people might consider the solution to be worse than the problem. You could of course just declare your entity properties to be public. That would avoid not only setters but getters as well. Doctrine 2's lazy loading functionality would not work.
A more advanced approach it to realize that the form component uses a property access object to transfer data to and from your entity. That is where the 'add' and 'set' messages are coming from. Property access objects are also what allows you to use arrays as well as entities. http://symfony.com/doc/current/components/property_access/introduction.html
The form component allows you to plug in your own property access object which means that you can create your own access object which can write directly to private/protected variables using Reflection. This, by the way, is the same technique that Doctrine 2 uses to hydrate your entities using database information.
Of course I can already hear howls of protest of this approach mostly about violating encapsulation. But think about it for a moment before down voting. The form component really is just persisting and retrieving the state of an entity to and from an html document. Exactly what Doctrine 2 does. As long as you don't misuse the technique then there is no violation.
I routinely use this approach to avoid writing endless getters and setters. Seems to work fine in practice.
I'm trying to decide on this dilemma as I'm writing some PHP API's I'm working on. I'm trying my best to write some solid APIs without being a PHP veteran, by groping through the dark hoping to find some best practices. I'm also uncertain if I'm using the right terminologies, so please correct me.
I have some entities that store their data in a database, which I'm modeling in an object-oriented way. Should my models always strictly represent what's currently in the database, or not?
Loose Database Representation
The user can freely change the model's attributes, then later save whatever changes to the database.
The model does not always reflect what's in the database, because the user can change the model arbitrarily.
<?php
// Write a snippet
$snippet = (new Snippet)
->label("grapes")
->content("wine")
->save();
// Load a snippet
$snippet = (new Snippet)
->label("bananas")
->load();
// Update an existing snippet
$snippet
->content("potassium")
->save();
?>
Strict Database Representation
The user cannot freely change the model's attributes. Only getters are provided for the attributes (no setters).
The model is guaranteed to always represent what's in the database.
The only way to change the model, is to also change what's in the database.
<?php
// Write a snippet
$snippet = (new Snippet)->write("grapes", "wine");
// Load a snippet
$snippet = (new Snippet)->read("bananas");
// Update an existing snippet
$snippet->update("potassium");
?>
Which API style would you prefer to use?
I started with the loose model, and have started to wonder if the strict model is a better way to do things? Does the strict model's promise of integrity outweigh the loose model's flexibility?
I'm open to any thoughts, comments, pros/cons, alternatives, and ideas; I just want to do PHP right, and make a good API that other programmers find pleasing :)
Both examples remind me of the ActiveRecord pattern. ActiveRecord is when you endow your objects with CRUD methods - that is, they know how to create, read, update, and delete themselves from a data source.
Now, if I am understanding you correctly, you are wondering if it is better to be able to set a model's attributes, and then call CRUD methods on it, or call the CRUD methods directly, passing in arguments that set the attributes internally? In either case, it seems like both 'representations' are as loose or strict as the other. As far as a good API goes, I would say the 'loose' representation would be what most people expect.
Now, on to suggestions. There are two popular patterns for interacting with data sources. One is the ActiveRecord Pattern, and the other is the Repository Pattern. I've described briefly the ActiveRecord pattern. The Repository Pattern strips out data interaction responsibilities from the model, and puts it in a 'repository' class. This repository class is responsible for CRUD operations. There are many posts about the pros and cons of the ActiveRecord v. Repository Pattern out there, so you can look that up. I will say that the Repository Pattern is more widely accepted as being the 'better' one.
In reference to when you say, "The user can freely change the model's attributes, then later save whatever changes to the database.": Objects, in general, should protect their invariants. That is to say, you shouldn't allow their data to be set to an invalid state. An object should be constructed with the information it needs, and not provide setters unless it makes sense for the values in the object to be changed. And even then, you can often give a setter a better name then just setX(). ei: fillUp() instead of setFuel() on a car object.
I personally would design things with the repository pattern:
class SnippetRepository
void save(Snippet snippet) { ... }
void update(Snippet snippet) { ... }
boolean delete(Snippet snippet) { ... }
Snippet load(SnippetId id) { ... }
end
$snippet = (new Snippet)
->label("grapes")
->content("wine");
snippetRepository.save($snippet);
I hope that helps.
The documentation warns a few times about ensuring wakeup and clone implementations on Doctrine 2 entities, e.g.:
http://docs.doctrine-project.org/en/latest/cookbook/implementing-wakeup-or-clone.html
It doesn't say why, however... I presume it has something to do with not messing with Doctrine's Entity Manager and the in-memory-cache it might maintain, but a cursory dive into the (enormous) code base doesn't say much more, nor did a quick search of the users list.
Might anyone knowledgeable with the Doctrine internals know precisely why Doctrine 2 needs safe wakeup and clone methods on entities?
Doctrine 2 needs to convert data fetched from the database into entities (php objects). This process is called hydration.
Doctrine 2 doesn't use the traditional method of using the new operator (thus constructing a class), but it uses the following method:
It builds a string which represents a serialized empty version of your class.
It unserializes that string to make it an actual object. This is why you need to safely implement __wakeup.
It stores that object as prototype.
This process is done once for each entity class.
Then whenever it needs to hydrate an entity, it will clone the prototype. This is why you need to safely implement __clone.
This is all done a small method newInstance() in ClassMetadataInfo.
The advantage of doing this is that the constructor isn't used when a new entity is hydrated. That leaves the developer free to do anything he/she wants in the constructor (including using parameters).
update
The reason why you need to safely implement the __wakeup and __clone methods is this:
Because Doctrine 2 unserializes and clones entities when it needs to hydrate them, those methods will get called. But when Doctrine 2 does this, the entities will not have any data set (not even the identifier(s)). The data will be set afterwards.
So when you implement them in such a way that your logic is only performed when the entity does have the identifier(s), you are sure that your logic is only performed when you unserialize or clone the entity, not when Doctrine 2 does it.
Jasper's answer nails the precise reason, but it doesn't give the background — as in why Doctrine is proceeding to unserialize and clone entities.
The rational for doing so is to allow entities to define whatever constructor they want, as explained in this blog post:
http://www.doctrine-project.org/2010/03/21/doctrine-2-give-me-my-constructor-back.html
At ConFoo 2010 during my presentation, someone asked about the constructor of entities in Doctrine 2 and whether or not it could be used. I think this is something worth writing about since in Doctrine 1 this was not possible. The constructor was hi-jacked from you and used internally by Doctrine.
In Doctrine 2 it is possible to define the constructor in your entity classes and is not required to be a zero argument constructor! That’s right, Doctrine 2 never instantiates the constructor of your entities so you have complete control!
This is possible due to a small trick which is used by two other projects, php-object-freezer and Flow3. The gist of it is we store a prototype class instance that is unserialized from a hand crafted serialized string where the class name is concatenated into the string. The result when we unserialize the string is an instance of the class which is stored as a prototype and cloned everytime we need a new instance during hydration.
Have a look at the method responsible for this:
<?php
public function newInstance()
{
if ($this->_prototype === null) {
$this->_prototype = unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name));
}
return clone $this->_prototype;
}