With these classes, how would you change a record for a "Person" to an "Employee".
/**
* #Entity
* #InheritanceType("SINGLE_TABLE")
* #DiscriminatorColumn(name="discr", type="string")
* #DiscriminatorMap({"person" = "Person", "employee" = "Employee"})
*/
class Person
{
// ...
}
/**
* #Entity
*/
class Employee extends Person
{
// ...
}
I tried changing the value of the discriminator column but I can't access that. I also tried creating an 'Employee' instance and manually copy the data over but that doesn't work with auto-incrementing id's. It just gets added as a new record instead of updating the existing one.
Do I need to write a custom sql query or am I doing something else that is fundamentally wrong?
It is not a good sign when the type of an instance of an object needs to change over time. I'm not talking about downcasting/upcasting here, but about the need to change the real type of an object.
First of all, let me tell you why it is a bad idea:
A subclass might define more attributes and do some additionnal work
in it's constructor. Should we run the new constructor again? What
if it overwrites some of our old object's attributes?
What if you were working on an instance of that Person in some part of your code, and then it suddenly transforms into an Employee (which might have some redefined behavior you wouldn't expect)?!
That is part of the reason why most languages will not allow you to change the real class type of an object during execution (and memory, of course, but I don't want to get into details). Some let you do that (sometimes in twisted ways, e.g. the JVM), but it's really not good practice!
More often than not, the need to do so lies in bad object-oriented design decisions.
For those reasons, Doctrine will not allow you to change the type of your entity object. Of course, you could write plain SQL (at the end of this post - but please read through!) to do the change anyway, but here's two "clean" options I would suggest:
I realize you've already said the first option wasn't an option but I spent a while writing down this post so I feel like I should make it as complete as possible for future reference.
Whenever you need to "change the type" from Person to Employee, create a new instance of the Employee and copy the data you want to copy over from the old Person object to the Employee object. Don't forget to remove the old entity and to persist the new one.
Use composition instead of inheritance (see this wiki article for details and links to other articles). EDIT: For the hell of it, here's a part of a nice conversation with Erich Gamma about "Composition over Inheritance"!
See related discussions here and here.
Now, here is the plain SQL method I was talking about earlier - I hope you won't need to use it!
Make sure your query is sanitized (as the query will be executed without any verification).
$query = "UPDATE TABLE_NAME_HERE SET discr = 'employee' WHERE id = ".$entity->getId();
$entity_manager->getConnection()->exec( $query );
Here is the documentation and code for the exec method which is in the DBAL\Connection class (for your information):
/**
* Execute an SQL statement and return the number of affected rows.
*
* #param string $statement
* #return integer The number of affected rows.
*/
public function exec($statement)
{
$this->connect();
return $this->_conn->exec($statement);
}
Related
The question hard to formulate in just one sentence when I don't have the exact terms ready for use, but I'm basically working on a Symfony 5 project that involves a MySQL database. I use Twig to allow for communication between my PHP controllers and my HTML interface. Until now, I've been doing just fine using simple references to entity fields in Twig, such as:
myEntity.someField
To get the value I needed. However, I currently need to reference a "nested" field like so :
myEntity1.myEntity2Field.someField
The "nesting" making a world of a difference between the two. I am now getting an error when trying to do this (Impossible to access an attribute ("someField") on a string variable ("<value from entity2 field>")),
probably because my database is not organized correctly yet, from what I understand. Hopefully you could understand my difficulty. So, how can I tweak my database to allow this sort of double-referencing to take place?
Note: myEntity2Field refers to the name of a field from Entity2 that should serve as a reference to the entire Entity2 table, from which someField can then be extracted.
the error you are getting is because you are trying to access a value from a string or integer, not an Object.
myEntity.someField is the same as $myEntity->getSomeField() if you have a getter Method or $myEntity->someField if you are accessing the property directly.
If someField value is not an Object you can only access the value but if its an Object you will be able to access the other object properties and methods in this way.
To do so the best way is to use association(relation) between your entities spically if you have the association already in the database and if you build your relations right in your database so you jaut have to refernce this relation or association between your entities and doctrine will do the rest for you.
as an example:
<?php
/** #Entity */
class User
{
// ...
/**
* #ManyToOne(targetEntity="Address")
* #JoinColumn(name="address_id", referencedColumnName="id")
*/
private $address;
}
/** #Entity */
class Address
{
private $street;
public function getStreet(){
....
}
}
this example is a ManyToOne relation between the user and the addresse entity with the getters methos in the user entitiy you will be able to use the nesting when you access the user:
$user->getAddress()->getStreet()
as an example and this will work in twig also:
{{user.address.street}}
https://www.doctrine-project.org/projects/doctrine-orm/en/2.7/reference/association-mapping.html#many-to-one-unidirectional
the other way you can get the object inside your calss and map it with methods so you can access it as you want.
i hope i will be able to help you with this info.
I am programming my first symfony project and I stuck at a problem:
I have a entity I called it "load" which refers to other entities which a call "transaction" (x transactions belongs to 1 load) :
/**
* #ORM\OneToMany(targetEntity="Transaction", mappedBy="load")
*
*/
private $transactions;
The transactions can be flagged as deleted but they keep stored in the database.
I created a custom repository and some methods which deliver me the undeleted transactions.
But if I want to fetch a load with all it's transactions, I call
$load = $loadRepository->find($id);
it does what it is supposed. It fetches all transactions from the database which are referenced to the given load.
But I don't want to have the deleted transactions in my result. How can I achive this? I have absolutely no approach. Sure, I can iterate over the transactions and remove the deleted ones but I think there is a better solution.
I tried to register a repository for the transactions (this works) and override the find-method (this doesn't work).
Is there another method which is internally called and I have to override?
thank you in advance!
If I have correctly understand your question, this behavior already exist with the doctrine extension SoftDeletable, you can find documentation here
You just have to add something like deleteAt property on your Transaction entity then all entities with data inside this field will be automatically filtered like if they are really deleted. If you want to find all of the Transaction entities you can always disable the filter on a query.
I found a solution:
#config.yml:
doctrine:
orm:
filters:
deletedFilter:
class: AppBundle\Filter\SoftDeletedFilter
enabled: true
_
namespace AppBundle\Filter;
use Doctrine\ORM\Mapping\ClassMetaData,
Doctrine\ORM\Query\Filter\SQLFilter;
class SoftDeletedFilter extends SQLFilter
{
public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias)
{
if(!is_subclass_of($targetEntity->rootEntityName, "AppBundle\Entity\SoftDeleteableInterface")){
return "";
}
return $targetTableAlias.'.deleted = 0';
}
}
Now, all entities which implements the (empty) interface "SoftDeleteableInterface" will not be included if the deleted-value is not 0.
Thank you anyway for the answers/comments
What I am trying to achieve
Users would be able to configure Doctrine entities through an HTML form on a website.
Users would be able to define new entities, as well as add and delete fields for existing entities. (Similar to Drupal's content types)
The Doctrine entities would get dynamic properties based on the configuration that the user supplied through the web UI.
Either the single DB table per Doctrine entity would be altered dynamically whenever an entity configuration changes; Or there could be multiple tables used per single entity (each new entity field would get its own table).
Done so far
I have been researching this for the past few days without much success but I stumbled across this answer which seems quite related to what I am trying to achieve.
I have registered and added the loadClassMetadata listener which maps the field foo:
// src/DynamicMappingTest/AdminBundle/EventListener/MappingListener.php
namespace DynamicMappingTest\AdminBundle\EventListener;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
class MappingListener
{
public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
{
$classMetadata = $eventArgs->getClassMetadata();
if ($classMetadata->getName() != 'DynamicMappingTest\\AdminBundle\\Entity\\CustomNode')
{
// Not the CustomNode test class. Do not alter the class metadata.
return;
}
$table = $classMetadata->table;
$oldName = $table['name']; // ... or $classMetaData->getTableName()
// your logic here ...
$table['name'] = 'custom_node';
$classMetadata->setPrimaryTable($table);
$reflClass = $classMetadata->getReflectionClass();
dump($reflClass);
// ... or add a field-mapping like this
$fieldMapping = array(
'fieldName' => 'foo',
'type' => 'string',
'length' => 255
);
$classMetadata->mapField($fieldMapping);
}
}
Now, this all works as long as I have the foo property declared in the DynamicMappingTest\AdminBundle\Entity\CustomNode class:
// src/DynamicMappingTest/AdminBundle/Entity/CustomNode.php
namespace DynamicMappingTest\AdminBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* CustomNode
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="DynamicMappingTest\AdminBundle\Entity\CustomNodeRepository")
*/
class CustomNode
{
...
private $foo;
}
Problem
However, there is no way for me to know what properties the users will define for their custom entities. If I remove the foo property from the CustomNode class, the ReflectionClass that I get from the ClassMetadata will naturally not include the foo property and so I get the following exception whenever the mapField() in MappingListener is executed:
ReflectionException: Property DynamicMappingTest\AdminBundle\Entity\CustomNode::$foo does not exist
in vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/RuntimeReflectionService.php at line 80
77. */
78. public function getAccessibleProperty($class, $property)
79. {
80. $reflectionProperty = new ReflectionProperty($class, $property);
81.
82. if ($reflectionProperty->isPublic()) {
83. $reflectionProperty = new RuntimePublicReflectionProperty($class, $property);
Questions
Is it possible to have fully configurable dynamic Doctrine entities?
Am I on the right track with my approach? If not, could you suggest an alternative?
How could I have truly dynamic class properties? Or should I be generating new Doctrine entity PHP classes whenever the users change the entity configuration?
Is it possible to have fully configurable dynamic Doctrine entities?
Doctrine generates proxy classes for you entities. That means that doctrine generates PHP code with class, which extends your Entity class and overrides the methods - puts some custom logic and then calls the parent method.
So, I think that the only way to make this really happen is to generate the PHP code for entities in your code. That is, every time entity is created in your website, you should generate PHP file with that entity, then run migrations.
Am I on the right track with my approach? If not, could you suggest an alternative?
I don't think that you should use Doctrine ORM at all in this case, at least in the way you're trying to do that.
Generally, ORM is used for easier/more manageable programming. That is, you can set relations, use lazy-loading, unit of work (change entity properties and then just flush) etc. If your entities are generated dynamically, what features will you use at all? Developer will not write code for these entities, because, as you've said, there is no way to know what fields it will have.
You haven't provided concrete use-case - why do you want to do that in the first place. But I imagine that it could be really done in some easier way.
If users can store any structure at all, should you use MySQL at all? ElasticSearch or similar solutions could be really much better in such cases.
How could I have truly dynamic class properties? Or should I be generating new Doctrine entity PHP classes whenever the users change the entity configuration?
As I've mentioned - yes. Unless you would want to override or replace some of Doctrine code, but I imagine it could be lots of it (proxy classes etc.)
Please be brutally honest, and tear my work apart if you have to.
So I'm re-writing a small web-application that I recently made. The reason for this is simply that the code got pretty messy and I want to learn and apply better OO design. What this application should do is just simple CRUD.
I have a database with 3 tables, companies and partners which are in no relation to each other and city which has a 1:n relation with companies and partners. Very simple, really. Now, I have several questions which i will state at the end of my post. Here i'll just try to explain:
My first approach was that I created classes company, partner and city, fetched all datasets from the database and created objects from that:
class company {
private $id = null;
private $name = null;
private $city = null;
//many more attributes
function __construct( $id, $name, $city, [...] ) {
$this->id = $id;
$this->name = $name;
$this->city = $city;
//huge constructor
}
/*
* getters + setters here
*
* no need to paste the partner class as it looks just like this one
*
*/
}
And that is all these classes did. I fetched every dataset from the database and constructed company, partner and city objects (the attribute city within these classes is an object with several attributes itself) and saved them into two arrays arr_companies and arr_partners, which then held these objects...and it worked fine like that.
Now, what I wanted is to update, insert, delete into the database, and all 3 classes (city, company, partner) need this functionality. My approach was that I created a new class with a constructor that would basically take 2 strings command and object, e.g. ('update', 'company') and it would then update the company directly in the database leaving my objects untouched. That made me really sad, because I had such nicely constructed objects and I didn't know how to make use of them.
Questions:
Is it bad to have such huge constructors (my biggest one would take
28 parameters)?
Should you have a separate class for database
operations or is it better to have maybe an abstract class or
interface for it and let the subclasses themselves handle update, delete, insert?
Is it common to just write, delete from the database whenever or should I just apply these changes to my objects and only execute the commands to the database later, for example when the session ends?
I figure an application like this must have been done a fantastillion times before. What is the proper approach here? create objects, work with objects, save them to the database?
I have so many questions but I think many of them I just don't know how to ask.
Please note that if possible I would not like to use an ORM at this point.
Thank you very much for your time.
Questions posed in OP:
"Is it bad to have such huge constructors (my biggest one would take 28 parameters)"?
Yes. Imagine the calling code. You would have to pass 28 different values, not to mention each call would have to respect the exact order specified in the constructor. If one parameter was out of place, you could wreck havoc with parameter dependent algorithms. If you really need to pass a large number of parameters, I would recommend passing them in as an array (posted an example to another SO question).
"Should you have a separate class for database operations or is it better to have maybe an abstract class or interface for it and let the subclasses themselves handle update, delete, insert?"
Generally speaking, when creating classes, you want to try to identify the nouns that best represent your business needs. In your specific case you would probably have three classes; Company, Partner, and City.
Now within each class (noun), your methods would be in the form of verbs, so symantically your calling code makes sense: if ($company->getName() === 'forbes')
As you mentioned, each class needs a database object (dbo) to work with, so you could implement any number of patterns to expose datase connections to your classes; singleton, singleton with factory, or dependency injection, etc.
Abstract (parent) classes are great for sharing common algorithms across child classes, and should be identified when you are in the psuedo-code stage of your design. Parent classes also allow you to force child classes to have methods by declaring abstract methods within the parent.
Interfaces are a useful tool in certain situations, but I find they are less flexible than declaring abstract methods in parent class. But are good in situations where classes do not share a common parent.
"Is it common to just write, delete from the database whenever or should I just apply these changes to my objects and only execute the commands to the database later, for example when the session ends"?
CRUD activity should happen at the time the action is executed. If you wait for the session to end, you may run into situations where a session is pre-maturely ended due to a user closing a browser, for example. To better protect your data you can wrap your CRUD activity within transactions.
If you are running a high-traffic application, you can implement a queuing system and queue up the work to be done.
"I figure an application like this must have been done a fantastillion times before. What is the proper approach here? create objects, work with objects, save them to the database"?
You are correct, this has been done before, and are commonly referred to as ORMs (object relation mappers). Basically, an ORM will introspect your database schema, and create objects (and relations) which represent your schema. So instead of working with native SQL, you are working with objects. Although you can use SQL for custom business needs, but in the case of Doctrine, you would use Doctrine Query Language (DQL) vs native SQL.
An ORM I would highly recommend is Doctrine.
If you do not want to use an ORM, you can add CRUD methods to your primary classes. I Opted for an interface so your classes don't have to extend from a parent comprised of database operations. Also, check out this post on using a singleton/factory for exposing your classes database object(s).
Consider the following:
// Company.php
class Company implements iDatabaseOperation
public function delete()
{
// Lets use a DBO singleton/factory for DB access
// Uses PDO, which is strongly recommended
$dbo = Database::factory(Database::DATABASE_NAME);
$dbo->beginTransaction();
try {
$sql =
"DELETE FROM " .
" company " .
"WHERE " .
" id = :companyId " .
"LIMIT 1";
$stmt = $dbo->prepare($sql);
$stmt->bindValue(':companyId', $this->getId());
$stmt->execute();
$dbo->commit();
} catch (Exception $e) {
$dbo->rollback();
error_log($e->getMessage();
$e = null; // Php's garbage collection sucks
}
}
}
// iDatabaseOperation.php
interface iDatabaseOperation
{
public function delete();
public function update();
public function insert();
}
It is realy bad. Code is completele unreadable in this case. You have options
to use setters (can add validation logic inside, better readability, no need to fill empty fields with null)
to have separate class builder for each domain class (takes some memory for additional object). Example in java hope you can understand:
class CompanyBuilder {
private final Company c;
public CompanyBuilder() {
c = new Company();
}
CompanyBuilder addId(String id){c.id = id;}
// id should be package visible and class should be located in the same package with builder
CompanyBuilder addName(String name){...}
CompanyBuilder addCity(String city){...}
Company build(){ return c;}
}
hybrid solution to have methods to organise chain(worse debugging, better readability). In java will be methods:
class Company {
...
Company addId(String id){
this.id = id;
return this;
}
Company addName(String name){...}
...
}
Usage:
Company c = new Company().addId("1").addName("Name1");
maybe you can create more granular objects to reuse them later and add specific logic in correct place. For instance it can be Address(Location) object for company.
Follow single responsibility principle. SOLID description on wiki.
It helps to change database specific code without affection of other part of system in your case. Well, separate domain and database specific code, have common interface or abstract class(if you have common logic for all of domain classes - liskov principle). In subclasses implement domain specific part.
If you do not want to lose data you should save them each time or have cluster of servers or have distributed cache. If it is ok to lose save them in the end of session as batch. It will increase youre performance. Also you should save in transaction each time if you have concurrent updates.
Approach is get data from database/construct objects from this data or new objects/ work(update) objects/write data from objects to database
just write more code and read stackoverflow
Finally I suggest to read "Clean Code: A Handbook of Agile Software Craftsmanship" R.Martin.
You are essentially writing your own ORM. So, I wouldn't discount just switching to one that's already been written for you. The advantage to rolling your own is that you gain an understanding of how it works as your write it. But the disadvantage is that someone else has probably already done it better. But assuming you want to continue on...
General Advice: Remember to always break the problem down into simpler and simpler pieces. Each class should only perform a simple function. Also, you should not have to worry about caching updates... unless perhaps your database is on the other end of a remote connection over a modem.
Specific Advice follows:
I would setup your entity instance classes to house data and not to do a lot of data loading. Use other classes and logic for loading the data. I would use the constructor of the entity class only to populate the data that pertains to the class (and it's children).
A simple thing to do is to use static methods on the entity class for loading and saving data. E.g.
class city {
private $id = null;
private $name = null;
function __construct( $id, $name ) {
$this->id = $id;
$this->name = $name;
}
// getters and setters
...
// ---------------------
// static functions
// ---------------------
public static function loadById($cityId) {
// pull up the city by id
$retval = new city(row["id"], row["name"]);
// close db connection
return $retval;
}
public static function loadByCustomerId($customerId) {
// pull up multiple cities by customer id
// loop through each row and make a new city object
// return a hash or array of cities
}
public static function update($city) {
// generate your update statement with $city->values
}
// other methods for inserting and deleting cities
...
}
So now the code to get and update cities would look something like this:
// loading city data
$city = city::loadById(1); // returns a city instance
$cities = city::loadByCustomerId(1); // returns an array of city instances
// updating city data
$city->name = "Chicago"; // was "chicago"
city::update($city); // saves the change we made to $city
The static methods are not the best way to implement this, but it gets you pointed in the right direction. A repository pattern would be better, but that's beyond the scope of this one answer. I find that often I don't see the merit in a more involved solution like the repository pattern until I run into problems with the simpler solutions.
What you are doing looks greate. What you can add is an intermediate layer which maps your business object to your database(object relation mapping). There are a lot of object relational mapping api out there. Check this wikipedia list for ones you can use for PHP
I think a constructor with 28 parameters is too much, you should others classes managing some attributes having some stuff in common. You should give us what kind of others attributes you instanciated, and it could help you to find a way to make more common objects.
I think you should also create a class managing the operations and the database like a DBHandler with delete, update, and so on..
In my opinion, do modifications on tuples in your database directly after functions are called are important.
Why? Because it could avoid conflict, like the case you try to update an object which is supposed to be deleted for example, if you do modifications on your database at the end.
You might want to look at ruby on rails.
You don't necessarily have to switch over to it, but look at how they implement the MVC pattern and achieve CRUD.
What is the most useful/most standard/least surprising way to consistently write comment blocks for constructors and classes and files containing just a single class?
Comment blocks for classes, not constructors
Comment blocks for constructors, not classes
Comment blocks for both constructors and classes -> In that case what sort of details should go in each?
And then the file itself? Does this need a comment block if it just contains a single class? What details should go there?
I want to try and avoid, as much as possible, repetition between class, constructor and file comment blocks.
This is highly depending on your context and the assumed skill level of the people you work with or the people that come after you.
If you publish a framework, a library or something of the sort you usually assume that your user are of all skill levels so you might want to document as much trivial crap as possible to reduce the load of questions your community has to handle.
Let me start of with an example where I think documentation can be a major pain.
What do you absolutely need
If you want to use PHPDoc you need a file doc block and another doc block after that (usually the class doc block).
Those **need* to have a #package Tag. Everything else is optional.
I'd go so far and say that even the #package Tag is optional since you might be able to automatically generate it for project. And if i remember correctly PHPDoc lets you even set a default package for everything that doesn't have a tag.
For documentation in general let me start of with an example (a longer example is at the end):
How many times can you explain what "uri" means:
Note that for getUri it is explained what URI stands for (just to have something to talk about in the comment I'd assume) while it isn't in isAbsUri because there you can at least say "abs means absolute" twice.
If you are not an open source project (or need to ship COMPLETE!!!11eleven api documentation):
I'd strongly suggest to use proper, long and descriptive class, variable and method names instead of documentation.
There is no gain in writing something again in the doc blocks and since it is 2011 and we have 120 char wide terminals and autocompletion there is just no need anymore to abbreviate everything for the sake of saving some chars.
I'd even argue that documenting trivial things hurts you and your team by forcing you to waste time on things nobody gets value from you get into a habit of always writing trivial docs and not reading them anymore.
A good comment should explain WHY something was done while the code its self should explain HOW without needing further comments.
My favorite example for redundant docs is this one:
class myClass {
/**
* Constructor
*/
public function __construct() {
}
Some guidelines say you HAVE to document EVERYTHING and you end up with people stating the obvious again and again.
This adds no value but wastes time when reading the code.
An example for proper naming:
class Person {
/**
* Set a persons weight in Kilogram
*
* #param float $kg Weight in Kilogram
*/
public function setWeight($kg) {}
This code is easy to document because you need to explain what "kg" means because some people might use a different system and you can't google for "kg".
I'm in favor of writing
class Person {
/**
* #param float $kilogram
*/
public function setWeight($kilogram) {}
The doc block is superfluous because calling setWeight on Person can REALLY be expected to set the Weight on a Person. No need to write that out again.
Using $kilogramm as a parameter also saves you the trouble of explaining it in the docs and I'd say, depending on your environment, everyone can be expected to google for "kilogram" if he really doesn't know the measurement unit.
#PHPDoc documentation
All my humble opinion of course
If you don't use type-hinting always use #param tags.
Always use #return tags
Don't use #author tags at all. Collection code ownership is more valuable and the information is in the source control repository anyways.
Only use #copyright tags if you have to. I like only having a LICENSE file but I'm not a lawyer so it might be necessary.
Inline comments:
public function generateReport() {
// get the db connection
$reg = WhateverGlobalStorage::get(“db“);
// auth
if(!$reg->getOne("SELECT view_report FROM USER ...")) {}
// template
$id = $reg->getOne("select ... ");
// render
new ReportTemplate($id); // ...
}
If those are separate "blocks" just move them to descriptive named functions
public function generateReport() {
$this->checkAuthentication();
$template = this->createReportTemplate();
$this->renderReport($template);
}
// Not perfect but at least you can grasp what the method does much quicker
Additional resources:
Slides of a presentation I gave on the subject on some conferences: Slideshare: clean-code-stop-wasting-my-time
And additional small, little older, rant: they-told-you-to-document-everything-they-lied
Book references:
Clean Code: A Handbook of Agile Software Craftsmanship
Refactoring: Improving the Design of Existing Code
A longer example
abstract class xyzRequest {
/**
* Initializes this xyzRequest.
*
* Available options:
*
* * logging: Whether to enable logging or not (false by default)
*
* #param xyzEventDispatcher $dispatcher An xyzEventDispatcher instance
* #param array $parameters An associative array of initialization parameters
* #param array $attributes An associative array of initialization attributes
* #param array $options An associative array of options
*
* #return bool true, if initialization completes successfully, otherwise false
*
* #throws <b>xyzInitializationException</b> If an error occurs while initializing this xyzRequest
*/
public function initialize(xyzEventDispatcher $dispatcher, $parameters = array(), $attributes = array(), $options = array()) {
Lets see, line by line, what that documentation tells you.
(I'm joking around here a little bit to get my point across)
* Initializes this xyzRequest.
So calling ->initialize on a xyzRequest initializes that request? Really? Ok then, if you say so!
* Available options:
*
* * logging: Whether to enable logging or not (false by default)
We are told the options for the third parameter, not for the second or third param but maybe we know those if we know the framework? (Since we are not able to figure out what ->initialize does without someone telling use we might not be that smart...)
* #param xyzEventDispatcher $dispatcher An xyzEventDispatcher instance
Yeah, the type-hint is there. So if the method expects a "xyzEventDispatcher instance" we need to pass in a "xyzEventDispatcher instance". Good to know.
* #param array $parameters An associative array of initialization parameters
* #param array $attributes An associative array of initialization attributes
* #param array $options An associative array of options
Ok. So it's not a linear array. But that I need to pass "initialization parameters" to an "initialize" method I could have figured out.
Still no clue what I actually need to pass in there but as long as its documented it has to be fine!
* #return bool true, if initialization completes successfully, otherwise false
So a boolean return value is "true" for "good" and "false" for bad".
* #throws <b>xyzInitializationException</b> If an error occurs while initializing this xyzRequest
*/
So an exception is thrown if an error occurs while we are doing what the function is named?
So exceptions are used for error cases. Ok. Good to know.
Doesn't tell me the difference between return false and an exception.
The #throws its self is fine because it adds information
Btw: Why is this BOLD and not a #link
Personally, I only comment in the constructors if there is something special to comment about it (like a special initialization).
I wouldn't say that's the "most useful" way to go, but it keeps the code neat, and repeating two times the same thing isn't really needed (if that's your concern).
Comment everything - files (authorship, copyright, description etc), classes (description, code examples), methods and properties. Here is a good example with phpDoc comments.
Personally I think that class and method documentation is the most important documentation around. When I write code I want the help of my IDE when the code completion shows me the documentation belonging to a method. This way I can easily find the method I need.
Since I try to keep the explicit initialization of classes to a minimum, I don't user constructor comments. Hence, I try to avoid the use of constructors itself.
The code in a method or function should be as clear as possible by using declarative variable names and keeping them so small as possible. Only when I do something unexpected, by example for integration issues I comment them.