Are setters mandatory in extbase models? - typo3

I am following this documentation: https://docs.typo3.org/m/typo3/book-extbasefluid/10.4/en-us/5-Domain/2-implementing-the-domain-model.html
The 'Organization' model defines setters and a method "addContact"
/**
* Adds a contact to the organization
*
* #param Person The contact to be added
* #return void
*/
public function addContact(Person $contact)
{
$this->contacts->attach($contact);
}
I created an extbase model myself, which requires records from an objectstorage. But i figured it out, that I could render records from an objectstorage in fluid, without defining "add{property}" and "set{property} methods. What are the purpose of these methods? When and where are they called?

Setter methods (and adder for ObjectStorages) are not needed by the framework. I'd recommend not adding them if you do not have the use case of setting a value programmatically.
Generally speaking you should not add code that you dont need.
Extbase itself will use reflection to gather and set properties that match database columns.

Setters are for fields that have a representation in the database.
You can add more properties to the models which are i.e. calculated or get the values somewhere else from that don't have setter methods.
Those properties you can access in fluid templates as long as they have also a declaration in the model.
Concerning the method addContact that's one property with probably 4 methods:
getContact (is singular but can have several)
setContact (is singular but can have several)
addContact (adds one contact to the $contact)
removeContact (removes one contact from the $contact)
So this property is still connected / related to the database, just that it's a foreign table as it's foreign model too.
$contact in your case is likely of type \TYPO3\CMS\Extbase\Persistence\ObjectStorage which is like an array iterable but just as object.

Related

Manage many to many relations in FosRest Bundle

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.

Is there a way to annotate an AutoBean property so that it will not be serialized/deserialized?

I have an autobean with a property that is only needed for the UI. I believe that you can null out values and the AutoBeanCodex will not serialized that property, but that equates to an extra step which is needed at serialization.
I was hoping for some annotation similar to the Editor #Ignore annotation. For example:
public interface Foo {
...
#Ignore
String getUiOnlyProperty();
}
So, other than nulling out the value at serialization time, is there any other way to keep an autobean property from being serialized?
Autobeans are meant to be a Java skin on a JSON/XML/whatever format - they aren't really designed to hold other pieces of data. That said, several thoughts that either nearly answer your question with out-of-the-box tools, or might inspire some other ideas on how to solve your problem.
You should be able to build read-only properties by omitting the setter. This isn't quite what you are asking for, but still might be handy.
Along those lines, the JavaDoc for the #PropertyName annotation seems to allude to this possible feature:
/**
* An annotation that allows inferred property names to be overridden.
* <p>
* This annotation is asymmetric, applying it to a getter will not affect the
* setter. The asymmetry allows existing users of an interface to read old
* {#link AutoBeanCodex} messages, but write new ones.
*/
Reading old messages but writing new ones seems like it might be closer to what you are after, and still allowing you to work with the thing-that-looks-like-a-bean.
The real answer though seems to be the AutoBean.setTag and getTag methods:
/**
* A tag is an arbitrary piece of external metadata to be associated with the
* wrapped value.
*
* #param tagName the tag name
* #param value the wrapped value
* #see #getTag(String)
*/
void setTag(String tagName, Object value);
...
/**
* Retrieve a tag value that was previously provided to
* {#link #setTag(String, Object)}.
*
* #param tagName the tag name
* #return the tag value
* #see #setTag(String, Object)
*/
<Q> Q getTag(String tagName);
As can be seen from the implementation of these methods in AbstractAutoBean, these store their data in a totally separate object from what is sent over the wire. The downside is that you'll need to get the underlying AutoBean object (see com.google.web.bindery.autobean.shared.AutoBeanUtils.getAutoBean(U) for one way to do this) in order to invoke these methods.
child class/interface decoded as a parent interface does not explode on decoding allowing the goods to be passed together before the marshalling steps. my immediate test of the actual code below is performing as expected.
public interface ReplicateOptions {
/**
* Create target database if it does not exist. Only for server replications.
*/
Boolean getCreateTarget();
void setCreateTarget(Boolean create_target);
//baggage to pass along
interface ReplicateCall<T> extends ReplicateOptions {
/**
* If true starts subscribing to future changes in the source database and continue replicating them.
*/
AsyncCallback<T> getContinuous();
void setContinuous(AsyncCallback<T> continuous);
}
}

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 {

Does symfony have a built-in method for comparing tainted values to the original?

I am using symfony 1.4 with Doctrine. I have built a form which uses a table that has the Versionable behaviour. As expected, Versionable creates a new version of the row every time the form is submitted and saved. My problem is that I would like to prevent it doing so if the actual values submitted are not any different from the original values put into the form via the edit action.
I know that I can do this with javascript relatively easily. I'm just curious as to whether symfony or Doctrine have this functionality already, and how it is used if so. It just seems like something that symfony would have a method for, which could be checked right before $form->save() is called. Am I dreaming or perhaps missing something obvious?
You can use the DoctrineRecord::getModified() function which returns an array of the modified fields and associated values from an overridden save() function or in a listener (preSave would be the best I guess).
If the new values are not any different, you can bypass the actual call to save(), so no new version is created.
The comment for the save() method of the Doctrine_Record is
/**
* applies the changes made to this object into database
* this method is smart enough to know if any changes are made
* and whether to use INSERT or UPDATE statement
*
* this method also saves the related components
*
* #param Doctrine_Connection $conn optional connection parameter
* #throws Exception if record is not valid and validation is active
* #return void
*/
so first, you should check whether it does not already work.
If not, Doctrine_Record has a isModified() method you could use. If the bind() method of the form object modifies the object in the form which should at first contain the default values, then this method should return true.
If you don't want to override save() method or implement a listener as jaudette suggested you can instead stay with form binding:
$form->bind($values);
if ($form->isValid()) {
$form->updateObject();
$changes = $form->getObject()->getModified();
// save to database if desired
$form->save();
}
The object will not be saved to database by calling $form->updateObject(), but the actual php object is changed.
Also note that you might have to call getModified() on each related object if you have embedded subforms.

What is the phpdoc syntax to link $this to a specific class in Aptana?

I'm working on Magento templates, but this issue would apply to any template loading system.
As these templates are loaded by the template engine there's no way for the IDE (in this case Aptana) to know what object type $this is.
Potentially it could more than one object as a single template could be loaded by multiple objects, but ignoring this, what would the correct phpdoc syntax be to specify a specific class for the $this object?
You can define it like this:
/* #var $this type */
where type is a class name
To be clear, using $this should only ever indicate an object of the current class, right?
PhpDocumentor doesn't currently (v1.4.3) recognize $this as a specific keyword that should equate to a datatype of the class itself.
Only datatypes known by PHP and classes already parsed by PhpDocumentor are the proper datatype values to use with the #return tag. There is a feature request in to have some option available in PhpDocumtentor to aid in documenting fluent methods that always "return $this". [1]
In the case of the #var tag, I don't see how it would be feasible for a class variable to contain its own class instance. As such, I can't follow what "#var $this" should be saying.
If, however, your intention with $this is not for fluent methods that "return $this", and was simply to be some shortcut to PhpDocumentor and/or your IDE to magically guess what datatypes you might mean by using $this, I'd have to guess there's no way to do it. The closest suggestion I could make would be to use the name of a parent class that is a common parent to all the various child classes that this particular var/return might be at runtime, and then use the description part of the tag to have inline {#link} tags that list out the possible child classes that are possible.
Example: I have a Parent abstract class with Child1, Child2, and Child3 children that each could occur in my runtime Foo class.
So, Foo::_var could be any of those child class types at runtime, but how would I document this?
/**
* #var Parent this could be any child of {#link Parent}, {#link Child1}, {#link Child2}, or {#link Child3}...
*/
protected $_var;
Getting back to the "return $this" issue, I'd document things in a similar way:
/**
* a fluent method (i.e. it returns this class's instance object)
* #return Parent this could be any child of {#link Parent}, {#link Child1}, {#link Child2}, or {#link Child3}...
*/
public function foo() {
return $this;
}
Documenting this way at least allows your class doc to have links to the particular classes. What it fails to do is highlight the fluent 'ness. However, if your IDE is capable of recognizing the class names, then perhaps it will be able to do the necessary logical linking to those other classes. I think Eclipse is able to do this at least with popup help, if you hover over the class name in the tag's description. I do not think Eclipse can use this to then make the various child classes' methods available in code completion. It would know about the Parent methods for code completion, because the datatype I explicitly list is Parent, but that's as far as the IDE can go.
[1] -- http://pear.php.net/bugs/bug.php?id=16223
I have found that defining a type with #var for $this does not work - presumably because $this is special and is treated as such by Aptana. I have a similar need to the poster I think - it is in template files (in my case simply located and included by functions within the data class) that I wish to set a type for $this. As #ashnazg says, setting a type for $this within a class definition is not needed, because the type of $this is always the type of the class (up to inheritance).
There is, however, a workaround for template files. At the top of the template file simply put something like
/**
* #var My_Data_Model_Type
*/
$dataModel = &$this;
Then simply use $dataModel (or whatever you choose to call it - maybe something shorter) instead of $this in the template