1

Using PHP 5.3, I am currently writing an MVC application and need to extract the data that was passed in to a model for validation, to send back to the view for repopuating a form on error.

The fields in the model are marked private and can only be accessed if they appear in a list of fieldNames (so controllers can't attempt to change the contents of other 'business' fields in the class.

In the controller area marked 'BUG' below, attempting to access the private field just results in the array item being created but set to null, not the value. While in my debugger, if I inspect the field of the source ($templateM->$field) it shows the correct value.

What's going on?

In the model base class:

class model {

protected $fieldNames;

public function __get($name)
{
    if ($name === 'fieldNames')
        return $this->fieldNames; // Special exception for getting the list of fields
    if ($name === 'errorList')
        return $this->errorList; // special exception for getting the current errors
    if (in_array($name, (array)$this->fieldNames))
        return $this->$name;
    else
        throw new Exception('Invalid access to private model field');
}
}

In the model:

class template extends model
{
function __construct()
{
    parent::__construct();
    $this->fieldNames = new immutableArray(array('id', 'etc'));
}

private $id = 0;
private $etc = 1;
}

In the controller:

class templateManager extends controller
{
    function create()
    {
        // Validate form data
  $templateM = getModel('template');
  $templates = array();
  $bodyData = array();
  $bodyData['showSuccess'] = false;

  $result = $templateM->validate();

  if ($result)
  {
      if ($templateM->save())
      {
          $bodyData['showSuccess'] = true;
      }
  }

  // Load present data (post insert)
  $templates = $templateM->getAllAsArray();

  $bodyData['errorMessages'] = (array)$templateM->errorList;

  $formData = array();
  if (count($bodyData['errorMessages']) > 0)
  {
      foreach($templateM->fieldNames as $field)
            {
                $formData[$field] = $templateM->$field; // <- BUG
            }
  }

  $bodyData['formData'] = $formData;

  $bodyData['templateData'] = $templates;
  $this->_drawPage($bodyData);
}
Nidonocu
  • 12,476
  • 7
  • 42
  • 43

1 Answers1

2

Actually i would recommend for you to stop abusing __get(). You already have too many if's in it, and that list will get only longer and longer. Better to make proper getter and setter methods.

AS for the cause of your problems: the Model::__get() cannot access the private variables. It will work if you define them as protected.

Additionally, you might find this rant useful. At least the "side notes" part of it.

Community
  • 1
  • 1
tereško
  • 58,060
  • 25
  • 98
  • 150
  • Thank you for both answers. This is part of a prototype system so I'll look in to finding a better solution to the access problem. – Nidonocu Mar 21 '12 at 11:45
  • @Nidonocu , the most common recommendation in OOP is : favor composition over inheritance. Might apply to your case too .. – tereško Mar 21 '12 at 11:48