I am trying to make a search bar for my application.
I am using the following Mini Framework: https://github.com/panique/mini
What I want to do is have an input field where you type an username, and then a table is displayed underneath with all the information from the Database.
Environment:
PHP 7.4
Apache
CentOS 8
SQL Server 2019
My problem is, I don't know how to pass the input value to the controller and then to the model.
Let me show you what I have tried:
Account Model:
public function getUser($name)
{
$sql = "SELECT * FROM dbo.user_table WHERE Name = :name ORDER BY UserID DESC";
$query = $this->db->prepare($sql);
$query->execute(array(':name' => $name));
return $query->fetchAll();
}
Account Controller:
/**
* ACTION: getUser
*/
public function getUser()
{
if(isset($_POST['search_user'])) {
$checkUser = $this->model->getUser($_POST['username']);
}
}
My View:
<form action="<?php echo URL; ?>account/getUser" method="POST" class="mb20">
<div class="row">
<div class="input-wrap col-sm-12">
<input type="text" placeholder="Type username" name="username" autocomplete="off" />
</div>
</div></br>
<input type="submit" value="Search" name="search_user" />
</form>
I am not sure how to echo the result in the view. Maybe someone here could guide me in the correct direction.
Thanks!
Account Controller:
/**
* ACTION: getUser
*/
public function search()
{
if(isset($_POST['search_user'])) {
$checkUser = $this->model->getUser($_POST['username']);
}
require APP . 'view/search/index.php'; // your search view path
}
Search View:
<form action="<?php echo URL; ?>search" method="POST" class="mb20">
<div class="row">
<div class="input-wrap col-sm-12">
<input type="text" placeholder="Type username" name="username" autocomplete="off" />
</div>
</div></br>
<input type="submit" value="Search" name="search_user" />
</form>
<?php
if (isset($checkUser)) {
echo '<ul>';
foreach ($checkUser as $key => $value) {
echo '<li>';
echo $value->name;
echo '</li>';
}
echo '</ul>';
}
In this way, if there's the $_POST['search_user'], the function search will perform the search and put the result on the $checkUser variable. The variable will be still present on the View because you're requiring it after the $checkUser declaration. Then, the View checks if the variable is present and displays the results.
IMPORTANT
The line echo $value->name; is a dangerous behavior, because it can allow XSS, so, before rendering anything from the database, remember to escape it properly. Some ways to do it:
How to prevent XSS with HTML/PHP?
https://www.php.net/manual/pt_BR/function.strip-tags.php
Related
would like some advice/help on how to connect form controller to post form method in my CI site. I want to data submitted from one viewer to another. Thank you for the help!!
Here is the controller Im using (Form.php), took if from another site:
Form.php
<?php
class Form extends CI_Controller {
public function __construct() {
parent::__construct();
}
// Show form in view page i.e view_page.php
public function form_show() {
$this->load->view("addEdit");
}
// When user submit data on view page, Then this function store data in array.
public function data_submitted() {
$data = array(
'file_name' => $this->input->post('file'),
'title' => $this->input->post('title')
);
// Show submitted data on view page again.
$this->load->view("profile", $data);
}
}
?>
Its to connect to this code:
addEdit.php
<form method="post" action="postAction.php" enctype="multipart/form-data">
<div class="form-group">
<label>Image</label>
<?php if(!empty($imgData['file_name'])){ ?>
<img src="uploads/images/<?php echo $imgData['file_name']; ?>">
<?php } ?>
<input type="file" name="image" class="form-control" >
</div>
<div class="form-group">
<label>Title</label>
<input type="text" name="title" class="form-control" placeholder="Enter title" value="<?php echo !empty($imgData['title'])?$imgData['title']:''; ?>" >
</div>
Back
<input type="hidden" name="id" value="<?php echo !empty($imgData['id'])?$imgData['id']:''; ?>">
<input type="submit" name="imgSubmit" class="btn btn-success" value="SUBMIT">
</form>
When I first tried to make it work I got this error:
404 Page Not Found
The page you requested was not found.
http://culturedkink.com/index.php/register/postAction.php(the url)
postAction.php is the form Im trying to get the data to work from
The end result is to have info submitted from addEdit.php be seen on profile.php with the help of postAction.php
make routes for it first.
config/routes.php
$route['add'] = 'Controller_name/data_submitted';
$route['edit/(:any)'] = 'Controller_name/data_submitted/$1';
where is your add/edit button put this there
for add
Add New
for edit button
$row['id'] is an example i m giving. you can get data by name and id..whatever you want.
Update
//controller
public function data_submitted($id=0) {
$data=array();
$data['dataDetails']=$this->get_profile_data_by_id($id);
$data['view'] = 'folder_name/addEdit';
if ($id > 0) {
$profileArray = [
'file_name' => $this->input->post('file'),
'title' => $this->input->post('title')
];
if ($this->User_model->editById($id, $profileArray)) {
$id = $id;
}
}
else{
$profileArray = [
'file_name' => $this->input->post('file'),
'title' => $this->input->post('title')
];
if ($this->User_model->add($id, $profileArray)) {
$id = $id;
}
}
$this->load->view("profile", $data);
}
form view page
<?php echo isset($dataDetails) ? "Update" : "Add"; ?>
First check your form method and action. Your action does not exist. First check how CI works with form. The action should have a method declared in a controller. The url looks like this,
When you submit the form the data will be submitted in this method. Whatever you need to do with this form data you can do that in this method.
I'm a newbie in OctoberCms and i don't have much knowledge in Laravel also. While self studying I face a request like this it's a Select if record exist query I need to read the database and look for the match and I'm really confuse.
This is my form in form.htm where I design my Form.
use Drufal\DynamicContentManager\Models\MembersVerification;
==
<form data-request="onSend" accept-charset="UTF8" enctype="multipart/form-data">
<div class="form-group">
<label>First Name:</label>
<input type="text" class="form-control" name="first_name" required>
</div>
<div class="form-group">
<label>Middle Name:</label>
<input type="text" class="form-control" name="middle_name">
</div>
<div class="form-group">
<label>Last Name:</label>
<input type="text" class="form-control" name="last_name" required>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary" >Submit</button>
</div>
</form>
and this my model
<?php namespace Drufal\DynamicContentManager\Models;
use Model;
use Input;
/**
* Model
*/
class MembersVerification extends Model
{
use \October\Rain\Database\Traits\Validation;
/*
* Disable timestamps by default.
* Remove this line if timestamps are defined in the database table.
*/
public $timestamps = false;
/**
* #var array Validation rules
*/
public $rules = [
];
/**
* #var string The database table used by the model.
*/
public $table = 'drufal_dynamiccontentmanager_members';
public function onSend(){
$fn = Input::get('first_name');
$mn = Input::get('middle_name');
$ln = Input::get('last_name');
$membertbl=$table::where('first_name', '=', $fn)->first();
if ($membertbl === null) {
echo"
<script>
alert('Successfully');
</script>
";
}else{
echo"NO RESULT";
}
}
}
Help the newbie please.
I think you missed the DB:: in your database request:
$users = Db::table('users')->where('votes', 100)->first();
Maybe this documentation will help you:
https://octobercms.com/docs/database/query#where-clauses
why i'm getting this error every time i click the view button without a value in database??
the black circle has a complete value. the red circle is not
Here is the Sample interface of my testing system:
This is the interface sample i've working on
on model:
public $table = "enduserticket";
public function action()
{
return $this->belongsTo('App\action');
}
public function enduser()
{
return $this->belongsTo('App\enduser');
}
public function status()
{
return $this->belongsTo('App\status');
}
public function users()
{
return $this->belongsTo('App\users');
}
on Controller (resource show):
{
$info = enduserticket::findorfail($id);
return view('user.user_view_table',['info' => $info]);
}
on view page:
Back
Reference No.:
Date:
created_at)); ?>" readonly="true">
Requestor Name:
enduser->eufn. ' ' . $info ->enduser->eumn. ' ' .$info->enduser->euln; ?>" readonly="true">
Position:
enduser->eupos; ?>" readonly="true">
Office/Staff:
enduser->euoffsta; ?>" readonly="true">
Priority Level:
prioritylevel; ?>" readonly="true">
Brief Description of Request:
{{ $info->description }}
Type of Request:
typeofrequest; ?>" readonly="true">
Date Submitted:
datesubmitted)); ?>" readonly="true">
Date Required:
daterequired)); ?>" readonly="true">
Handled By:
users->name; ?>" placeholder="N/A" readonly="true">
Start Action:
action->date_start)); ?>" placeholder="N/A" readonly="true">
End of Action:
Description of Specific Work:
Acceptance Rating:
Remarks:
first off all read how blade template engine works check it out here Displaying data in Blade
You can use data_get() to get some data from variable which might not actually be there. For instance in your case you can do it like this
<div class="form-group row">
<label for="" class="col-sm-3 col-form-label">Position: </label>
<div class="col-sm-8">
<input type="text" class="form-control" id="" value="{{ data_get($enduser, 'eupos') }}" readonly="true">
</div>
</div>
You should read model binding documents your users function is belongsTo which means 1 so it's user and not users opposite of that enduserticket functio is hasMany so populate it to endusertickets
PS
And for show function you probably want to show endtickets of each user to themselves only and not everyone so i suggest you take care of that with providing validation (depend of your usertickets table if there is user_id column is the best if you validate authenticated user with that column this way each user only see their own tickets.
I am not very much sure if my title question is correct, however i am facing sever error of multiple loops within foreach, despite of having only one item in array. I am pasting my code here;
Display (Controller)
$table_data = array(
'table_data' => $this->display_model->get_table_data($table_name),
'edit_table_data'=>$this->display_model->get_table_data($table_name,$row_id)
);
$form_name='edit_'.$table_name;
$this->load->view('header');
$this->load->view($form_name,$table_data);
$this->load->view('footer');
You can see tabe_data and edit_table_data is calling same function with different parameter.
Here i doubt on the time scheduling between these two function calls (which honestly i am wrong because codeigniter manages function calls)
Display_model (Model)
public function get_table_data($table_name,$row_id=null)
{
$return = "";
if ($row_id != null)
{
switch ($table_name) {
case 'user':
//$return = $this->db->where($table_name."_id",$row_id)->get($table_name)->result();
$return = $this->db->select($table_name.'.*,country.country_name')
->join('country','country.country_id=user.user_country_id','left')
->where($table_name.'_id',$row_id)
->get($table_name)->result();
break;
case 'user_document':
//$return = $this->db->where($table_name."_id",$row_id)->get($table_name)->result();
$return = $this->db->select($table_name.'.*,document.document_name')
->join('document','document.document_id=use_document.document_id','left')
->where($table_name.'_id',$row_id)
->get($table_name)->result();
break;
default:
$return = $this->db->where($table_name."_id",$row_id)->get($table_name)->result();
break;
}
if($return != null)
{
return $return;
}
else
{
return "no_data";
}
}
Here is my view where i am getting error
<?php foreach ($edit_table_data as $etd_row) {?>
<form method="post" class="form-horizontal" action="<?php echo site_url('admin/edit_row/user_type/'.$etd_row->user_type_id)?>">
<div class="form-group">
<label class="col-sm-4 control-label">User Type Name</label>
<div class="col-sm-8"><input type="text" class="form-control" name="user_type_name" value="<?php echo $etd_row->user_type_name?>"></div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<div class="col-sm-2 col-sm-offset-2">
<button class="btn btn-primary" type="submit">Edit changes</button>
</div>
</div>
</form>
<?php } ?>
on the foreach loop line, i am given error
Thanks in advance for your comments
Error
A PHP Error was encountered
Severity: Warning
Message: Invalid argument supplied for foreach()
Filename: views/edit_user_type.php
Line Number: 18
Backtrace:
File: C:\wamp\www\gmf\application\views\edit_user_type.php
Line: 18
Function: _error_handler
File: C:\wamp\www\gmf\application\controllers\Display.php
Line: 170
Function: view
File: C:\wamp\www\gmf\index.php
Line: 315
Function: require_once
You'd get this error if $edit_table_data is not an array -- in this case probably a string.
My CI knowledge is a bit rusty, but I guess something along these lines may help you out:
$query = $this->db->select($table_name.'.*,country.country_name')
->join('country','country.country_id=user.user_country_id','left')
->where($table_name.'_id',$row_id)
->get($table_name);
if ($query->num_rows() === 0){
return []; // Make sure we're always returning an array.
// I'd rather handle this stuff in the view...
// Probably some kind of message that shows:
// that there are not results when $edit_table_data is not an array, otherwise loop.
}
return $query->result();
Or you could do something along these lines:
<?php
if (!is_array($edit_table_data)) {
echo 'No results here.';
} else {
foreach ($edit_table_data as $etd_row) { ?>
<form method="post" class="form-horizontal"
action="<?php echo site_url('admin/edit_row/user_type/' . $etd_row->user_type_id) ?>">
<div class="form-group">
<label class="col-sm-4 control-label">User Type Name</label>
<div class="col-sm-8"><input type="text" class="form-control" name="user_type_name"
value="<?php echo $etd_row->user_type_name ?>"></div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<div class="col-sm-2 col-sm-offset-2">
<button class="btn btn-primary" type="submit">Edit changes</button>
</div>
</div>
</form>
<?php
}
}
?>
There does not seem to be a reason to call get_table_data twice, once with and once without $row_id, because you never use $table_data['$table_data'] in the view. In the interests of getting something that works that first call should be eliminated. The revised controller looks like this.
$table_data['edit_table_data'] = $this->display_model->get_table_data($table_name,$row_id) ;
$form_name='edit_'.$table_name;
$this->load->view('header');
$this->load->view($form_name,$table_data);
$this->load->view('footer');
The model code in the question is missing a curly brace } to close this statement.
if ($row_id != null)
{
So it is a little hard to tell exactly what you want to happen if $row_id is not provided. Without further information, my opinion is that get_table_data should not give the second argument a default value. In other words, the function should be defined without a default value for `$row_id - like this.
public function get_table_data($table_name, $row_id)
Without a default value for `$row_id a fatal error occurs if no value is provided. So the controller will need to make sure a value is provided.
Likewise, the controller should always check the return of the model is appropriate, or the model should always return something that the view can use.
get_table_data() contains a lot of repeated code - where($table_name.'_id', $row_id) and get($table_name)->result() appear three times each. By rearranging the logic, the repeating lines can be eliminated to make the function much more concise. Consider this version.
public function get_table_data($table_name, $row_id)
{
if($table_name === 'user')
{
$this->db
->select($table_name.'.*, country.country_name')
->join('country', 'country.country_id = user.user_country_id', 'left');
}
elseif($table_name === 'user_document')
{
$this->db
->select($table_name.'.* ,document.document_name')
->join('document', 'document.document_id = use_document.document_id', 'left');
}
return $this->db
->where($table_name."_id", $row_id)
->get($table_name)
->row();
}
The above returns data from any $table_name where $table_name."_id" == $row_id. Specific "select" and "join" clauses are added in the case of 'user' or 'user_document' tables.
Because you seem to be interested in only one row you should call row() instead of result().
It's important to know that db->row() will return NULL if no records are found. That fact can be used to test the model return and react appropriately. In this case, we do the check in the view. Because there is only one row. no foreach is needed.
<?php if(isset($edit_table_data)) { ?>
<form method="post" class="form-horizontal" action="<?php echo site_url('admin/edit_row/user_type/'.$edit_table_data->user_type_id) ?>">
<div class="form-group">
<label class="col-sm-4 control-label">User Type Name</label>
<div class="col-sm-8"><input type="text" class="form-control" name="user_type_name" value="<?php echo $edit_table_data->user_type_name ?>"></div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<div class="col-sm-2 col-sm-offset-2">
<button class="btn btn-primary" type="submit">Edit changes</button>
</div>
</div>
</form>
<?php
}
else { ?> <div>No Data Available</div> <?php } ?>
I've exhausted all research endpoints (docs, Google, SO, etc.), so I've been driven to ask this question publicly. The very nature of my problem should have been solved by the CodeIgniter 3.0.6 official documentation in the section entitled "Adding Dynamic Data to the View" as I (think) I'm dealing with a variable never making the scope of my controller to be accessed by my view.
I'm adding a single, custom modification to a content publishing app consisting of an edit page fetching content by ID for table data update. 1st, the form;
EDIT.PHP
<div class="row">
<div class="col-md-12">
<h3>Update post</h3>
<form method="post" action="<?php echo base_url('post/update'); ?>" enctype="multipart/form-data">
<div class="form-group">
<label for="title">Title</label>
<input type="text" name="title" id="title" placeholder="News title" value="<?php echo $data['post']->title; ?>" class="form-control" />
</div>
<div class="form-group">
<label for="category">Category</label>
<select name="category" id="category" class="form-control">
<?php foreach($data['categories'] as $category): ?>
<option value="<?php echo $category->idcategory; ?>" <?php echo set_select('category', $category->idcategory); ?>><?php echo $category->title; ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="form-group">
<label for="image">Image</label>
<input type="file" name="image" id="image" class="form-control" placeholder="Upload an image" />
</div>
<div class="form-group">
<label for="body">Post detail</label>
<textarea name="body" id="body" class="form-control" placeholder="Provide news content. Basic HTML is allowed."><?php echo $data['post']->body; ?></textarea>
</div>
<div class="form-group">
<label for="tags">Tags</label>
<input type="text" name="tags" id="tags" value="<?php echo set_value('tags'); ?>" class="form-control" placeholder="Comma separated tags" />
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
I've edited the input values to target the values I need the form populated with in the cases of the Title and Post detail inputs (didn't need to alter anything for the category input, as it's a dropdown working brilliantly), and leaving the tags form input as is to not break output layout while I troubleshoot. Controller/function Post.php was duped from original 'add' function, and I'm including the entirety rather than what I feel is the problematic code chunk;
UPDATE FUNCTION
public function update($idpost) {
$this->load->helper('form');
$data['title'] = 'Update post | News Portal';
$data['post'] = $this->posts->get($idpost);
$this->load->model('category_model', 'cm');
$data['categories'] = $this->cm->get_all();
$this->load->library('form_validation');
$this->form_validation->set_rules('title', 'title', 'trim|required');
$this->form_validation->set_rules('body', 'post body', 'trim|required');
$this->form_validation->set_rules('tags', 'tags', 'required');
if($this->input->method(TRUE) == 'POST' && $this->form_validation->run()) {
$config['upload_path'] = './assets/uploads/';
$config['allowed_types'] = 'gif|jpg|png';
$config['max_size'] = '2000';
$config['max_width'] = '2000';
$config['max_height'] = '1200';
$config['encrypt_name'] = TRUE;
$this->load->library('upload', $config);
if (!$this->upload->do_upload('image')) {
$this->template->alert(
$this->upload->display_errors(),
'danger'
);
} else {
$upload_data = $this->upload->data();
$idpost = $this->posts->add(array(
'iduser' => $this->user->id(),
'title' => $this->input->post('title'),
'body' => $this->input->post('body'),
'image' => $upload_data['file_name']
));
$tags = $this->input->post('tags');
if(strlen($tags) > 0) {
$this->load->model('tag_model', 'tm');
$tags = explode(',', trim($tags));
$tags = array_map(array($this->tm, 'set_tag'), $tags);
$this->load->model('post_tag_model', 'ptm');
foreach($tags as $idtag) {
$this->ptm->add(array(
'idpost' => $idpost,
'idtag' => $idtag
));
}
}
$idcategory = $this->input->post('category');
if($idcategory) {
$this->load->model('post_category_model', 'pcm');
$this->pcm->add(array(
'idpost' => $idpost,
'idcategory' => $idcategory
));
}
$this->template->alert(
'Updated news item successfully',
'success'
);
redirect('post');
return;
}
}
$this->template->view('post/edit', $data);
}
This variable ($tags) is somehow lost between the controller and view, confirmed by using var_dump($this->_ci_cached_vars); to check all available objects within that corresponding view. I just need the variable $tags to repopulate with the data appropriate to the form input. How is it that there was no initialization of $tags within this function?
I COMPLETELY understand that the variable WILL NEVER be passed to the corresponding view because it's non-existant (as confirmed by my previous var_dump), but I'm lost as to how exactly to draw $tags within function scope so it can help form input to retrieve targeted data? All the other inputs are repopulating as needed. And, as an aside, I actually tracked down the original developer of this project and conferred with him on this. I tried to wrangle two approaches he outlined, but I ended up getting blank or erroring pages. The closest I could come theoretically to his second point - adapting a bit of code already in the news view partial;
<?php
if($tags = get_tags($data['news']->idpost)) {
echo '<div class="tags">';
echo 'Terms: ';
foreach($tags as $tag) {
echo ' <i class="fa fa-fw fa-link"></i> ' . $tag->title . ' ';
}
echo '</div>';
}
?>
which always ends in Undefined Index/Variable or some other damnable error message that I try to break my neck to solve, but just keep sinking further into the quagmire (lol!). It SEEMS simple to me, the basis of my problem, but I keep going around, and around, and around until I'm drunk dizzy and ten time more lost than I started out. Could someone provide a crumb of understanding?
I mean, I'm getting a conniption fit as it should be as simple as the answer provided here # Passing variable from controller to view in CodeIgniter. But, alas, 'tis not...thanks in advance for any clarificative leads.
#DFriend - I'm not wanting to alter the structure too much as ;
a) the code this is duped from is working and the only goal is to pull data from the appropriate table into that form input,
b) I don't want to disturb current functionality or inadvertently open another issue, and,
c) I'm trying to zero in on the correct elements.
Thank you for your time and answer, #DFriend.
I believe that the reason for your problems is because of the redirect call. By calling that you are essentially putting a new URL into the browser. Websites are stateless. Without using sessions or other means each request for a URL is unique. So by calling redirect you are wiping any knowledge of $tags from existence.
You can probably get around this by pushing $tags into the $_SESSION array and then checking for and retrieving it in the post controller.
Alternately, if post() is in the same controller you can simple call it instead of the redirect. post() will have be modified to accept an argument, or $tags will have to be a property of the controller class.
So to call directly to post, instead of
redirect('post');
return;
do this
$this->post($tags);
return;
Then define post to accept an optional argument
public function post($tags=null){
//somewhere in here
if(isset($tags)){
//$data is sent to views
$data['tags'] = $tags;
}
}
Expanded Answer:
How to implement a Post/Read/Get pattern in Codeigniter and still use field validation and repopulated form fields.
Using Codeigniter (CI) to implement a PRG pattern for processing requires an extension of the CI_Form_validation class. The code that follows should be in /application/libraries/MY_Form_validation.php
<?php
/**
* The base class (CI_Form_validation) has a protected property - _field_data
* which holds all the information provided by validation->set_rules()
* and all the results gathered by validation->run()
* MY_Form_validation provides a public 'setter' and 'getter' for that property.
*
*/
class MY_Form_validation extends CI_Form_validation{
public function __construct($rules = array())
{
parent::__construct($rules);
}
//Getter
public function get_field_data() {
return $this->_field_data;
}
//Setter
public function set_field_data($param=array()){
$this->_field_data = $param;
}
}
Without the template library you are using I fell back on $this->load->view(). And without access to your models and associated data I had to make some assumptions and, in some cases, leave db calls out.
Overall, I tried not to alter the structure too much. But I also wanted to demonstrate a couple handy uses of the form helper functions.
for the most part the restructuring I did was mostly an attempt at providing a clear example. If I succeed as showing the concepts you should be able to implement this fairly easily.
Here's the revised view. It makes more use of the 'form' helper functions.
<head>
<style>
.errmsg {
color: #FF0000;
font-size: .8em;
height: .8em;
}
</style>
</head>
<html>
<body>
<div class="row">
<div class="col-md-12">
<h3>Update post</h3>
<?php
echo form_open_multipart('posts/process_posting');
echo form_hidden('idpost', $idpost);
?>
<div class="form-group">
<label for="title">Title</label>
<input type="text" name="title" id="title" placeholder="News title" value="<?php echo $title; ?>" class="form-control" />
<span class="errmsg"><?php echo form_error('title'); ?> </span>
</div>
<div class="form-group">
<label for="category">Category</label>
<?php
echo form_dropdown('category', $categories, $selected_category, ['class' => 'form-control']);
?>
</div>
<div class="form-group">
<label for="image">Image</label>
<input type="file" name="image" id="image" class="form-control" placeholder="Upload an image" />
</div>
<div class="form-group">
<label for="body">Post detail</label>
<textarea name="body" id="body" class="form-control" placeholder="Provide news content. Basic HTML is allowed."><?php echo $body; ?></textarea>
<span class="errmsg"><?php echo form_error('body'); ?> </span>
</div>
<div class="form-group">
<label for="tags">Tags</label>
<input type="text" name="tags" id="tags" value="<?php echo $tags ?>" class="form-control" placeholder="Comma separated tags" />
<span class="errmsg"><?php echo form_error('tags'); ?> </span>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
<?= form_close(); ?>
</div>
</div>
</body>
</html>
The crux of this solution is to store form_validation->_field_data in the session when validation fails. The view loading function looks for a failure flag in session data and, if the flag is true, restores form_validation->_field_data to the current form_validation instance.
I tried to put a lot of explanation in the comments. What follows in the controller complete with display and processing methods.
class Posts extends CI_Controller
{
function __construct()
{
parent::__construct();
$this->load->library('session');
$this->load->library('form_validation', NULL, 'fv');
}
/**
* post()
* In this example the function that shows the posting edit page
* Note the use of the optional argument with a NULL default
*/
function post($idpost = NULL)
{
$this->load->model('category_model', 'cm');
$categories = $this->cm->get_all();
/*
* Your model is returning an array of objects.
* This example is better served by an array of arrays.
* Why? So the helper function form_dropdown() can be used in the view.
*
* Rather than suggest changing the model
* these lines make the conversion to an array of arrays.
*/
$list = [];
foreach($categories as $category)
{
$list[$category->idcategory] = $category->title;
}
$data['categories'] = $list; // $data is used exclusivly to pass vars to the view
if(!empty($idpost))
{
//if argument is passed, a database record is retrieved.
$posting = $this->posts->get($idpost);
//Really should test for a valid return from model before using it.
//Skipping that for this example
$title = $posting->title;
$body = $posting->body;
//assuming your model returns the next two items like my made up model does
$selected_category = $posting->category;
$tags= $posting->tags;
}
else
//a failed validation (or a brand new post)
{
//check for failed validation
if($this->session->failed_validation)
{
// Validation failed. Restore validation results from session.
$this->fv->set_field_data($_SESSION['validated_fields']);
}
}
//setup $data for the view
/* The 'idpost' field was add to demonstrate how hidden data can be pasted to and from
* a processing method. In this case it would be useful in providing a 'where = $value'
* clause on a database update.
* Also, a lack of any value could be used indicate an insert is requried for a new record.
*
* Notice the ternary used to provide a default value to set_value()
*/
$data['idpost'] = $this->fv->set_value('idpost', isset($idpost) ? $idpost : NULL);
$data['title'] = $this->fv->set_value('title', isset($title) ? $title : NULL);
$data['body'] = $this->fv->set_value('body', isset($body) ? $body : NULL);
$data['tags'] = $this->fv->set_value('tags', isset($tags) ? $tags : NULL);
$data['selected_category'] = $this->fv->set_value('category', isset($selected_category) ? $selected_category : '1');
$this->load->view('post_view', $data);
}
public function process_posting()
{
if($this->input->method() !== 'post')
{
//somebody tried to access this directly - bad user, bad!
show_error('The action you have requested is not allowed.', 403);
// return; not needed because show_error() ends with call to exit
}
/*
* Note: Unless there is a rule set for a field the
* form_validation->_field_data property won't have
* any knowledge of the field.
* In Addition, the $_POST array from the POST call to the this page
* will be GONE when we redirect back to the view!
* So it won't be available to help repopulate the <form>
*
* Rather than making a copy of $_POST in $_SESSION we will rely
* completely on form_validation->_field_data
* to repopulate the form controls.
* That can only work if there is a rule set
* for ANY FIELD you want to repopulate after failed validation.
*/
$this->fv->set_rules('idpost', 'idpost', 'trim'); //added any rule so it will repopulate
// in this example required would not be useful for 'idpost'
$this->fv->set_rules('title', 'title', 'trim|required');
$this->fv->set_rules('body', 'post body', 'trim|required');
$this->fv->set_rules('tags', 'tags', 'required');
//add rule for category so it can be repopulated correctly if validation fails
$this->fv->set_rules('category', 'category', 'required');
if(!$this->fv->run())
{
// Validation failed. Make note in session data
$this->session->set_flashdata('failed_validation', TRUE);
//capture and save the validation results
$this->session->set_flashdata('validated_fields', $this->fv->get_field_data());
//back to 'posts/index' with server code 303 as per PRG pattern
redirect('posts/post', 'location', 303);
return;
}
// Fields are validated
// Do the image upload and other data storage, set messges, etc
// checking for $this->input->idpost could be used in this block
// to determine whether to call db->insert or db->update
//
// When process is finished, GET the page appropriate after successful <form> post
redirect('controller/method_that_runs_on_success', 'location', 303);
}
//end Class
}
Questions? Comments? Insults?