Jump to content
Larry Ullman's Book Forums

Recommended Posts

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 :)

Share this post


Link to post
Share on other sites

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.

  • Upvote 1

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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.

  • Upvote 1

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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');

?>

Share this post


Link to post
Share on other sites

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.

  • Upvote 1

Share this post


Link to post
Share on other sites

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...

Share this post


Link to post
Share on other sites

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.

  • Upvote 1

Share this post


Link to post
Share on other sites

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-object
same for the second result:  FATAL ERROR:  Call to a member function getContent() on a non-object
Can you point me a direction where to look?  I suspect this is wrong: $result=$stmt->fetch();

yet it seems to work...
 

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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');
    ?>

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

That might work, although don't you already have a reference to the page record after retrieving it from the database? Or no?

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

×
×
  • Create New...