David John Posted November 5, 2012 Share Posted November 5, 2012 Hi, The more I learn about and use OOP, the more I like it. One of the "Review and Pursue" exercises is implementing an edit page feature, and I would like to know how to go about it. Here's what I am doing (which is not entirely correct): //create a new form set_include_path(get_include_path() . PATH_SEPARATOR . '/my/path'); require('HTML/QuickForm2.php'); $form = new HTML_QuickForm2('editPageForm'); //add something $something = $form->addElement('text', 'something'); $something->setLabel('Something'); $something->addFilter('strip_tags'); //add anotherThing $anotherThing = $form->addElement('text', 'anotherThing'); $anotherThing->setLabel('AnotherThing'); $anotherThing->addFilter('strip_tags'); $submit = $form->addElement('submit', 'submit', array('value'=>'Edit This Page')); //get page from database $q = 'SELECT id, something, anotherThing FROM database WHERE id=:id'; $stmt = $pdo->prepare($q); $r = $stmt->execute(array(':id' => $_GET['id'])); //if OK, fetch record if ($r) { $stmt->setFetchMode(PDO::FETCH_CLASS, 'Class'); $schedule = $stmt->fetch(); //confirm it exists if($schedule) { $q = 'UPDATE database SET something=:something, anotherThing=:anotherThing WHERE id=:id LIMIT 1'; $stmt = $pdo->prepare($q); $r = $stmt->execute(array(':something' => $something->getValue(), ':anotherThing' => $anotherThing->getValue())); } else { throw new Exception('An invalid page ID was provided.'); } } else { throw new Exception('An invalid page ID was provided.'); } Not sure how to properly approach this one, but it's not retrieving the records in the input textbox. Any advice would be greatly appreciated Link to comment Share on other sites More sharing options...
Larry Posted November 6, 2012 Share Posted November 6, 2012 Glad you're enjoying OOP. Here, your order is wrong. To edit a page, you must first retrieve it from the database. Then you use those existing values for the form elements. Then, when the form is submitted, you update the database using those new values. 1 Link to comment Share on other sites More sharing options...
David John Posted November 7, 2012 Author Share Posted November 7, 2012 Thanks for the reply, Larry. After retrieving the value(s) from the database, how are they used for the form elements? On the edit page, I'm creating a form with HTML_QuickForm2, and I used addElement, setLabel, addFilter, etc. The part that I'm struggling with is determining how to echo the input value in QuickForm2 that is to be edited/updated. Link to comment Share on other sites More sharing options...
Antonio Conte Posted November 7, 2012 Share Posted November 7, 2012 From the book: Once you’ve added all the elements, you show the form by simply printing it: echo $form; To explain what happens in detail, is that $form is an object holding several HTML elements in an array. The object must have a method called __toString() that let you use echo on an object. The __toString() method is a magic method like __construct(), and it will be called each time you try to print info from an object. An alternative approach would be to explicitly have a method that would let you echo out the form. As a simple explanation, I wrote this super simple class for you. If you try to run this, you'll see that you can print the list using both "echo $list" and "echo list->printList();". Functionally, these methods are equal to each other. All printList() does is to call __toString(). <?php class HtmlList { private $list = array(); /** * Adds elements to the list */ public function add( $element ) { $this->list[] = $element; } // I am called using $list->printList() public function printList() { return $this->__toString(); // Here we call __toString() } // I am called using echo $list public function __toString() { $out = ""; // Add foreach ( $this->list as $element ) { $out .= "<li>{$element}</li>"; } return $out.'<br />'; } } $list = new HtmlList(); $list->add("First list element"); $list->add("And a new one"); $list->add("After two comes three"); // Print the list echo $list; // Also print the list echo $list->printList(); Hope that helps you to understand. The HTML_QuickForm2 class is obviously a lot more advanced than this example, but it works exactly the same way as the code above. 1 Link to comment Share on other sites More sharing options...
Larry Posted November 7, 2012 Share Posted November 7, 2012 Check out this example: http://pear.php.net/manual/en/package.html.html-quickform2.tutorial.php It uses the addDataSource() method to assign default values to form elements. That's what you want. 1 Link to comment Share on other sites More sharing options...
David John Posted November 8, 2012 Author Share Posted November 8, 2012 From the book: To explain what happens in detail, is that $form is an object holding several HTML elements in an array. The object must have a method called __toString() that let you use echo on an object. The __toString() method is a magic method like __construct(), and it will be called each time you try to print info from an object. An alternative approach would be to explicitly have a method that would let you echo out the form. As a simple explanation, I wrote this super simple class for you. If you try to run this, you'll see that you can print the list using both "echo $list" and "echo list->printList();". Functionally, these methods are equal to each other. All printList() does is to call __toString(). <?php class HtmlList { private $list = array(); /** * Adds elements to the list */ public function add( $element ) { $this->list[] = $element; } // I am called using $list->printList() public function printList() { return $this->__toString(); // Here we call __toString() } // I am called using echo $list public function __toString() { $out = ""; // Add foreach ( $this->list as $element ) { $out .= "<li>{$element}</li>"; } return $out.'<br />'; } } $list = new HtmlList(); $list->add("First list element"); $list->add("And a new one"); $list->add("After two comes three"); // Print the list echo $list; // Also print the list echo $list->printList(); Hope that helps you to understand. The HTML_QuickForm2 class is obviously a lot more advanced than this example, but it works exactly the same way as the code above. Hi, Antonio. Thank you. I appreciate your taking the time to show me an example of __toString. Check out this example: http://pear.php.net/...m2.tutorial.php It uses the addDataSource() method to assign default values to form elements. That's what you want. Thanks, Larry. That's exactly how I went about it. The database entries are outputting correctly, but I keep getting this error message when I try to submit: Call to a member function isSubmitted() on a non-object in /****/views/edit_page.php on line 9 I'll keep at it. Link to comment Share on other sites More sharing options...
Edward Posted November 8, 2012 Share Posted November 8, 2012 Check out this example: http://pear.php.net/...m2.tutorial.php It uses the addDataSource() method to assign default values to form elements. That's what you want. Those magic methods that Antonio was mentioning is something i would like to have seen a bit more of in the book. There are get and set magic methods, actually i was reading in the Yii Cookbook how Yii uses these in CComponent which you extend your class from and then you can omit the get and set when getting or setting properties. Anyway this is off the subject of this thread, so back to the thread. Link to comment Share on other sites More sharing options...
David John Posted November 8, 2012 Author Share Posted November 8, 2012 Quick update: I'm able to get the form to work now, but the values are not updating in the database. Here's an example of my code: require('includes/utilities.inc.php'); $q = 'SELECT id, city, state, zip FROM address WHERE id=:id'; $stmt = $pdo->prepare($q); $r = $stmt->execute(array(':id' => $_GET['id'])); if($r) { $stmt->setFetchMode(PDO::FETCH_CLASS, 'Data'); $info = $stmt->fetch(); } if ($info) { $idInfo = $info->getId(); $cityInfo = $info->getCity(); $stateInfo = $info->getState(); $zipInfo = $info->getZip(); } //create a new form set_include_path(get_include_path() . PATH_SEPARATOR . '/my/path/'); require('HTML/QuickForm2.php'); $form = new HTML_QuickForm2('editPageForm'); $form->addDataSource(new HTML_QuickForm2_DataSource_Array(array('id' => $idInfo, 'city' => $cityInfo, 'state' => $stateInfo, 'zip' => $zipInfo,))); //add city $city = $form->addElement('text', 'city'); $city->setLabel('City'); $city->addFilter('strip_tags'); $city->addRule('required', 'Please enter a city.'); //add state $state = $form->addElement('text', 'state'); $state->setLabel('State'); $state->addFilter('strip_tags'); $state->addRule('required', 'Please enter the state.'); //add zip $zip = $form->addElement('text', 'zip'); $zip->setLabel('Zip Code'); $zip->addFilter('trim'); $zip->addRule('required', 'Please enter the zip code.'); $submit = $form->addElement('submit', 'submit', array('value'=>'Edit')); if ($_SERVER['REQUEST_METHOD'] == 'POST') { if ($form->validate()) { $q = 'UPDATE address SET city=:city, state=:state, zip=:zip WHERE id=:id'; $stmt = $pdo->prepare($q); $r = $stmt->execute(array(':id' => $idInfo, ':city' => $cityInfo, ':state' => $stateInfo, ':zip' => $zipInfo, )); if ($r) { $form->toggleFrozen(true); $form->removeChild($submit); } } } //display login include('includes/header.inc.php'); include('views/edit_page.php'); include('includes/footer.inc.php'); ?> Link to comment Share on other sites More sharing options...
HartleySan Posted November 9, 2012 Share Posted November 9, 2012 David John, just a quick tip: You may want to put your code within CODE tags. It'll make it easier for everyone to read. 1 Link to comment Share on other sites More sharing options...
Larry Posted November 9, 2012 Share Posted November 9, 2012 The problem is you're adding the data source as the original database values with every running of the script, including the form's submission. You should only set the data source when the page is not submitted. 1 Link to comment Share on other sites More sharing options...
David John Posted November 13, 2012 Author Share Posted November 13, 2012 Does the order of code matter (in terms of UPDATE and SELECT)? Also, just curious if the addDataSource array should look something like this: $form->addDataSource(new HTML_QuickForm2_DataSource_Array(array('id' => $id->getValue(), 'city' => $city->getValue(), 'state' => $state->getValue(), 'zip' => $zip->getValue))); I'm still working through it... Link to comment Share on other sites More sharing options...
Larry Posted November 17, 2012 Share Posted November 17, 2012 Yes, it most assuredly matters the order of the code. That's pretty much always true. As for your addDataSource() array, looking at the code you posted earlier, this code doesn’t look remotely correct. 1 Link to comment Share on other sites More sharing options...
michiel Posted January 29, 2013 Share Posted January 29, 2013 Hi,I try to create the edit_page.php I am able to to retrieve the data from the data base and populate the new html quickform using addDataSource method. This is my pdo statement: $stmt = $pdo->prepare('SELECT title, content FROM pages WHERE id=:id');$stmt->execute(array( ':id' => $_GET['id']));$stmt->setFetchMode(PDO::FETCH_CLASS, 'Page');$result=$stmt->fetch();//then I create new form (I dont paste the whole code here) and pull content from database in form using addDataSource. So far it works:$form->addDataSource(new HTML_QuickForm2_DataSource_Array(array( 'title' => $result->getTitle(), 'content'=> $result->getContent() )));When I press submit to UPDATE I get this message:FATAL ERROR: Call to a member function getTitle() on a non-objectsame for the second result: FATAL ERROR: Call to a member function getContent() on a non-objectCan you point me a direction where to look? I suspect this is wrong: $result=$stmt->fetch(); yet it seems to work... Link to comment Share on other sites More sharing options...
Larry Posted January 30, 2013 Share Posted January 30, 2013 That means $result is not the right type of object (i.e., one with those methods). So, yes, you're not fetching it out properly. Link to comment Share on other sites More sharing options...
michiel Posted February 4, 2013 Share Posted February 4, 2013 Solved it! But new problem arises: the edits are 'updated' in the form but not in the database.. Link to comment Share on other sites More sharing options...
michiel Posted February 5, 2013 Share Posted February 5, 2013 Still having trouble :-( The problem is the UPDATE .... WHERE...statement. I dont know how to retireve the page id. I tried with $page->getId( ) ; $_GET['id']. Etc.Now: with the code below I can edit and update the data base, except: I update all the rows (as expected, but hey: the connection works). Any suggestions?<?php # edit page.php require('includes/utilities.inc.php'); //code is dubious!!!!!!!!! if (!$user->canEditPage(new Page)) { header("Location:index.php"); exit;} //-------------------------------------------- // Create a new form: set_include_path(get_include_path() . PATH_SEPARATOR . '/usr/local/pear/share/pear/'); require('HTML/QuickForm2.php'); $form = new HTML_QuickForm2('EditPageForm'); // Het titel invoerveld: $title = $form->addElement('text', 'title'); $title->setLabel('Pagina titel'); $title->addFilter('strip_tags'); $title->addRule('required', 'Vul een pagina titel in'); // Het verhaal invoerveld: $content = $form->addElement('textarea', 'content'); $content->setLabel('Je verhaal'); $content->addFilter('trim'); $content->addRule('required', 'Voer je tekst in'); // De 'voeg toe' button: $submit = $form->addElement('submit', 'submit', array('value'=>'Update deze pagina')); //prepare statement: $q = 'SELECT id, title, content FROM pages WHERE id=:id'; $stmt = $pdo->prepare($q); $r = $stmt->execute(array( ':id' => $_GET['id'])); if ($r) { // fetch the page content from database as object: $stmt->setFetchMode(PDO::FETCH_CLASS, 'Page'); while ($page = $stmt->fetch()) { // populate the form with the data: $form->addDataSource(new HTML_QuickForm2_DataSource_Array(array( 'title' => $page->getTitle(), 'content'=> $page->getContent() ))); } } if ($_SERVER['REQUEST_METHOD'] == 'POST') { // Handle the form submission // Validate the form data: if ($form->validate()) { $q = 'UPDATE pages SET title=:title , content=:content'; //WHERE id=:id'; $stmt = $pdo->prepare($q); $s=$stmt->execute(array(':title'=> $title->getValue(), ':content' => $content->getValue())); //how to retrieve the id of this page? if ($s) { $form->toggleFrozen(true); $form->removeChild($submit); } } // End of form validation IF. } // End of form submission IF. // Show the page: $pageTitle = 'Edit page'; include('includes/header.inc.php'); include('views/edit_page.html'); include('includes/footer.inc.php'); ?> Link to comment Share on other sites More sharing options...
Larry Posted February 6, 2013 Share Posted February 6, 2013 You'll need to store the ID value ($_GET['id'] when the page is first loaded) in a hidden form input (or a session) so that the update query has access to it. Link to comment Share on other sites More sharing options...
michiel Posted February 7, 2013 Share Posted February 7, 2013 Succes! Thank you for the lead. I went for the hidden form input method. It works now. Now up to the next task: delete the page ;-) Michiel Link to comment Share on other sites More sharing options...
Larry Posted February 8, 2013 Share Posted February 8, 2013 Great. Thanks for letting us know! Link to comment Share on other sites More sharing options...
michiel Posted February 12, 2013 Share Posted February 12, 2013 Hi,one last question regarding this code. Specifically this snippet: if (!$user->canEditPage(new Page)) { header("Location:index.php"); exit;}Is this the right way to make the object from the page class? The parameter works, but it doesnt seem right to me. I havent seen this before. The site is coming along fine otherwise. Link to comment Share on other sites More sharing options...
Larry Posted February 13, 2013 Share Posted February 13, 2013 Actually, the canEditPage() method should be passed an instance of the specific page being edited. Link to comment Share on other sites More sharing options...
michiel Posted February 13, 2013 Share Posted February 13, 2013 is this what we want?if (!$user->canEditPage(new Page($_GET['id']))) { header("Location:index.php"); exit;} Link to comment Share on other sites More sharing options...
Larry Posted February 13, 2013 Share Posted February 13, 2013 That might work, although don't you already have a reference to the page record after retrieving it from the database? Or no? Link to comment Share on other sites More sharing options...
michiel Posted February 19, 2013 Share Posted February 19, 2013 Hi,This works ... if (!$user->canEditPage(new Page($id))) { header("Location:index.php"); exit;} Link to comment Share on other sites More sharing options...
Larry Posted February 20, 2013 Share Posted February 20, 2013 Okay, glad it's working for you and thanks for sharing. Link to comment Share on other sites More sharing options...
Recommended Posts