2

tl;dr: I need to get the name of a given function, but not the current function I'm in.

For example, something like the "getFunctionName()" in the code bellow:

$listFieldNames = array(
    getFunctionName($country->getName()) => 'Name',
    getFunctionName($country->getAcronym()) => 'Acronym'
);

You may be wondering why do I want to do this. Well, I came up with that when I was thinking about how to handle user input in my app. After reading a lot of discussions about using or not using exceptions to validate user input, I ended up choosing to use something like a Notification class (I'm using Zend Framework 1.12):

class Application_Model_Notification
{
    protected $message;
    protected $fieldName;
    protected $code;

    public function __construct($message, $fieldName = NULL, $code = NULL)
    {
        return $this->setMessage($message)
            ->setFieldName($fieldName)
            ->setCode($code);
    }

    // getters and setters;
}

When I validate the data sent by the user, for each field that has a bad input, I push a notification into an array. Each notification use the $fieldName attribute to identify what field is holding the problematic information.

This way, I can show to the user the fields with bad input and place messages near their matching fields. Because the attributes in Model can have different names from the UI forms names (specially when the webdesigner and the webdeveloper aren't the same person), I need to build a list matching them. And here is the problem: I want to avoid build that list with plain strings. The reason is I can change the name of an attribute in the Model, and it would be painfull to change it in the lists too. Otherwise, if a I use the name of its getter, I could easily change it by using the refactor command of the IDE. I just don't know how to get it! And it's not by using the magic constants, because they only work with the current function/method, while my case is about any method given...

I don't know if what I'm doing is a good practice, so I'm putting bellow what I intend to do:

In the Country Controller

public function insertAction()
{
    $country = new Application_Model_Country();
    $country->setName($this->getParam('Name'))
        ->setAcronym($this->getParam('Acronym'));

    $bloCountry = new Application_Model_Business_Country();
    try {
        // The aforementioned list
        $listFieldNames = array(
            getFunctionName($country->getName()) => 'Name',
            getFunctionName($country->getAcronym()) => 'Acronym'
        );

        $bloCountry->insert($country, $listFieldNames);
        if ($bloCountry->countNotifications() > 0) {
            $this->view->notifications = $bloCountry->getNotifications();
        } else {
            $this->view->success = 'Country saved succesfuly.';
        }
    } catch (Exception $e) {
        $this->view->error = $e->getMessage();
    }
}

In the Country Business Object inside the Model

protected $_country;
protected $_notifications;

// Constructor, getters, setters and other methods
// (...)

protected function validate($country, $listFieldNames)
{
    if (trim($country->getName()) == '') {
        $_notifications[] = new Application_Model_Notification(
            'The country name must be specified',
            $listFieldNames[getFunctionName($country->getName())]
        );
    } else {
        $_country->setName(trim($country->getName()));
    }
}

public function insert($country, $listFieldNames)
{
    $this->validate($country, $listFieldNames);
    if (countNotifications() > 0) {
        return 0;
    } else {
        $daoCountry = new Application_Model_DbTables_Country();
        return $daoCountry->save($this->_country);
    }
}

Thanks in advance!

8
  • 2
    I've read your question over and over, and I can't figure out what you want. What is getFunctionName() supposed to return? Commented Dec 19, 2013 at 2:21
  • Sorry for not make my question very clear, @Barmar, the getFunctionName() was supposed to return a string with the name of a given function. You're probably thinking of the magic constants, but they don't work for me because they are used to return the name of the current function, and I need to get the name of the function I want. Commented Dec 19, 2013 at 10:01
  • So you expect getFunctionName($country->getName()) to return something like Country::getName? But the argument to getFunctionName is just a string (the name of a country), how can it know what function it came from? Commented Dec 19, 2013 at 16:00
  • That is exactly the problem. I just need to get dynamically the name of any given function, but how can I do this? I know whether I write down the function, I'm just calling it. So I'm expecting there is some way I can get that name and it could be in any format, the one you've just said "Country::getName" fits perfectly... Commented Dec 19, 2013 at 17:58
  • If you can write '$country->getName()' in the argument, why can't you just write the literal 'Country::getName' in the array assignment? Commented Dec 19, 2013 at 19:30

1 Answer 1

3

So for each custom field that comes from the web, you're going to want a validation function that gets called on it. You can do this on the model level. You're going to have to define those yourself; you will have to do some work.

Defining an interface provides a contract that each model must not break. That means that you can expect every class/model that implements it to have those functions defined.

interface FieldValidationInterface
{
    public function isValid();
    public function getNotifications();
}

class Country implements FieldValidationInterface
{
    /**
     * Check to see if the model is valid 
     * by checking every field
     */
    public function isValid()
    {
        $valid = true;

        // go through each private member
        if (!$this->name) {
            $this->notifications['name'] = 
                'The country name must be specified';
            $valid = false;
        }

        return $valid;
    }

    public function getNotifications()
    {
        return $this->notifications;
    }
}

// The logic for insertAction()
if (!$coutry->isValid()) {
    foreach ($country->getNotifications() as $field => $msg) {
        // do something to report to the web: 
        // which field was bad ($field), and why ($msg)
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, @Andrea. Putting the validation right in the model allows me to use my protected attributes directly and this way I can avoid all that effort of using the attributes getters names to indentify them. But I'm still concerned of the design pattern... Shouldn't I keep my entities anemic and put the validation in another class in the Model, for the sake of separating validation logic from the entity itself? That's what I've been trying to do, but I ended up with the problem I asked first: the need to use functions names...
You can make the validation class a separate class and pass it into the constructor of the Country class. If you're interested in learning about design patterns with small classes that have a single responsibility, you may be interested in dependency injection: fabien.potencier.org/article/11/what-is-dependency-injection
It seems this way it'll assure the separation, but I need to take a look at this article. Thanks, soon I'll post if it helped.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.