Does anyone have experience of uploading a series of files to a web server with FuelPHP?
My current setup adds content to a database from a Form, but I'd like to process images at this point too - so basically move them to my web server when submitting a form.
Is this simple to do?
I have my 'action_add()' method in my controller, but not sure how to update it to loop through all my file fields and move files.
public function action_add()
{
$val = Model_Article::validate('add_article');
if ($val->run())
{
$status = (Input::post('save_draft') ? 0 : 1);
if ( ! $val->input('category_id'))
{
$category_id = null;
}
else
{
$category_id = $val->validated('category_id');
}
$article = new Model_Article(array(
'user_id' => $this->user_id,
'category_id' => $category_id,
'title' => $val->validated('title'),
'body' => $val->validated('body'),
'published' => $status,
));
if ($article->save())
{
Session::set_flash('success', 'Article successfully added.');
}
else
{
Session::set_flash('error', 'Something went wrong, '.
'please try again!');
}
Response::redirect('articles/add');
}
$this->template->title = 'Add Article';
$this->template->content = View::forge('articles/add')
->set('categories', Model_Category::find('all'), false)
->set('val', Validation::instance('add_article'), false);
}
My Form:
<h2>Add an Article</h2>
<p>Publish a new article by filling the form below.</p>
<div class="options">
<div class="option">
<?php echo Html::anchor('articles', 'View Articles'); ?>
</div>
<div class="option">
<?php echo Html::anchor('categories/add', 'Add a Category'); ?>
</div>
</div>
<?php echo $val->show_errors(); ?>
<?php echo Form::open(array('enctype' => 'multipart/form-data')); ?>
<?php $select_categories = array(null => 'Uncategorized'); ?>
<?php foreach ($categories as $category): ?>
<?php $select_categories[$category->id] = $category->name; ?>
<?php endforeach; ?>
<div class="input select">
<?php echo Form::label('Category', 'category_id'); ?>
<?php echo Form::select('category_id', e($val->input('category_id')),
$select_categories); ?>
</div>
<div class="input text required">
<?php echo Form::label('Title', 'title'); ?>
<?php echo Form::input('title', e($val->input('title')),
array('size' => '30')); ?>
</div>
<div class="input textarea required">
<?php echo Form::label('Body', 'body'); ?>
<?php echo Form::textarea('body', e($val->input('body')),
array('rows' => 4, 'cols' => 40)); ?>
</div>
<div class="input textarea required">
<?php echo FORM::file('filename'); ?>
</div>
<div class="input submit">
<?php echo Form::submit('add_article', 'Publish'); ?>
<?php echo Form::submit('save_draft', 'Save Draft'); ?>
</div>
<?php echo Form::close(); ?>
Many thanks for any pointers.
Okay I can give you some instruction.
First fuelphp upload documentation
Hope it helps sorry if there are typos in it
public function action_add()
{
$val = Model_Article::validate('add_article'); //<-- maybe its just me but I never saw any similar to this in fuelphp sorry about this if I'm wrong
// if your form validation is okay than continue with everyhing else
if ($val->run())
{
$article = Model_Article::forge();
// Custom configuration for this upload
$config = array(
'path' => DOCROOT.DS.'foldername/tomove/your/images',
'randomize' => true,
'ext_whitelist' => array('img', 'jpg', 'jpeg', 'gif', 'png'),
);
Upload::process($config);
// if a valid file is passed than the function will save, or if its not empty
if (Upload::is_valid())
{
// save them according to the config
Upload::save();
//if you want to save to tha database lets grab the file name
$value = Upload::get_files();
$article->your_file_input_name = $value[0]['saved_as'];
}
$status = (Input::post('save_draft') ? 0 : 1);
if ( ! $val->input('category_id'))
{
$category_id = null;
}
else
{
$category_id = $val->validated('category_id');
}
$article->user_id = $this->user_id;
$article->category_i = $category_id;
$article->title = $val->validated('title');
$article->body = $val->validated('body');
$article->published = $status;
if ($article->save())
{
Session::set_flash('success', 'Article successfully added.');
}
else
{
Session::set_flash('error', 'Something went wrong, '.
'please try again!');
}
Response::redirect('articles/add');
}
$this->template->title = 'Add Article';
$this->template->content = View::forge('articles/add')
->set('categories', Model_Category::find('all'), false)
->set('val', Validation::instance('add_article'), false);
}
Related
I tried to implement standard PHP logic for add, edit articles to blog, so i have add method:
public function add()
{
$this->load->model('admin/Blog_Model');
if (!empty($this->input->post())) {
$user = $this->Blog_Model->addPost($this->input->post());
}
$this->getForm();
}
edit method:
public function edit($id = '')
{
$this->load->model('admin/Blog_Model');
if (!empty($this->input->post())) {
var_dump($id); exit;
$user = $this->Blog_Model->editPost($this->input->post(), $id);
}
$this->getForm($id);
}
and getForm method:
public function getForm($id = '')
{
if (!empty($id)) {
$post = $this->Blog_Model->getPost($id);
$data['action'] = 'admin/blog/edit';
} else {
$data['action'] = 'admin/blog/add';
}
$data['formTitle'] = array(
'name' => 'title',
'id' => 'content-title',
'value' => isset($post['title']) ? $post['title'] : '',
'placeholder' => 'Заглавие',
'class' => 'form-control'
);
$data['formContent'] = array(
'name' => 'content',
'id' => 'content-blog',
'value' => isset($post['content']) ? $post['content'] : '',
'placeholder' => 'Съдържание',
);
$data['formButton'] = array(
'type' => 'submit',
'content'=> 'Изпрати',
'class'=> 'btn btn-primary btn-block btn-flat'
);
$data['head'] = $this->load->view('admin/head', NULL, TRUE);
$data['left_column'] = $this->load->view('admin/left_column', NULL, TRUE);
$this->load->view('admin/header', $data);
$this->load->view('admin/blog_form', $data);
$this->load->view('admin/footer');
}
and blog_form view with form:
<div class="box-body pad">
<?php echo form_open($action); ?>
<div class="box-body">
<div class="form-group">
<label for="content-title">Заглавие:</label>
<?php echo form_input($formTitle); ?>
</div>
<div class="form-group">
<label for="content_blog">Съдържание:</label>
<?php echo form_textarea($formContent); ?>
</div>
<div class="col-xs-12 col-md-3 pull-right">
<?php echo form_button($formButton); ?>
</div>
</div>
<?php echo form_close(); ?>
</div>
So .. everything works perfect, but i have problem with this part:
if (!empty($id)) {
$post = $this->Blog_Model->getPost($id);
$data['action'] = 'admin/blog/edit';
} else {
$data['action'] = 'admin/blog/add';
}
if it's edit i want to send id like GET parameter. I think the problem is there than i does not use standard GET parameters instead of site_url function, when i show all articles here:
<?php foreach ($posts as $post) { ?>
<tr>
<td><?php echo $post['id']; ?></td>
<td><?php echo $post['title']; ?></td>
<td><?php echo $post['content']; ?></td>
<td><div class="btn-group">
Редактирай
Изтрий
</div></td>
</tr>
<?php } ?>
Try to change
if (!empty($id)) {
$post = $this->Blog_Model->getPost($id);
$data['action'] = 'admin/blog/edit';
} else {
$data['action'] = 'admin/blog/add';
}
to
if (!empty($id)) {
$post = $this->Blog_Model->getPost($id);
$data['action'] = 'admin/blog/edit/'.$id; // pass $id to edit controller
} else {
$data['action'] = 'admin/blog/add';
}
First of all, I inherited the code for this site so I'm having trouble figuring out some of it. The problem is with our blog page creation. When I try to create a new blog page (using an admin site) I get an error before each element. It only appears on the create side and works fine on the edit side. I'm also still able to create the new post, it just has the notices. It was working as of about 24 hours ago and nothing was changed in any of the code.
The errors I'm getting are :
> A PHP Error was encountered
>Severity: Notice
>Message: Undefined property: stdClass::$keywords
>Filename: admin/form.php
>Line Number: 94
as well as:
> $title, Line Number: 28
> $comments_enabled, line 122
>$slug, line 33
>$status, line 38
>$body, line 53
>$preview_hash, line 58
I've narrowed it down to the $extra array code that doesn't seem to be getting read (maybe?). Here is my create function:
public function create()
{
// They are trying to put this live
if ($this->input->post('status') == 'live')
{
role_or_die('blog', 'put_live');
$hash = "";
}
else
{
$hash = $this->_preview_hash();
}
$post = new stdClass();
// Get the blog stream.
$this->load->driver('Streams');
$stream = $this->streams->streams->get_stream('blog', 'blogs');
$stream_fields = $this->streams_m->get_stream_fields($stream->id, $stream->stream_namespace);
// Get the validation for our custom blog fields.
$blog_validation = $this->streams->streams->validation_array($stream->stream_slug, $stream->stream_namespace, 'new');
// Combine our validation rules.
$rules = array_merge($this->validation_rules, $blog_validation);
// Set our validation rules
$this->form_validation->set_rules($rules);
if ($this->input->post('created_on'))
{
$created_on = strtotime(sprintf('%s %s:%s', $this->input->post('created_on'), $this->input->post('created_on_hour'), $this->input->post('created_on_minute')));
}
else
{
$created_on = now();
}
if ($this->form_validation->run())
{
// Insert a new blog entry.
// These are the values that we don't pass through streams processing.
$extra = array(
'title' => $this->input->post('title'),
'slug' => $this->input->post('slug'),
'category_id' => $this->input->post('category_id'),
'keywords' => Keywords::process($this->input->post('keywords')),
'body' => $this->input->post('body'),
'status' => $this->input->post('status'),
'created_on' => $created_on,
'created' => date('Y-m-d H:i:s', $created_on),
'comments_enabled' => $this->input->post('comments_enabled'),
'author_id' => $this->current_user->id,
'type' => $this->input->post('type'),
'parsed' => ($this->input->post('type') == 'markdown') ? parse_markdown($this->input->post('body')) : '',
'preview_hash' => $hash
);
if ($id = $this->streams->entries->insert_entry($_POST, 'blog', 'blogs', array('created'), $extra))
{
$this->pyrocache->delete_all('blog_m');
$this->session->set_flashdata('success', sprintf($this->lang->line('blog:post_add_success'), $this->input->post('title')));
// Blog article has been updated, may not be anything to do with publishing though
Events::trigger('post_created', $id);
// They are trying to put this live
if ($this->input->post('status') == 'live')
{
// Fire an event, we're posting a new blog!
Events::trigger('post_published', $id);
}
}
else
{
$this->session->set_flashdata('error', lang('blog:post_add_error'));
}
// Redirect back to the form or main page
($this->input->post('btnAction') == 'save_exit') ? redirect('admin/blog') : redirect('admin/blog/edit/'.$id);
}
else
{
// Go through all the known fields and get the post values
$post = new stdClass;
/*
---------Gives array to string error without the if statement-------
foreach ($this->validation_rules as $key => $field)
{
$post->$field['field'] = set_value($field['field']);
}*/
foreach ($this->validation_rules as $key => $field)
{
if (isset($_POST[$field['field']]))
{
$post->$field['field'] = set_value($field['field']);
}
}
$post->created_on = $created_on;
// if it's a fresh new article lets show them the advanced editor
$post->type or $post->type = 'wysiwyg-advanced';
}
// Set Values
$values = $this->fields->set_values($stream_fields, null, 'new');
// Run stream field events
$this->fields->run_field_events($stream_fields, array(), $values);
$this->template
->title($this->module_details['name'], lang('blog:create_title'))
->append_metadata($this->load->view('fragments/wysiwyg', array(), true))
->append_js('jquery/jquery.tagsinput.js')
->append_js('module::blog_form.js')
->append_js('module::blog_category_form.js')
->append_css('jquery/jquery.tagsinput.css')
->set('stream_fields', $this->streams->fields->get_stream_fields($stream->stream_slug, $stream->stream_namespace, $values))
->set('post', $post)
->build('admin/form');
}
The $extra array doesn't seem to be getting read. These errors also came about at the same time as an array to string error. I was hoping the fix for that would fix both but so far no good. The errors are coming from two sources as well. I was thinking it might be the if statement not being read? Or maybe it has something to do with the $validation_rules at the beginning of the file?
This bit of code is the first one to fail (for $type) and the only one through the actual controller.php file and the rest (keywords, title, slug, etc) fail under the form.php file.
$post->type or $post->type = 'wysiwyg-advanced';
Any advice or help is appreciated. I'm still fairly new to PHP and CodeIgniter but it looks like it'll be to much work to overhaul the website.
Thank you.
Edit: I've added my edit function below, maybe someone else can see why it works but not my create function.
public function edit($id = 0)
{
$id or redirect('admin/blog');
$post = $this->blog_m->get($id);
// They are trying to put this live
if ($post->status != 'live' and $this->input->post('status') == 'live')
{
role_or_die('blog', 'put_live');
}
// If we have keywords before the update, we'll want to remove them from keywords_applied
$old_keywords_hash = (trim($post->keywords) != '') ? $post->keywords : null;
$post->keywords = Keywords::get_string($post->keywords);
// If we have a useful date, use it
if ($this->input->post('created_on'))
{
$created_on = strtotime(sprintf('%s %s:%s', $this->input->post('created_on'), $this->input->post('created_on_hour'), $this->input->post('created_on_minute')));
}
else
{
$created_on = $post->created_on;
}
// Load up streams
$this->load->driver('Streams');
$stream = $this->streams->streams->get_stream('blog', 'blogs');
$stream_fields = $this->streams_m->get_stream_fields($stream->id, $stream->stream_namespace);
// Get the validation for our custom blog fields.
$blog_validation = $this->streams->streams->validation_array($stream->stream_slug, $stream->stream_namespace, 'new');
$blog_validation = array_merge($this->validation_rules, array(
'title' => array(
'field' => 'title',
'label' => 'lang:global:title',
'rules' => 'trim|htmlspecialchars|required|max_length[100]|callback__check_title['.$id.']'
),
'slug' => array(
'field' => 'slug',
'label' => 'lang:global:slug',
'rules' => 'trim|required|alpha_dot_dash|max_length[100]|callback__check_slug['.$id.']'
),
));
// Merge and set our validation rules
$this->form_validation->set_rules(array_merge($this->validation_rules, $blog_validation));
$hash = $this->input->post('preview_hash');
if ($this->input->post('status') == 'draft' and $this->input->post('preview_hash') == '')
{
$hash = $this->_preview_hash();
}
//it is going to be published we don't need the hash
elseif ($this->input->post('status') == 'live')
{
$hash = '';
}
if ($this->form_validation->run())
{
$author_id = empty($post->display_name) ? $this->current_user->id : $post->author_id;
$extra = array(
'title' => $this->input->post('title'),
'slug' => $this->input->post('slug'),
'category_id' => $this->input->post('category_id'),
'keywords' => Keywords::process($this->input->post('keywords'), $old_keywords_hash),
'body' => $this->input->post('body'),
'status' => $this->input->post('status'),
'created_on' => $created_on,
'updated_on' => $created_on,
'created' => date('Y-m-d H:i:s', $created_on),
'updated' => date('Y-m-d H:i:s', $created_on),
'comments_enabled' => $this->input->post('comments_enabled'),
'author_id' => $author_id,
'type' => $this->input->post('type'),
'parsed' => ($this->input->post('type') == 'markdown') ? parse_markdown($this->input->post('body')) : '',
'preview_hash' => $hash,
);
if ($this->streams->entries->update_entry($id, $_POST, 'blog', 'blogs', array('updated'), $extra))
{
$this->session->set_flashdata(array('success' => sprintf(lang('blog:edit_success'), $this->input->post('title'))));
// Blog article has been updated, may not be anything to do with publishing though
Events::trigger('post_updated', $id);
// They are trying to put this live
if ($post->status != 'live' and $this->input->post('status') == 'live')
{
// Fire an event, we're posting a new blog!
Events::trigger('post_published', $id);
}
}
else
{
$this->session->set_flashdata('error', lang('blog:edit_error'));
}
// Redirect back to the form or main page
($this->input->post('btnAction') == 'save_exit') ? redirect('admin/blog') : redirect('admin/blog/edit/'.$id);
}
// Go through all the known fields and get the post values
foreach ($this->validation_rules as $key => $field)
{
if (isset($_POST[$field['field']]))
{
$post->$field['field'] = set_value($field['field']);
}
}
$post->created_on = $created_on;
// Set Values
$values = $this->fields->set_values($stream_fields, $post, 'edit');
// Run stream field events
$this->fields->run_field_events($stream_fields, array(), $values);
$this->template
->title($this->module_details['name'], sprintf(lang('blog:edit_title'), $post->title))
->append_metadata($this->load->view('fragments/wysiwyg', array(), true))
->append_js('jquery/jquery.tagsinput.js')
->append_js('module::blog_form.js')
->set('stream_fields', $this->streams->fields->get_stream_fields($stream->stream_slug, $stream->stream_namespace, $values, $post->id))
->append_css('jquery/jquery.tagsinput.css')
->set('post', $post)
->build('admin/form');
}
Edit2: I've added the whole form.php that is sending most of the errors.
<section class="title">
<?php if ($this->method == 'create'): ?>
<h4><?php echo lang('blog:create_title') ?></h4>
<?php else: ?>
<h4><?php echo sprintf(lang('blog:edit_title'), $post->title) ?></h4>
<?php endif ?>
</section>
<section class="item">
<div class="content">
<?php echo form_open_multipart() ?>
<div class="tabs">
<ul class="tab-menu">
<li><span><?php echo lang('blog:content_label') ?></span></li>
<?php if ($stream_fields): ?><li><span><?php echo lang('global:custom_fields') ?></span></li><?php endif; ?>
<li><span><?php echo lang('blog:options_label') ?></span></li>
</ul>
<!-- Content tab -->
<div class="form_inputs" id="blog-content-tab">
<fieldset>
<ul>
<li>
<label for="title"><?php echo lang('global:title') ?> <span>*</span></label>
<div class="input"><?php echo form_input('title', htmlspecialchars_decode($post->title), 'maxlength="100" id="title"') ?></div>
</li>
<li>
<label for="slug"><?php echo lang('global:slug') ?> <span>*</span></label>
<div class="input"><?php echo form_input('slug', $post->slug, 'maxlength="100" class="width-20"') ?></div>
</li>
<li>
<label for="status"><?php echo lang('blog:status_label') ?></label>
<div class="input"><?php echo form_dropdown('status', array('draft' => lang('blog:draft_label'), 'live' => lang('blog:live_label')), $post->status) ?></div>
</li>
<li class="editor">
<label for="body"><?php echo lang('blog:content_label') ?> <span>*</span></label><br>
<div class="input small-side">
<?php echo form_dropdown('type', array(
'html' => 'html',
'markdown' => 'markdown',
'wysiwyg-simple' => 'wysiwyg-simple',
'wysiwyg-advanced' => 'wysiwyg-advanced',
), $post->type) ?>
</div>
<div class="edit-content">
<?php echo form_textarea(array('id' => 'body', 'name' => 'body', 'value' => $post->body, 'rows' => 30, 'class' => $post->type)) ?>
</div>
</li>
</ul>
<?php echo form_hidden('preview_hash', $post->preview_hash)?>
</fieldset>
</div>
<?php if ($stream_fields): ?>
<div class="form_inputs" id="blog-custom-fields">
<fieldset>
<ul>
<?php foreach ($stream_fields as $field) echo $this->load->view('admin/partials/streams/form_single_display', array('field' => $field), true) ?>
</ul>
</fieldset>
</div>
<?php endif; ?>
<!-- Options tab -->
<div class="form_inputs" id="blog-options-tab">
<fieldset>
<ul>
<li>
<label for="category_id"><?php echo lang('blog:category_label') ?></label>
<div class="input">
<?php echo form_dropdown('category_id', array(lang('blog:no_category_select_label')) + $categories, #$post->category_id) ?>
[ <?php echo anchor('admin/blog/categories/create', lang('blog:new_category_label'), 'target="_blank"') ?> ]
</div>
</li>
<?php if ( !module_enabled('keywords')): ?>
<?php echo form_hidden('keywords'); ?>
<?php else: ?>
<li>
<label for="keywords"><?php echo lang('global:keywords') ?></label>
<div class="input"><?php echo form_input('keywords', $post->keywords, 'id="keywords"') ?></div>
</li>
<?php endif; ?>
<li class="date-meta">
<label><?php echo lang('blog:date_label') ?></label>
<div class="input datetime_input">
<?php echo form_input('created_on', date('Y-m-d', $post->created_on), 'maxlength="10" id="datepicker" class="text width-20"') ?>
<?php echo form_dropdown('created_on_hour', $hours, date('H', $post->created_on)) ?> :
<?php echo form_dropdown('created_on_minute', $minutes, date('i', ltrim($post->created_on, '0'))) ?>
</div>
</li>
<?php if ( ! module_enabled('comments')): ?>
<?php echo form_hidden('comments_enabled', 'no'); ?>
<?php else: ?>
<li>
<label for="comments_enabled"><?php echo lang('blog:comments_enabled_label');?></label>
<div class="input">
<?php echo form_dropdown('comments_enabled', array(
'no' => lang('global:no'),
'1 day' => lang('global:duration:1-day'),
'1 week' => lang('global:duration:1-week'),
'2 weeks' => lang('global:duration:2-weeks'),
'1 month' => lang('global:duration:1-month'),
'3 months' => lang('global:duration:3-months'),
'always' => lang('global:duration:always'),
), $post->comments_enabled ? $post->comments_enabled : '3 months') ?>
</div>
</li>
<?php endif; ?>
</ul>
</fieldset>
</div>
</div>
<input type="hidden" name="row_edit_id" value="<?php if ($this->method != 'create'): echo $post->id; endif; ?>" />
<div class="buttons">
<?php $this->load->view('admin/partials/buttons', array('buttons' => array('save', 'save_exit', 'cancel'))) ?>
</div>
<?php echo form_close() ?>
</div>
</section>
In your code:
$post->type or $post->type = 'wysiwyg-advanced';
PHP will first evaluate $post->type, and if that returns false, the second part of your or statement will be run. Since PHP has to evaluate it, it will attempt to access the property, and since it's not set, the interpreter throws a notice and assumes it's false.
The proper way to do this is:
if (!isset($post->type)) {
$post->type = 'wysiwyg-advanced';
}
// Or in PHP 7:
$post->type = $post->type ?? 'nobody';
Replace
$post->type or $post->type = 'wysiwyg-advanced';
with
$post->type = 'wysiwyg-advanced';
hope it works..
I'm not sure how to describe my question. First I added a button at my CCGridview:
array(
'class'=>'CButtonColumn',
'template' => '{view}{update}{delete}{upload_image}',
'buttons' => array(
'upload_image' => array(
'label' => 'upload foto',
'url' => 'Yii::app()->createUrl("/image/create",
array("product_id" => $data->product_id))',
),
),
),
when I clicked it will bring me to the /image/create view which has a product_id value. For example on that gridview I clicked record number 7, so the url would be:
(webApp)/index.php/image/create?product_id=7
Since it rendering a partial _form so the form has the attribute according to the image table which has this attributes: id, title, filename, product_id.
So the view will be something like:
<div class="row">
<?php echo $form->labelEx($model,'title'); ?>
<?php echo $form->textField($model,'title',array('size'=>45,'maxlength'=>45)); ?>
<?php echo $form->error($model,'title'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'filename'); ?>
<?php echo $form->fileField($model,'filename',array('size'=>45,'maxlength'=>45)); ?>
<?php echo $form->error($model,'filename'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'product_id'); ?>
<?php echo $form->textField($model,'product_id'); ?>
<?php echo $form->error($model,'product_id'); ?>
</div>
<div class="row buttons">
<?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save'); ?>
</div>
My question is, how do we use the value from the url which I mentioned before is 7 (../create?product_id=7) into the product_id attribute without have to type it at provided textField?
In other word I will remove this from the view:
<div class="row">
<?php echo $form->labelEx($model,'product_id'); ?>
<?php echo $form->textField($model,'product_id'); ?>
<?php echo $form->error($model,'product_id'); ?>
</div>
But when i submitted, the form the value (7) should have been passed/saved at product_id field.
Added:
My controller actionCreate is
//...
public function actionCreate()
{
$dir = Yii::app()->basePath . '/../productimages/';
$uploaded = false;
$model=new Image();
if(isset($_POST['Image']))
{
$model->attributes=$_POST['Image'];
$tempSave=CUploadedFile::getInstance($model,'filename');
if($model->validate())
{
$uploaded = $tempSave->saveAs($dir.'/'.$tempSave->getName());
$this->redirect(array('/products/index'));
}
}
$this->render('index', array(
'model' => $model,
'uploaded' => $uploaded,
'dir' => $dir,
));
}
That's it. Many thanks..
modify your controller this way:
if(isset($_POST['Image']))
{
$model->attributes=$_POST['Image'];
$tempSave=CUploadedFile::getInstance($model,'filename');
if($model->validate())
{
$uploaded = $tempSave->saveAs($dir.'/'.$tempSave->getName());
$this->redirect(array('/products/index'));
}
} else {
//initialize defaults
$model->product_id=intval($_GET['product_id']);
}
I have two tables in database profile_fields and profile_fields_values.
Table profile_fields has columns
id
fieldname
fieldtitle
fieldtype
orderby
required
published
Table profile_field_values has columns
id
field_id
user_id
field_value
Here I have to create a dynamic profile management.
How do I show dynamic forms in Yii?
You need to use Form Builder, it has plenty of example how to construct your form using an array. It also supports sub-forms. Just follow the examples from the linked tutorial, content it's to long to be referenced here.
Update:
class LoginForm extends CFormModel
{
public $username;
public $password;
}
$form = new LoginForm();
$form->validatorList->add(
CValidator::createValidator('required', $form, 'username, password')
);
or another example:
class SomeModel
{
public $orders;
public function rules()
{
return array(
array('orders', 'validateOrders'),
);
}
public function validateOrders($attribute, $params)
{
foreach($this->orders as $order)
if (empty($order)) {
$this->addError('orders', 'There is an empty order');
break;
}
}
}
A more broader example is on forum.
I am trying to build this dynamic profile management let me know my approach is my approach is right?
firstly i have created a input form(_form) where user can input fieldtype,fieldname,fieldtitle and field default value and etc which can be save in database table (profile_fields).In this fieldtype is bydefault set and user choose it from dropdownlist As like in the below form.
<?php
/* #var $this ProfileManagerController */
/* #var $model ProfileFields */
/* #var $form CActiveForm */
?>
<div class="form">
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'profile-fields-form',
'enableAjaxValidation'=>false,
)); ?>
<p class="note">Fields with <span class="required">*</span> are required.</p>
<?php echo $form->errorSummary($model); ?>
<div class="row">
<?php echo $form->labelEx($model,'location'); ?>
<?php echo $form->dropDownList($model,'location',CHtml::listData(Countries::model()->findAll('',array('orderby' => 'countryName ASC')),'countryCode','countryName'), array('empty' => array("*" => 'For All Countries'))); ?>
<?php echo $form->error($model,'location'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'profile_type'); ?>
<?php echo $form->dropDownList($model,'profile_type',Yii::app()->params['userRoles'], array('empty' => array("*" => 'For All users')), array($model->profile_type)); ?>
<?php //echo $form->dropDownList($model, 'profile_type', Yii::app()->params['userRoles'], array($model->profile_type)); ?>
<?php echo $form->error($model,'profile_type'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'section'); ?>
<?php echo $form->dropDownList($model,'section',array('profile'=>'profileSection','basicdetails'=>'BasicDetails','contactdetails'=>'ContactDetails','imagedetails'=>'ImageDetails','clientdetails'=>'ClientDetails','tagdetails'=>'TagDetails','otherdetails'=>'OtherDetails','alldetails'=>'AllDetails')); ?>
<?php echo $form->error($model,'section'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'field_name'); ?>
<?php echo $form->textField($model,'field_name',array('size'=>60,'maxlength'=>255)); ?>
<?php echo $form->error($model,'field_name'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'field_title'); ?>
<?php echo $form->textField($model,'field_title',array('size'=>60,'maxlength'=>255)); ?>
<?php echo $form->error($model,'field_title'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'field_type'); ?>
<?php echo $form->dropDownList($model,'field_type',array('text' => 'Text','date' => 'Date','email' => 'Email', 'radio' => 'Radio','multiselect' => 'Multi Select Dropdown List','file'=>'File','checkbox'=>'CheckBox','hidden'=>'Hidden','select'=>'Dropdownlist','password'=>'Password','checkboxlist'=>'Checkboxlist','radiolist'=>'Radiolist','textarea'=>'TextArea'),array('options' => array($model->field_type => array('selected' => true)))); ?>
<?php echo $form->error($model,'field_type'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'field_default_value'); ?>
<?php echo $form->textArea($model,'field_default_value',array('rows'=>6, 'cols'=>50)); ?>
<?php echo $form->error($model,'field_default_value'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'required'); ?>
<?php echo $form->dropDownList($model, 'required', array('1' => 'Yes', '0' => 'No')); ?>
<?php echo $form->error($model,'required'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'published'); ?>
<?php echo $form->dropDownList($model, 'published', array('1' => 'Yes', '0' => 'No')); ?>
<?php echo $form->error($model,'published'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'order_by'); ?>
<?php echo $form->textField($model,'order_by'); ?>
<?php echo $form->error($model,'order_by'); ?>
</div>
<div class="row buttons">
<?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save'); ?>
</div>
<?php $this->endWidget(); ?>
</div><!-- form -->
secondly I have created a view index file which will show dynamically what type of fieldstypes and fieldsname and field title are set by the user in profile_field table and call the extension created by me and then another user can input accordingly .and these values are save in profile_field_values table .
----------index file---------------
<div class="form">
<?php
$form = $this->beginWidget('CActiveForm', array(
'id' => 'completeProfile-form',
'htmlOptions' => array('enctype' => 'multipart/form-data'),
'enableAjaxValidation' => false,
'clientOptions' => array('validataOnSubmit' => true),
'enableClientValidation' => true,
));
?>
<?php
if (!empty($field_data)) {
foreach ($field_data as $field) {
$selectedOptions = '';
$def_value='';
$field_name = $field->field_name; // required field
$field_type = $field->field_type; // required field
$field_id = $field->id; // required field
//for validation
$req = $field->required == 1 ? 'required' : ''; // required if using validation
$email = $field->field_type == 'email' ? 'email' : ''; // required if using validation
$password = $field->field_type == 'password' ? 'password' : ''; // required if using validation
$class = array($req, $email, $password); // class must be array type, if no class found, send empty array
//values present in ProfileFieldsValues to populate
$value = ProfileFieldsValues::model()->findByAttributes(array('user_id' => Yii::app()->user->id, 'field_id' => $field->id));
// set html options
$htmlOptions = array();
$htmlOptions['class'] = implode(" ", $class);
$htmlOptions['value'] = $value ? $value->field_value : '';
// field array - Must SET
$fieldArray = array();
$fieldArray['model'] = $field;
$fieldArray['form'] = $form;
$fieldArray['field_type'] = $field_type;
$fieldArray['field_name'] = $field_name;
$fieldArray['field_id'] = $field_id;
$fieldArray['default_value'] = $value ? $value->field_value : $field->field_default_value;
//If input type field is dropdowlist for selecttion
if($field_type == 'select' ){
if(!empty($field->field_default_value)){
$my_string = preg_replace(array('/\n/'), '#PH#', $field->field_default_value );
$my_array = explode('#PH#', $my_string);
foreach($my_array as $my_arr){
$def=explode('|',$my_arr);
$def_value[$def[0]]=$def[1];
}
$fieldArray['select_box_array']=$def_value;
}else{
$fieldArray['select_box_array'] =$country;
}
$htmlOptions['prompt'] = 'SELECT ANY';
$value ? $htmlOptions['options']=array($value->field_value=>array('selected'=>'true')): $htmlOptions['prompt'] = 'SELECT ANY';
}
//if input type field is multiple select dropdownlist
if( $field_type == 'multiselect'){
if(!empty($field->field_default_value)){
$my_string = preg_replace(array('/\n/'), '#PH#', $field->field_default_value );
$my_array = explode('#PH#', $my_string);
foreach($my_array as $my_arr){
$def=explode('|',$my_arr);
$def_value[$def[0]]=$def[1];
}
$fieldArray['select_box_array']=$def_value;
}else{
$fieldArray['select_box_array'] =$country;
}
$htmlOptions['prompt'] = 'SELECT Multiple';
if(!empty($value)){
$field_valu= explode(',',$value->field_value);
foreach($field_valu as $eachValue){
$selectedOptions[$eachValue] = array('selected'=>'selected');
}
$htmlOptions['options']= $selectedOptions;
}
}
// if input type field is radio button
if ($field_type == 'radiolist') {
$fl = ProfileFieldsValues::model()->findByAttributes(array('field_id' => $field->id, 'user_id' => Yii::app()->user->id));
if(!empty($field->field_default_value)){
$my_string = preg_replace(array('/\n/'), '#PH#', $field->field_default_value );
$my_array = explode('#PH#', $my_string);
foreach($my_array as $my_arr){
$def=explode('|',$my_arr);
$def_value[$def[0]]=$def[1];
}
$fieldArray['radio_box_array']=$def_value;
}else{
$fieldArray['radio_box_array'] =array('hello','bye');
}
$value = $fl ? $fl->field_value : 0;
$htmlOptions = array('labelOptions' => array('style' => 'display:inline'), 'separator' => ' ','value' => $value);
}
//if input type field is checkbox list
if ($field_type == 'checkboxlist') {
$fl = ProfileFieldsValues::model()->findByAttributes(array('field_id' => $field->id, 'user_id' => Yii::app()->user->id));
if(!empty($field->field_default_value)){
$my_string = preg_replace(array('/\n/'), '#PH#', $field->field_default_value );
$my_array = explode('#PH#', $my_string);
foreach($my_array as $my_arr){
$def=explode('|',$my_arr);
$def_value[$def[0]]=$def[1];
}
$fieldArray['check_box_array']=$def_value;
}else{
$fieldArray['check_box_array'] =array('hello','bye');
}
$value = $fl ? (array)explode(",",$fl->field_value) : array(0);
$htmlOptions = array('labelOptions' => array('style' => 'display:inline'), 'separator' => ' ','value' => $value );
}
//if input type field is file
if ($field_type == 'file') {
$files = ProfileFieldsValues::model()->findByAttributes(array('field_id' => $field->id, 'user_id' => Yii::app()->user->id));
if(isset($files->field_value)){
echo CHtml::image(Yii::app()->request->baseUrl . '/images/user_images/' .$files->field_value, 'Image', array('class' => 'img-polaroid', 'width' => 200));
}
}
$fieldArray['htmlOptions'] = $htmlOptions;
if ($field->published == '1') {
if($field->field_type == 'checkbox' || $field->field_type == 'radio' ){ ?>
<div class="row">
<?php $this->widget('ext.dynamicFields.EDynamicFields', $fieldArray); ?>
<?php echo $field->field_title; ?>
<?php echo $form->error($field, $field->field_title); ?>
</div>
<?php }else{ ?>
<div class="row">
<?php echo $form->labelEx($field, $field->field_title); ?>
<?php $this->widget('ext.dynamicFields.EDynamicFields', $fieldArray); ?>
<?php echo $form->error($field, $field->field_title); ?>
</div>
<?php } ?>
<?php } ?>
<?php } ?>
<div class="row buttons">
<?php echo CHtml::submitButton('Submit'); ?>
</div>
<?php
}
$this->endWidget();
?>
</div><!-- form -->
<?php Yii::app()->clientScript->registerScriptFile(Yii::app()->getBaseUrl(true) . '/js/jquery.validate.js'); ?>
<script type="text/javascript">
$("#completeProfile-form").validate({
});
</script>
I have created a extension for various input type fields like
1.text
2.email textbox
3.hidden input type field
4.textarea
5.dropdownlist
6. multiple select dropdownlist
7.password textfield
8.file
9.radiolist
10.radio button
11 checkbox
12checkboxlist
13 date field
<?php
/**
* Description of EDynamicFields
* It will show dynamic fields
*
* #author Gaurav Parashar
*/
class EDynamicFields extends CWidget {
public $field_type;
public $field_name;
public $field_id;
public $default_value;
public $select_box_array = array();
public $radio_box_array = array();
public $check_box_array = array();
public $htmlOptions = array();
public $model;
public $form;
public $select;
public function run() {
switch ($this->field_type) {
case 'text':
echo $this->form->textField($this->model, "field_name[$this->field_type][$this->field_id]", $this->htmlOptions);
break;
case 'email':
echo $this->form->textField($this->model, "field_name[$this->field_type][$this->field_id]", $this->htmlOptions);
break;
case 'hidden':
echo $this->form->hiddenField($this->model, "field_name[$this->field_type][$this->field_id]", $this->default_value);
break;
case 'textarea':
echo $this->form->textArea($this->model, "field_name[$this->field_type][$this->field_id]", $this->htmlOptions);
break;
case 'select':
echo $this->form->dropDownList($this->model, "field_name[$this->field_type][$this->field_id]", $this->select_box_array, $this->htmlOptions);
break;
case 'password':
echo $form->passwordField($model,'password',$this->htmlOptions);
break;
case 'multiselect':
$newarr = array_merge($this->htmlOptions, array('multiple' => 'multiple'));
echo $this->form->dropDownList($this->model, "field_name[$this->field_type][$this->field_id]", $this->select_box_array, $newarr);
break;
case 'file':
echo $this->form->fileField($this->model, "field_name[$this->field_type][$this->field_id]" ,$this->htmlOptions);
break;
case 'radio':
echo $this->form->radioButton($this->model, "field_name[$this->field_type][$this->field_id]", $this->htmlOptions);
break;
case 'radiolist':
echo CHtml::radioButtonList("ProfileFields[field_name][$this->field_type][$this->field_id]",$this->htmlOptions['value'],$this->radio_box_array,$this->htmlOptions);
break;
case 'checkbox':
echo $this->form->checkBox($this->model, "field_name[$this->field_type][$this->field_id]", $this->htmlOptions);
break;
case 'date':
$this->widget('zii.widgets.jui.CJuiDatePicker', array(
'attribute' => "field_name[$this->field_type][$this->field_id]",
'model' => $this->model,
'htmlOptions'=>array(
'class'=>'required',
),
'options' => array(
'dateFormat' => 'yy-mm-dd',
'maxDate' => 'new Date()', // One month ahead
//'minDate' => '-50y', // Today
'changeMonth' => true,
'changeYear' => true,
'yearRange'=>'2000:2099',
'minDate' => '2000-01-01', // minimum date
'maxDate' => '2099-12-31',
)
));
break;
case 'checkboxlist':
echo CHtml::checkBoxList("ProfileFields[field_name][$this->field_type][$this->field_id]",$this->htmlOptions['value'],$this->check_box_array,$this->htmlOptions);
break;
}
}
}
view:
<?php
$attr_form = array('class' => 'form-horizontal');
echo form_open('login/create', $attr_form); ?>
<div class="form-group">
<label class="col-sm-4 control-label">Gender</label>
<div class="col-sm-4">
<?php echo form_radio('gender', 'M'); ?>
<?php echo form_radio('gender', 'F'); ?>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-4 col-sm-8">
<?php
$data_submit = array('class'=> 'btn btn-info', 'name' => 'submit', 'value'=> 'Create Account');
echo form_submit($data_submit);?>
</div>
</div>
controllers:
function create ()
{
$this->load->library('form_validation');
$this->form_validation->set_rules('gender', 'Gender', 'required');
if($this->form_validation->run() == FALSE)
{
$this->signup();
}
else
{
$this->load->model('parents_model');
if($query = $this->parents_model->create_member())
{
$data['main_content'] = 'successful';
$this->load->view('include/template', $data);
}
else
{
$this->signup();
}
}
}
model:
function create_member ()
{
$new_parents = array(
'gender' => $this->input->post('gender')
);
$insert = $this->db->insert('parents', $new_parents);
return $insert;
}
I just simplified the other form inputs.
Can anyone figure out whats wrong with my code? It cannot go to successful page.
Or do I use wrong form_radio code ?
I have tried many times! Please help me....
You have a syntax error.
$this->input->post->('gender')
should be:
$this->input->post('gender')
try this
$gender = $this->input->post('gender')['M'] ? 'M':'F';
$new_parents = array('gender' => $gender);
After I restarted my localhost, everything works again.
Cause I have created a column in the table without restarting!