I have a background in Java, lately I learned a the theory behind some web development language, while my back-end language is PHP. In addition, I started to working with CodeIgniter (I'm not sure if it does matter to my question, but anyway).
So, I started to build a simple galleries system - but not sure if the architecture is right (I based on my background in Java, but I don't know if web development is the same).
The galleries system is very standard: user can upload / delete images and galleries, view gallery, view image and view all galleries (in this case the name of the gallery is displayed and thumb of the last added image). there is pagination at the all 'views'.
I created 3 classes, under application/libraries/galleries:
gallery_actions.php:
class Gallery_Actions {
// Nuber of galleries to display in one page
const galleriesPerPage = 4;
public function getGalleries($page) {
$q = .. query ..;
return $this->getObjectGalleryArray($q->result_array());
}
public function getFeatureGallery() {
$gallery = .. query .. ->row_array();
return new Gallery($gallery);
}
public function getPopularGalleries($limit) {
$q = .. query ..;
return $this->getObjectGalleryArray($q->result_array());
}
// Get database galleries array and return object galleries array
private function getObjectGalleryArray($q = array()) {
$galleries = array();
foreach ($q as $gallery) {
$galleries[] = new Gallery($gallery);
}
return $galleries;
}
}
gallery.php:
class Gallery {
// holds gallery info from DB
// int id, varchar(255) name, varchar(255) lastImg, int countImgs
public $config = array();
// Nuber of imgs to display in one page
const imgsPerPage = 12;
// In most cases (maybe at all), gets all config. sometimes only id.
function __construct($params = array()) {
if (count($params) > 0) {
foreach ($params as $key => $val) {
$this->config[$key] = $val;
}
}
}
// Watch inside gallery
public function getGallery($page) {
return array[
'info' => $this->config,
'images' => $this->getImagesOfGallery($page)
];
}
// Watch when browse galleries
public function getPreview() {
return array[
'name' => $this->config['name'],
'lastImg' => new Gallery_Image($this->config['lastImg']),
'url' => $this->config['url']
];
}
private function getImagesOfGallery($page) {
$q = .. query ..;
$imgs = array();
foreach ($q->result_array() as $img) {
$imgs = new Gallery_Image($img);
}
return $imgs;
}
public function create() { .. }
public function uploadImages() { .. }
public function delete() { .. }
private function updateCount() { .. }
}
Gallery_Image:
class Gallery_Image {
// holds img info from DB
// int id, varchar(255) name, varchar(255) url
public $config;
// In most cases gets all config OR only id.
function __construct($params) {
if (count($params) > 0) {
foreach ($params as $key => $val) {
$this->config[$key] = $val;
}
}
}
public function getImage() { return $this->config; }
public function update() { .. }
public function delete() { .. }
public function getThumb() { .. return url string .. }
}
It's a little long, but it's really not hard to understand.
To be honest, I wrote the code just now, so maybe there are syntax errors - but that not the point.
The point is the mixing of the OOP at the code && web development. The big advantages of this code is that there isn't duplicated code, very clearly, actualize the idea of OO.
WHAT I'M NOT SURE - is the creation of the objects necessary and effective? I mean, web development is the same architecture method such as, for example, building a game for android phone? each table in the database (of course not binding tables etc) has a php class and object?
The web is a delivery mechanism, nothing more. See: http://www.youtube.com/watch?v=WpkDN78P884
As you said, building a game for android and building a web application often have similar architectural challenges. There is no architectural silver bullet - the form and intent of your code should inform each other.
The creation of objects is never necessary - some programmers would prefer to write web apps in assembly! However, objects can be a valuable abstraction. As you said, "The big advantages of this code is that there isn't duplicated code, very clearly, actualize the idea of OO." The important advantages are code readability and maintainability, which are both (almost totally) subjective. It is up to you as the maintainer of the codebase to decide what is most effective for you.
Now, if you are looking for web app architecture OPINIONS, check this out: http://12factor.net/
Related
I know this sounds very much like "Is there a PHP framework that does my entire job for me?" But bear with me.
Say I want to create a signup form for a camp, and I have a simple data structure in mind --
Person
First name
Last name
Address
Address
Line 1
Line 2
Suburb
Town
etc
Things I have seen that do part but not all of what I want:
PHP form libraries like jFormer and ValidForm (not to mention all the big frameworks): these things let you define the form you want to make using a little bit of PHP -- so you'd say "add text field, add textarea", etc -- but they don't let the user edit the form data structure, nor do they automatically save into a data structure. They're more useful for developers.
Front-end form creators like foxyform, jotform: they let the user edit the form but the backend needs to be done in some other way, and it's not linked up.
Then there's Wordpress Pods CMS, which is almost exactly what I want -- but without the wordpress part.
Ideally, I would like one of two things:
1) A microframework where you define your data schema in some reasonably simple way, like say Json or Yaml -- your basic
Person
First name: Text
Last name: Text
Address: has_one Address
Address
... and so on
And it would take that and create the form you needed and maybe even create the database schema and so forth. You could then get hold of the data objects to iterate over in your code elsewhere (I'm not crazy enough to try and automate that as well... Or maybe I am, but certainly it feels outside the scope of this particular encapsulation).
OR
2) The above, plus a little editor for editing the data schema.
Create data type:
Name: [Person]
Fields:
First name: [Text field]
[+ Add field]
I have had a good look around and haven't found anything that's small and standalone and does just this. Pods CMS is almost exactly what I want, but smaller and cleaner and not tied to Wordpress.
Does such a thing exist? If not -- and I'm straying onto opinion here but I'll take a chance -- does it seem like such a thing should exist? Wouldn't it be nice to just be able to drop such a thing into any application, and either write the schema yourself or allow the user to edit it? It doesn't seem so very difficult, and it would be usable in so many contexts.
I am not quite sure such a detail of personalization exists but let's give it a try:
First you should create your classes:
class Person{
private $first_name;
private $last_name;
private $adress;
public function __construct($data=array(), adress $adress=null){
foreach ($data as $cle => $valeur)
$this->$cle=$valeur;
$this->adress=$adress;
}
public function __get($property){
return $this->$property;
}
public function __set($property,$value)
{
$this->$property=$value;
}
public function all_object_properties() {
return get_object_vars($this);
}
public function all_class_properties(){
return get_class_vars(__CLASS__);
}
}
class Adress{
private $id;
private $line_1;
private $line_2;
private $suburb;
public function __construct($data=array()){
foreach ($data as $cle => $valeur)
$this->$cle=$valeur;
}
public function __get($property){
return $this->$property;
}
public function __set($property,$value)
{
$this->$property=$value;
}
public function all_object_properties() {
return get_object_vars($this);
}
public function all_class_properties(){
return get_class_vars(__CLASS__);
}
public function fill($id){
$connexion=db_connect();
$req=$connexion->prepare("SELECT * FROM adresses WHERE id=:id");
$req->execute(array('id'=>$id));
while ($row = $req->fetch(PDO::FETCH_ASSOC)){
foreach ($row as $cle => $valeur)
$this->$cle=$valeur;
}
return $this;
}
public function save(){
$connexion=db_connect();
$sql1="INSERT INTO adresses (";
$sql2=" VALUES (";
$vars=$this->all_properties();
foreach($vars as $var=>$value){
$sql1.=$var.", ";
$sql2.=":".$var.", ";
}
$sql1=substr($sql1,0,-2).")";
$sql2=substr($sql2,0,-2).")";
$sql=$sql1.$sql2;
$query=$connexion->prepare($sql);
$query->execute($vars);
if($query){
$this->id=$connexion->lastInsertId();
return true;
}else{
return false;
}
}
public function update(){
$connexion=db_connect();
$sql1="UPDATE adresses SET ";
$vars=$this->all_properties();
foreach($vars as $var=>$value){
$sql1.=$var."=".":".$var.", ";
}
$sql1=substr($sql1,0,-2)." WHERE id=:id";
$query=$connexion->prepare($sql1);
$query->execute($vars);
if($query){
return true;
}else{
return false;
}
}
}
Then you want the ability to create a form based on a file like JSON or even XML:
<forms>
<form>
<host>name_of_my_page_where_my_form_is_displayed.php</host>
<method>post</method>
<target>#</method>
<input>
<type>text</type>
<name>first_name</type>
<class>Person</class>
</input>
<input>
<type>text</type>
<name>last_name</type>
<class>Person</class>
</input>
<input>
<type>text</type>
<name>line_1</type>
<class>Adress</class>
</input>
<input>
<type>text</type>
<name>suburb</type>
<class>Adress</class>
</input>
</form>
</forms>
Here you need a function to parse and create the form:
function display_form($xml_file,$page_to_display){
$content=null;
$values=array();
$dom = new DOMDocument;
$dom->load($xml_file);
$forms=$dom->getElementsByTagName("form");
foreach($forms as $form){
$urls = $form->getElementsByTagName( "host" );
$url = $urls->item(0)->nodeValue;
if($url==htmlspecialchars($page_to_display)){
$tp_method = $form->getElementsByTagName( "method" );
$method = $tp_method->item(0)->nodeValue;
$tp_target = $form->getElementsByTagName( "target" );
$target = $tp_target->item(0)->nodeValue;
$content="<form action=".$target." method=".$method."><br/>";
$inputs=$dom->getElementsByTagName("input");
foreach($inputs as $input){
$tp = $form->getElementsByTagName( "type" );
$type = $tp->item(0)->nodeValue;
$tp = $form->getElementsByTagName( "name" );
$name = $tp->item(0)->nodeValue;
$tp = $form->getElementsByTagName( "class" );
$class = $tp->item(0)->nodeValue;
$content.="<input type=".$type." name=".$name."/><br/>";
$values[]=array("class"=>$class,"name"=>$name);
}
$content.="<input type='submit' value='Submit'/>";
}
}
return array("content"=>$content,"values"=>$values);
}
Finally in your page where the form is displayed:
<?php
$array=display_form("forms.xml",$_SERVER['REQUEST_URI']);
$content=$array['content'];
$values=$array['values'];
$classes=array();
$names=array();
foreach($values as $tab){
$class=$tab['class'];
$name=$tab['name'];
$classes[]=(!in_array($class,$classes)) ? $class : null;
$names[]=$name;
${$class}[]=$name;
}
$form_submitted=true;
foreach($names as $name){
if(!isset($_POST[$name]))
$form_submitted=false;
}
if($form_submitted){
foreach($classes as $name_class){
$var= new $name_class;
foreach(${$name_class} as $value){
$var->__set($value,$_POST[$value]);
}
$var->save();
}
}
echo $content;
In addition, you may want to create a function to fill your xml.
In each classes you can use functions fill() to retrieve data for an object in the database based on their ID, save() to create a new insert in the database, or update() to update an already existent row based on the ID.
There is a lot of improvement which can be done, but the general idea is here.
Feel free to improve it and make yours!
The best example i can think of is a hall of fame page for sports.
You can then have a navigation that can limit the results depending on the user's requests, Past 3 Months and boxing for example.
What would be the best way to display multiple kind of result layouts, for example,
The swimming results have a different layout to football, football differs to boxing and then add a time limiter by timestamp.
These are the options i have thought of so far and would like your opinion on.
Simple PHP
if($_GET['sport'] = "boxing"){
if(isset($_GET['timescale'])){
$start = 1334752108;
$end = 1334759108;
$query = "SELECT athlete_name, athlete_age, athlete_desc FROM `athletes` WHERE `timestamp` BETWEEN '".$start."' AND '".$end."' AND `sport` = 'boxing' LIMIT 30";
} else {
$query = "SELECT athlete_name, athlete_age, athlete_desc FROM `athletes` WHERE `sport` = 'boxing' LIMIT 30";
}
while($row = mysql_fetch_array(mysql_query($query))){
echo "<div class='boxing'>";
//show results
echo "</div>";
}
}
if($_GET['sport'] = "swimming"){
//repeated
}
if($_GET['sport'] = "football"){
//repeated
}
Ajax
Have either one page that will handle all the requests (ajax_request_hof.php) that contains similar code to the PHP above.
EDIT
skafandri suggested a Data Mapping Class, would anyone else advise this or is able to show me an example?
Any ideas on how i can improve this are greatly welcomed and needed.
You mentioned in SO chat that you didn't have any experience with frameworks so here's a suggestion without one.
I know I'm probably going to be flamed for this, but knowing that it's an organizational structure issue you can steal some concepts of MVC and use them until you can port it to a more proper structure to at least make it a little cleaner and a lot easier to manage.
Disclaimer: In no way is this a good structure but for your problem, considering you told me you didn't have any background on OOP and or patterns, but it's "good enough" as a temporary solution.
If you order it like this you can insert it into almost any framework without doing a lot of work.
Here's one way you can do it.
With the following classes:
<?php
class BasketballPage
{
protected $mapper;
public construct ( $mapper )
{
$this->mapper = $mapper;
}
public function display_player_info( $playerid, $sportid )
{
$basketball_player = $this->mapper->get_sports_player( $playerid, $sportid )
echo '<p>Basketball player name ' . $basketball_player['name'];
echo '<p>Some other HTML, etc</p>';
}
public function display_match_data($matchid, $sportid)
{
//Same as above but would call to $this_mapper->get_match_data(); And display relevant HTML.
}
public function display_player_info_AJAX( $playerid, $sportid )
{
$player = $this->mapper->get_sports_player();
header('Content-type: text/json');
header('Content-type: application/json');
echo json_encode( $player );
exit();
}
}
class BoxingPage
{
protected $mapper;
public function display_player_info( $playerid, $sportid)
{
$boxing_person = $this->mapper->get_sports_player( $playerid, $sportid)
echo '<p>Person\'s boxing name ' . $boxing_person['name'];
echo '<p>Some other HTML, etc</p>';
}
}
class Mapper
{
protected $connection;
public function __construct ( $connection )
{
$this->connection = $connection;
}
public function get_sports_player($id, $sportid)
{
$query = $this->connection->prepare( 'SELECT * FROM players WHERE id = :player_id AND sport_id' );
$query->bindValue(':player_id', $id, PDO::PARAM_INT);
$query->bindValue(':sport_id', $sport_id, PDO::PARAM_INT);
$query->execute();
return $query->fetchAll( PDO::FETCH_ASSOC );
}
public function get_match_data($matchid, $sportid)
{
//some query here that returns match data.
}
}
?>
You'd have a single php page for each of these classes, since they can grow big.
I.e:
Basketballpage.php
Boxingpage.php
Mapper.php
Then include these files into your index.php. and your index could look something like this:
index.php?playerid=1&sportid=2
<?php
//Instantiate the classes first.
$connection = new PDO($dsn,$username,$password); //your database credentials
$mapper = new Mapper( $connection );
$basketballpage = new BasketballPage( $mapper );
$boxingpage = new BoxingPage( $mapper );
if( $_GET['page'] == 2]) //lets say basketball is id 2 in your database
{
$basketballpage->display_player_info( $_GET['playerid'], $_GET['sportid'] );
}
//In this same page you'd also add this other line, but lets say they visit the bottom link instead: index.php?playerid=1&sportid=3
if( $_GET['page'] == 3]) //lets say boxing is 3 in your database
{
$boxing->display_player_info( $_GET['playerid'], $_GET['sportid'] );
}
//THEN lets say someone visits a different link like: index.php?index.php?matchid=1&sportid=2&page=2
if( $_GET['page'] == 2] && $_GET['matchid'])
{
$boxingpage->display_match_data( $_GET['playerid'] );
}
//On the above you can use that same category, but a different function will display a different page!
//Bonus example, you can use it for AJAX easily. Lets say they visit the url index.php?playerid=1&sportid=2&AJAX=1
if( $_GET['page'] == 2 && GET['AJAX'] == 1)
{
$basketballpage->display_player_info_AJAX( $_GET['playerid'], $_GET['sportid'] );
}
?>
It seems complicated but once you see how it's all connected, notice how your index page is only around 30-40 lines! It can make things really neat and you can just concentrate on routing your requests on index.php while the other files take care of the rest.
EAV is a great solution to handle different data models, you can also write a data mapping class, although I recommend you to use a PHP framework, why not ZEND?
The basic ideas to solving this well are:
Split your data retrieval from your display.
class Model { public function getData() {} }
class View { public function write() {} }
$model = new Model();
$view = new View();
$view->write($model->getData());
Implement Model::getData:
Loop to build the sports that you are interested in so that you can OR them in a query.
Get all of the results.
Use PHP to order the array into sports.
Implement View::write:
Loop over each sport, displaying it correctly.
The pagination in Symfony is pretty straightforward and pretty good. However I'm looking for the best direction to go for adding in Sorting to the table.
My thoughts are that the sorting column, direction and current page number are defined in the uri, like this:
http://www.mysite.com/backend_dev.php/articles/author/asc/3/
And then on each page, Symfony uses the uri to determine the current sorting column, direction and page and then manipulates all the pagination links to take those things into account so that when you click on a link to change pages or sort by a different column it takes you to the proper place.
Does anyone have any other directions I could go with this? I know about the simplicity of jQuery's tablesorter plugin but it sucks when there are 1000+ records because you have to load them all at once to make that plugin work.
The generator admin has an interesting approach. It gets the sorting from URI as well like below.
/backend_dev.php/pedidos?sort=status&sort_direction=asc
In order not to carry those get parameters throughout the links (it's a pain to do that), it stores in the user session. Let's see an example. In the action you'll have
public function executeIndex(sfWebRequest $request)
{
// sorting
if ($request->getParameter('sort') && $this->isValidSortColumn($request->getParameter('sort')))
{
$this->setSort(array($request->getParameter('sort'), $request->getParameter('sort_type')));
}
// pager
if ($request->getParameter('page'))
{
$this->setPage($request->getParameter('page'));
}
$this->pager = $this->getPager();
$this->sort = $this->getSort();
}
//// more code
protected function setPage($page)
{
$this->getUser()->setAttribute('ef3Pedido.page', $page, 'admin_module');
}
protected function getPage()
{
return $this->getUser()->getAttribute('ef3Pedido.page', 1, 'admin_module');
}
protected function getSort()
{
if (null !== $sort = $this->getUser()->getAttribute('ef3Pedido.sort', null, 'admin_module'))
{
return $sort;
}
$this->setSort($this->configuration->getDefaultSort());
return $this->getUser()->getAttribute('ef3Pedido.sort', null, 'admin_module');
}
protected function setSort(array $sort)
{
if (null !== $sort[0] && null === $sort[1])
{
$sort[1] = 'asc';
}
$this->getUser()->setAttribute('ef3Pedido.sort', $sort, 'admin_module');
}
protected function isValidSortColumn($column)
{
return Doctrine::getTable('Pedido')->hasColumn($column);
}
It's a nice approach for both, the end user and the developer.
I have users' table users, where I store information like post_count and so on. I want to have ~50 badges and it is going to be even more than that in future.
So, I want to have a page where member of website could go and take the badge, not automatically give him it like in SO. And after he clicks a button called smth like "Take 'Made 10 posts' badge" the system checks if he has posted 10 posts and doesn't have this badge already, and if it's ok, give him the badge and insert into the new table the badge's id and user_id that member couldn't take it twice.
But I have so many badges, so do I really need to put so many if's to check for all badges? What would be your suggestion on this? How can I make it more optimal if it's even possible?
Thank you.
optimal would be IMHO the the following:
have an object for the user with functions that return user specific attributes/metrics that you initialise with the proper user id (you probably wanna make this a singleton/static for some elements...):
<?
class User {
public function initUser($id) {
/* initialise the user. maby load all metrics now, or if they
are intensive on demand when the functions are called.
you can cache them in a class variable*/
}
public function getPostCount() {
// return number of posts
}
public function getRegisterDate() {
// return register date
}
public function getNumberOfLogins() {
// return the number of logins the user has made over time
}
}
?>
have a badge object that is initialised with an id/key and loads dependencies from your database:
<?
class Badge {
protected $dependencies = array();
public function initBadge($id) {
$this->loadDependencies($id);
}
protected function loadDependencies() {
// load data from mysql and store it into dependencies like so:
$dependencies = array(array(
'value' => 300,
'type' => 'PostCount',
'compare => 'greater',
),...);
$this->dependencies = $dependencies;
}
public function getDependencies() {
return $this->dependencies;
}
}
?>
then you could have a class that controls the awarding of batches (you can also do it inside user...)
and checks dependencies and prints failed dependencies etc...
<?
class BadgeAwarder {
protected $badge = null;
protected $user = null;
public function awardBadge($userid,$badge) {
if(is_null($this->badge)) {
$this->badge = new Badge; // or something else for strange freaky badges, passed by $badge
}
$this->badge->initBadge($badge);
if(is_null($this->user)) {
$this->user = new User;
$this->user->initUser($userid);
}
$allowed = $this->checkDependencies();
if($allowed === true) {
// grant badge, print congratulations
} else if(is_array($failed)) {
// sorry, you failed tu full fill thef ollowing dependencies: print_r($failed);
} else {
echo "error?";
}
}
protected function checkDependencies() {
$failed = array();
foreach($this->badge->getDependencies() as $depdency) {
$value = call_user_func(array($this->badge, 'get'.$depdency['type']));
if(!$this->compare($value,$depdency['value'],$dependency['compare'])) {
$failed[] = $dependency;
}
}
if(count($failed) > 0) {
return $failed;
} else {
return true;
}
}
protected function compare($val1,$val2,$operator) {
if($operator == 'greater') {
return ($val1 > $val2);
}
}
}
?>
you can extend to this class if you have very custom batches that require weird calculations.
hope i brought you on the right track.
untested andp robably full of syntax errors.
welcome to the world of object oriented programming. still wanna do this?
Maybe throw the information into a table and check against that? If it's based on the number of posts, have fields for badge_name and post_count and check that way?
Once you're OK with basic record form built after example from Tutorial, you realize you want more professionally designed Record Form. E.g. I don't want to duplicate record form for the same table in User and Admin areas.
1) Does anyone use some mechanism, possibly inheritance, to reduce duplication of almost similar admin and user forms? Is that burdensome or sometimes you better just do with copy-pasting?
2) Has anyone considered it to be a good idea to build some basic Record class
that can determine that among several record forms on this page, the current post is addressed specifically to this record form
that can distinguish between Edit or Delete buttons clicks in some organized fashion.
3) My current practice includes putting all form config code (decorators, validations, initial values) into constructor and form submit handling is put into a separate ProcessSubmit() method to free controller of needless code.
All the above addresses to some expected Record Form functionality and I wonder if there is any guideline, good sample app for such slightly more advanced record handling or people are still reinveting the wheel. Wondering how far you should go and where you should stop with such impovements...
Couple of suggestions:
First of all - Use the init() function instead of constructors to add your elements when you are subclassing the form. The init() function happens after the parameters you pass to the class are set.
Second - Instead of subclassing your form - you can just set an "option" to enable the admin stuff:
class My_Record_Form extends Zend_Form {
protected $_record = null;
public function setRecord($record) {
$this->_record = $record;
}
public function getRecord() {
if ($this->_record === null || (!$this->_record instanceOf My_Record)) {
throw new Exception("Record not set - or not the right type");
}
return $this->_record;
}
protected $_admin = false;
public function setAdmin($admin) {
$this->_admin = $admin;
}
public function getAdmin() { return $this->_admin; }
public function init() {
$record = $this->getRecord();
$this->addElement(......);
$this->addElement(......);
$this->addElement(......);
if ($this->getAdmin()) {
$this->addElement(.....);
}
$this->setDefaults($record->toArray());
}
public function process(array $data) {
if ($this->isValid($data)) {
$record = $this->getRecord();
if (isset($this->delete) && $this->delete->getValue()) {
// delete button was clicked
$record->delete();
return true;
}
$record->setFromArray($this->getValues());
$record->save();
return true;
}
}
}
Then in your controller you can do something like:
$form = new My_Record_Form(array(
'record'=>$record,
'admin'=>My_Auth::getInstance()->hasPermission($record, 'admin')
));
There is nothing "wrong" with making a My_Record_Admin_Form that handles the admin stuff as well - but I found this method keeps all the "record form" code in one single place, and a bit easier to maintain.
To answer section 2: The edit forms in my code are returned from a function of the model: $record->getEditForm() The controller code ends up looking a little like this:
protected $_domain = null;
protected function _getDomain($allowNew = false)
{
if ($this->_domain)
{
return $this->view->domain = $this->_domain;
} else {
$id = $this->_request->getParam('id');
if (($id == 'new' || $id=='') && $allowNew)
{
MW_Auth::getInstance()->requirePrivilege($this->_table, 'create');
$domain = $this->_table->createRow();
} else {
$domain = $this->_table->find($id)->current();
if (!$domain) throw new MW_Controller_404Exception('Domain not found');
}
return $this->view->domain = $this->_domain = $domain;
}
}
public function editAction()
{
$domain = $this->_getDomain(true);
MW_Auth::getInstance()->requirePrivilege($domain,'edit');
$form = $domain->getEditForm();
if ($this->_request->isPost() && $form->process($this->_request->getPost()))
{
if ($form->delete && $form->delete->getValue())
{
return $this->_redirect($this->view->url(array(
'controller'=>'domain',
'action'=>'index',
), null, true));
} else {
return $this->_redirect($this->view->url(array(
'controller'=>'domain',
'action'=>'view',
'id'=>$form->getDomain()->id,
), null, true));
}
}
$this->view->form = $form;
}
So - the actual id of the record is passed in the URI /domain/edit/id/10 for instance. If you were to put multiple of these forms on a page - you should make sure to set the "action" attribute of the form to point to an action specific to that form.
I created a SimpleTable extends Zend_Db_Table and SimpleForm extends Zend_Db_Form classes. Both of these assume that your table has an auto-incrementing ID column.
SimpleTable has a saveForm(SimpleForm $form) function which uses the dynamic binding to match form element names to the columns of the record. I also included an overridable saveFormCustom($form) for any special handling.
The SimpleForm has an abstract setup() which must be overridden to setup the form. I use the init() to do the initial setup (such as adding the hidden ID field).
However, to be honest, I really don't like using the Zend_Form object, I feel like that should be handled in the View, not the Model or Controller.