覆盖Propel 1.6构造函数时会在填充对象时抛出警告

I have the following model where I'm overriding the constructor of the base class:

class Tasks extends BaseTasks {    

    public function __construct($currentUser, $taskId, $startTime) {
        parent::__construct();
        //........
        //set all parameters to their respective fields
        //........
    }

When I manually create a task using: $task= new Task('test_user',1,'10:15'); everything works fine.

The problem is when I fetch all tasks from the database:

 $tasks = TasksQuery::create()->find();

I get the errors:

Warning: Missing argument 1 for Tasks::__construct(), called in...
Warning: Missing argument 2 for Tasks::__construct(), called in...
Warning: Missing argument 3 for Tasks::__construct(), called in...

The stack trace shows that Propel in calling the constructor then populateObject to return the tasks objects with data:

Call Stack:
    //...other function calls
    0.1254   19326792  14. call_user_func(array (0 => 'TasksPeer', 1 => 'populateObject'), array (0 => '98', 1 => '2013-07-16 15:25:00', 2 => 'daily',...other params...) /library/propel1_6/formatter/PropelObjectFormatter.php:87
    0.1254   19326824  15. BaseTasksPeer::populateObject($row = array (0 => '98', 1 => '2013-07-16 15:25:00', ...other params...) /library/propel1_6/formatter/PropelObjectFormatter.php:87
    0.1254   19330456  16. Tasks->__construct($currentUser = ???, $taskId = ???, $startTime = ???) /models/om/BaseTasksPeer.php:485

Now if I decided to use value object in the constructor instead of the primitive data types like:

class Tasks extends BaseTasks {

    public function __construct(User $currentUser, $taskId, StartTime $startTime) {
        parent::__construct();
        //........
        //set all parameters to their respective fields
        //........
    }

The call to the constructor will fail with a fatal error!! Is there a way to solve this?

The Base class calls the constructor, but without arguments. In Order to avoid the warning, make the arguments optional

public function __construct($currentUser = null, $taskId = null, $startTime = null) {
    ... 
}

Instead of null you can, of course, use appropriate values as your application demands.

Short answer: there's no definitive solution for that (constructor DI).

I ended up using the setter DI, calling the setters when I need, first time from the controller, then everywhere I need. But then your controller code will be plagued with setter calls... anyway, I'll show you:

//actions.class.php
...
$current_user = $this->getUser();
$item = ItemQuery::findPk($id);             // you can't override every find* method...
$item
  ->setUser($current_user);                 // setter DI here
  ->archiveIn($current_user->getOfficeId()) // custom method, see below
  ->save();
...

//Item.php
//you need to define getUser() and setUser() methods in this class
...
public function archiveIn($office_id) {
  $this
    ->setOfficeId($office_id)
    ->setArchivedBy($this->getUser()->getUsername());  // get the injected user
  return $this;                                        // keep method chainability
}
...