5

I'm planning on rewritting an application that uses Zend Framework and Twilio (for sending and receiving SMS messages). Looking back, I don't think I placed all of the SMS functionality in the right places. This has made upgrading the website difficult.

Currently, I have an SMS controller that handles requests from Twilio (for incoming messages). I implement a finite state machine (yes, in one big action method) that can handle various commands. Responses are sent directly from this controller, but also from the models that my controllers manage. Because of this, I've ended up with duplicated SMS message templates and confusion as to where exactly a message has originated.

How should I have done this? Should incoming SMS messages be parsed and processed in its own model? Currently, I don't have an SMS model - just an SMS controller. Or, what you suggest?

If it matters, I'm planning on rewriting my application using CakePHP.

Chris Laplante
  • 29,338
  • 17
  • 103
  • 134
  • 2
    Yes, it should be in the Model. The Model contains the Application Logic. View and Controller form one (of many possible) User Interface to the Model. You want Thin Controllers and Fat Models. – Gordon Feb 04 '12 at 20:00
  • possible duplicate of [in MVC, where do you draw the line between a controller and model?](http://stackoverflow.com/questions/3499336/in-mvc-where-do-you-draw-the-line-between-a-controller-and-model) – Gordon Feb 04 '12 at 20:01

2 Answers2

3

I've developed more than a few ZF apps that use Twilio. I tend to either use their PHP helper library in the controller, or (if it's anything other than a simple application) wrap their helper in a service class: Application_Service_SMS.

At that point, sending an SMS message should look like this in the controller:

$sms->send($from, $to, $body); //$sms is a service object of the twilio lib

But that's only the sending part of the question, how do you get $body? Since you're running in an MVC framework, my suggestion would be to separate the two layers (model and view), just like you would do at any other point.

If the model determines the content of the messsage, do something like this in your controller:

$this->view->model = $model;
$body = $this->view->render('sms/' . $command . '.phtml'); 

You'll have to make sure the body is less that 160 characters (or split on that, and send multiple messages). And you've made the SMS message editable without changing your model (since the message is really part of the view layer).

And since with Twilio you can send SMS messages as part of a voice call's TwiML, you can also reuse that message template like this:

//inside a TwiML script
<Sms>
  <?php echo $this->partial('sms/cmd.phtml', array('model' => $this->model)); ?>
</Sms>
Tim Lytle
  • 17,549
  • 10
  • 60
  • 91
  • D'oh! Why didn't I think of using views to generate the messages? This is a great approach, thank you! – Chris Laplante Feb 05 '12 at 19:05
  • @SimpleCoder Something you might find useful working with Zend and Twilio: http://prezi.com/aee_eujg7grb/twilio-the-zend-framework-twiliocon-2011/ – Tim Lytle Feb 06 '12 at 16:38
1

The part of application that should be responsible for sending, receiving data is model.

What to do with them once they are correctly parsed is something what should controller take care about.

I considered longer answer but this is answer to your questions... If you have any subquestions, please ask in comment.

Vyktor
  • 20,559
  • 6
  • 64
  • 96
  • Ok thanks. So I should validate input in the controller before passing it to the model? – Chris Laplante Feb 04 '12 at 20:05
  • @SimpleCoder It depends... What kind of validation is it? If you validate form input you should check data in controller. If it check against some special characters in text of sms, model should have a method to validate data (and check them internally before sending). Maybe write your own validator. It should be pretty much as inserting data into database. Maybe: `ModelSMS` (no input validation), `ModelSMS_Reminder extends ModelSMS` checks valid user id. – Vyktor Feb 04 '12 at 20:09
  • For example, certain commands can only be invoked from specific numbers. Also, numbers can be blocked from invoking commands. Something like that is difficult for me to determine whether it should be model or controller. – Chris Laplante Feb 04 '12 at 20:13
  • @SimpleCoder take a look at http://stackoverflow.com/questions/3499336/in-mvc-where-do-you-draw-the-line-between-a-controller-and-model (link pasted as possible duplicate), there's great answer. But this particular example is Models job (with feedback via controller to view). You should divide dependencies into *core* (something that just shouldn't happen anywhere) and *local* (such as command parameter should be at least 20 chars long). – Vyktor Feb 04 '12 at 20:17