HTML Helper - Reusable View - PHP - php

I am new to PHP and I was hoping someone could help me determine what the best way to go about creating a reusable view would be. What I have is a form that will be used to Add or Edit data. Therefore the view will be identical except in the case of an Edit the form fields will be populated.
So I am creating an HTML helper that takes 2 parameters. The first will be form data (if there is any{edit}) and the second will be a bool that flags whether this is an insert or and edit(to change form action).
My question is... how should I handle the first parameter if the form is to used to Add data and therefore does not contain data? Optional parameter?
EDIT--
I am using CodeIgnitor as my MVC framework. That is what those form functions are being inherited.. fyi
Thanks..
<?php
if(!defined('BASEPATH') ) exit('No direct script access allowed');
if(!function_exists('WorkOrderForm'))
{
function WorkOrderForm($array = array('$query'),$edit)
{
$formHtml = "";
$attributes = array('class'=>'order','id'=>'orderForm');
if($edit)
{
$formHtml += form_open('order/update',$attributes);
}
else
{
$formHtml += form_open('order/add',$attributes);
}
$formHtml += form_input('name',$query[0]->name);
$formHtml += form_textarea('name',$query[0]->description);
$dropOptions = array('nstarted'=>'Not Started','complete'=>'Done','started'=>'In Progress');
$formHtml += form_dropdown('status',$dropOptions,$query[0]->status);
$formHtml += form_input('name',$query[0]->startDate);
$formHtml += form_input('name',$query[0]->endDate);
$formHtml += form_close();
return $formHtml;
}
}
?>

What are you guys doing? A reusable view is so much easier than this. Simply create a view and save it in the views folder. Add the fields that will appear both when adding and editing data and use an if statement in the value parameter to determine if it has data.
E.g.
Controller:
public function add()
{
$data['method'] = 'add';
$data['form_data'] = $this->some_model->get_something();
$this->load->view('reusable_view', $data);
}
public function edit($id)
{
$data['method'] = 'edit';
$data['form_data'] = $this->some_model->get_something($id);
$this->load->view('reusable_view', $data);
}
View:
<form method="post" action="my_controller/" . <?php echo $method; ?>>
<input type="text" value="<?php if ( isset($form_data['something']) ) {echo $form_data['something'];} " />
</form>
I see no reason to populate a form in a controller as that's not the way MVC works. Using a helper in order to populate the form is also weird, I think you've slightly missed the point of how Codeigniter works.

First off, the default argument should be on the right. And I would default it to 'false' or NULL.
function WorkOrderForm($edit, $array = false)
Then maybe check if $array is not true, and set all the $query[0] to NULL? So something like...
if(!$array) {
$query[0]->name = $query[0]->description = $query[0]->status = null;
}
There might be a more direct approach, but that's one way.

Firstly, if you're sending your query to the helper function as an array, there is no reason to turn it into another array. ie $array = array('$query') should just be $query this way you can access properties like this: $query->name as opposed to $query[0]->name. Secondly, if you're not editing the form entry, your $query would be empty, so you can use that as the trigger for what to return (either the blank form or the populated form):
function WorkOrderForm($query)
{
if($query!='')
{
//$formHTML=populated form
} else {
//$formHTML=empty form
}
return $formHTML;
}
Okay? But, there's a problem... The code you have in your helper won't work. You're using an arithmetic operator += to (assuming) concatenate the form data. What this does is try to add 1 to a string, which will always equal 0. What you're looking for is the .= operator; this will concatenate the form as would be expected. However, this offers you little control over how the form will look (as is, it will put all the form elements side-by-side -- not too pretty). What you could do is instead of concatenating them all together, push them into an array, then echo the form elements out one-by-one:
if($query!=''){
$form_array=array();
array_push($form_array,form_open('order/update',$attributes));
array_push($form_array,form_input('name',$query->name));
array_push($form_array,form_textarea('name',$query->description));
$dropOptions = array('nstarted'=>'Not Started','complete'=>'Done','started'=>'In Progress');
array_push($form_array,form_dropdown('status',$dropOptions,$query->status));
array_push($form_array,form_input('name',$query->startDate));
array_push($form_array,form_input('name',$query->endDate));
array_push($form_array,form_close());
}else{
$form_array=array();
array_push($form_array,form_open('order/add',$attributes));
array_push($form_array,form_open('order/update'));
array_push($form_array,form_input('name'));
array_push($form_array,form_textarea('name'));
$dropOptions = array('nstarted'=>'Not Started','complete'=>'Done','started'=>'In Progress');
array_push($form_array,form_dropdown('status',$dropOptions));
array_push($form_array,form_input('name'));
array_push($form_array,form_input('name'));
array_push($form_array,form_close());
}
return $form_array;
Then to present the form elements, iterate through the $form_array array that was returned:
$form_data='';//blank for new item, or data to populate form with to edit an item
$form_el = WorkOrderForm($form_data);
foreach($form_el as $key=>$val){
echo $val.'<br>';//I just added a <br> here so each form element will be on a new line; change to fit your needs
}
Hope this helps...

Related

PHP: Hide Form after validation (class)

I have a form that is mostly generated by a class named "buildform".
Now every part of the form validates itself on the position it is.
This looks like this:
echo $frm->create_input("customer_nr", "Customer Nr.", "text:empty:int");
The third attribute here are the conditions (here: text field, not empty only integer).
The function "create_input" calls some more function that are validating the form field directly on place when the form is submitted.
I do it this way for multiple reasons:
I can directly color the forms to red when there's an error
I only have to tell the form attributes one time instead of when creating it and validating.
This is really comfortable and until now has made creating forms very easy.
The validation errors for then the users will be stored in a class variable like this:
function add_err($n_errmsg) {
$this->errmsgs[] = $n_errmsg;
return;
}
At the end of the form I show the errors like this:
if(isset($_POST["sbm"])) {
$ret_err = $frm->ret_err();
if(!empty($ret_err)) {
echo $ret_err;
}
else {
// send success mail
}
}
This all works without any problems.
Now I had the idea to hide the form when it's submitted. But then I would have to make sure there are no errors before the form even is loaded!
I wanted to something like
else {
$hideform = true;
// send success mail
}
This currently is not possible as the errors are generated while "generating" the form fields.
If I move the errors to the top the errors are always "empty" there because the validation is done later below...
Do you have an idea how I can solve this?
Do I have to validate the forms before loading them or is there another way?
Thanks!
Best Regards
Toby
Ok, well there are a few ways to solve this.
Basically you are echoing the form html as you go along:
echo $frm->create_input(...);
echo $frm->create_input(...);
what you could do instead is save the html into a string:
$formhtml = '';
$formhtml .= $frm->create_input(...);
$formhtml .= $frm->create_input(...);
if($frm->ret_error()){
echo $formhtml;
//other logic
}else{
//send mail
}
Along the same lines, you could change your form class, so that this is done internaly, and add a show method:
private $html = '';
function create_input(...){
//retrun $ret;
$this->html .= $ret;
function show(){
echo $this->html;
}
$frm->create_input(...);
$frm->create_input(...);
if($frm->ret_error()){
$frm->show();
//other logic
}else{
//send mail
}

Single dynamic values submitted through one form

I am using Jquery UI Selectable. The user has the option to dynamically add new list items to the original setup.
I would like to include a 'clear' button that will give the user the ability to clear each individual item they created by clicking on an X input submit (img).
HTML (php)
if ($this->session->userdata('inactivefilter') == true) {
$inactivefilter = $this->session->userdata('inactivefilter');
$i=0;
foreach ($inactivefilter as $filter)
{
$filterdash = implode('-', explode(' ', $filter));
echo "<li class='ui-state-default' id='$filterdash'>$filter</li>";
echo "<div id=clear>
<form method='POST' action='".base_url()."main/clear_filter'>
<input type='image' name='filtervalue' value='$i' src='".base_url()."img/board/icons/clear.png'></input>
</form>
</div>";
$i++;
}
}
This is where the list is created. specifically the clear_filter action form.
Clear_filter currently 'attempts' to grab the value of '$i' but I don't know how to pass that correctly.
here is the controller:
public function clear_filter()
{
$i = $_POST['filtervalue'];
$this->thread_model->clear_filter($i);
}
I'll omit the clear_filter model due to its irrelevance to the problem.
Essentially, I just need $i to be picked up based on whatever value is clicked on in the dynamic form on the actual page.
Any help would be appreciated!
Well, it seems like I just had things a bit backwards.
The code was more or less correct.
For Codeigniter, you catch the passed input value=$i by using the name ="filtervalue"
Change the controller code to :
$i = $this->input->post('filtervalue');
and $i is set to whatever value was clicked on.

Form input field validation with PHP

I have a couple of fields in the <form>... $fieldset is array of the fields name, it loop them with isset() checking.
I want to apply validation (eg: required input, email) to a few fields, how to apply this from my code logic?
public function actionProfile($id = null) {
$profileModel = new ProfileModel;
// <input> fields name
$fieldset['name'] = array('FirstName', 'LastName');
$fieldset['address'] = array('HouseNumber', 'StreetName', 'Town', 'Location');
$formError = array();
if (isset($_POST['profile'])) {
// Process input event
foreach ($fieldset as $legend => $fields) {
foreach ($fields as $field) {
if (!isset($_POST['profile'][$field])) {
$formError[$legend] = $field;
} else {
$form[$legend][$field] = $_POST['profile'][$field];
}
}
}
if (count($formError) == 0) {
if ($profileModel->saveAddress($form['address'])) {
//Saved to the database.
}
}
}
// Get data from the database
$data['profile'] = $profileModel->find($id);
$view = new View($this->layout, $data)->render();
}
In the view file, it would look something like this:
<input type='text' value=<?php echo $profile['first_name'] name='profile[FirstName]' ?>
<input type='text' value=<?php echo $profile['last_name'] name='profile[LastName]' ?>
Edit: When editing the record via form.. If there is an error (validation) - I want to put user input value back into <input> value instead of value from the database. How can it be done from my code?
You are currently putting validation logic inside the controller. That should go in the Domain Business Object (read more: here and here).
Also, "model" is not a class. Model is a layer in MVC architecture. This layers mostly consists of two types of instances: Domain Objects and Data Mappers. Each with quite different responsibilities.
I think it would be wise to split the verification code from the actual update function.
Have it run through a validator first, checking for length and required inputs. When that passes, you can send all that (formatted) data to the action. If it doesn't pass the validation, return it to the view with additional error information so you can guide the user to fix the problem.
I hope you understand what I'm trying to explain to you. :-).
Use the PHP Filter functions:
http://www.php.net/manual/en/ref.filter.php
Use the Variable Handlers
http://us2.php.net/manual/en/ref.var.php

symfony image inside a button?

I'm trying to include an image inside a button using symfony1.4 with this code:
<?php
echo button_to(image_tag('icon.png')."button_name",'url-goes-here');
?>
But the result i get, instead of what i want is a button with "img src=path/to/the/icon.png button_name" as the value of the button. I've google'd it long enought and found nothing, so i'll try asking here.
In other words:
i'd like to find the way to generate html similar to:<button><img src=..>Text</button> but with a symfony url associated in the onclick option
How can i do it to put an image inside a button with symfony? Am i using the helpers wrong?
Thank you for your time!
You are using Symfonys button_to function incorrectly. From the documentation:
string button_to($name, $internal_uri, $options) Creates an
button tag of the given name pointing to a routed URL
As far as I can tell, the button_to function does not allow for image buttons. Instead, you will probably create the button tag yourself and use symfonys routing to output the url.
I finally created my own helper to display this kind of buttons. I know is not very efficient and flexible but works in my case. Here is the code
function image_button_to($img,$name,$uri,$options){
$sfURL = url_for($uri);
$sfIMG = image_tag($img);
if(isset($options['confirm'])){
$confirm_text = $options['confirm'];
$jsFunction = 'if(confirm(\''.$confirm_text.'\')){ return window.location=\''.$sfURL.'\';}else{return false;}';
}else{
$jsFunction = 'window.location="'.$sfURL.'";';
}
$onclick = 'onclick="'.$jsFunction.'"';
if(isset($options['title'])){
$title = 'title=\''.$options['title'].'\' ';
}else{
$title = '';
}
if(isset($options['style'])){
$style = 'style=\''.$options['style'].'\' ';
}else{
$style = '';
}
return '<button type="button" '.$onclick.$title.$style.' >'.$sfIMG." ".$name.'</button>';
}
With this function as helper, in the templates i just have to:
<?php echo image_button_to('image.png',"button_name",'module/actionUri');?>
hope this be useful for someone ;)

PHP quiz send data to next page

ok, i'm trying to do a quiz...all good by now. but when i'm trying to send the collected data(radio buttons values) through pages i can't get the logic flow. I have the main idea but i can;t put it into practice.
i want to collect all radio values
create an array containing this values
serialize the array
put the serialized array into a hidden input
the problem is that i want to send data on the same page via $_SERVER['PHP_SELF'] and i don;t know when in time to do those things.(cause on "first" page of the quiz i have nothing to receive, then on the "next" page i receive the S_POST['radio_names'] and just after the second page i can get that hidden input). i hope i made myself understood (it's hard even for me to understand what my question is :D )
You could try to use the $_SESSION object instead... For each page of your quiz, store up the results in the $_SESSION array. On the summary page, use this to show your results.
To accomplish this, on the beginning of each page, you could put something like:
<?
session_start();
foreach ($_POST as $name => $resp) {
$_SESSION['responses'][name] = $resp;
}
?>
Then, on the last page, you can loop through all results:
<?
session_start();
foreach ($_SESSION['responses'] as $name => $resp) {
// validate response ($resp) for input ($name)
}
?>
Name your form fields like this:
<input type="radio" name="quiz[page1][question1]" value="something"/>
...
<input type="hidden" name="quizdata" value="<?PHP serialize($quizdata); ?>"/>
Then when you process:
<?PHP
//if hidden field was passed, grab it.
if (! empty($_POST['quizdata'])){
$quizdata = unserialize($_POST['quizdata']);
}
// if $quizdata isn't an array, initialize it.
if (! is_array($quizdata)){
$quizdata = array();
}
// if there's new question data in post, merge it into quizdata
if (! empty($_POST)){
$quizdata = array_merge($quizdata,$_POST['quiz']);
}
//then output your html fields (as seen above)
As another approach, you could add a field to each "page" and track where you are. Then, in the handler at the top of the page, you would know what input is valid:
<?
if (isset($_POST['page'])) {
$last_page = $_POST['page'];
$current_page = $last_page + 1;
process_page_data($last_page);
} else {
$current_page = 1;
}
?>
... later on the page ...
<? display_page_data($current_page); ?>
<input type="hidden" name="page" value="<?= $current_page ?>" />
In this example, process_page_data($page) would handle reading all the input data necessary for the given page number and display_page_data($page) would show the user the valid questions for the given page number.
You could expand this further and create classes to represent pages, but this might give you an idea of where to start. Using this approach allows you to keep all the data handling in the same PHP script, and makes the data available to other functions in the same script.
You want to use a flow such as
if (isset $_POST){
//do the data processing and such
}
else {
/show entry form
}
That's the most straight forward way I know of to stay on the same page and accept for data.

Categories