Import csv to mysql using Yii framework - php

I have a problem with uploading csv file to database. This is my view:
<?php
$this->breadcrumbs = array(
__('People') => array('/contacts'),
__('Persons') => array('admin'),
__('Manage'),
);?>
<h1><?php echo __('People'); ?> <small><?php echo __('import contacts'); ?></small></h1><br/>
<div class="form">
<?php
$form = $this->beginWidget('bootstrap.widgets.TbActiveForm', array(
'id'=>'service-form',
'enableAjaxValidation'=>false,
'method'=>'post',
'type'=>'horizontal',
'htmlOptions'=>array(
'enctype'=>'multipart/form-data'
)
)); ?>
<fieldset>
<?php echo $form->errorSummary($model, 'Opps!!!', null, array('class'=>'alert alert-error span12')); ?>
<div class="control-group">
<div class="span4">
<div class="control-group <?php if ($model->hasErrors('postcode')) echo "error"; ?>">
<?php echo $form->labelEx($model,'file'); ?>
<?php echo $form->fileField($model,'file'); ?>
<?php echo $form->error($model,'file'); ?>
</div>
</div>
</div>
<div class="form-actions">
<?php $this->widget('bootstrap.widgets.TbButton', array('buttonType'=>'submit', 'type'=>'primary', 'icon'=>'ok white', 'label'=>'UPLOAD')); ?>
<?php $this->widget('bootstrap.widgets.TbButton', array('buttonType'=>'reset', 'icon'=>'remove', 'label'=>'Reset')); ?>
</div>
</fieldset>
<?php $this->endWidget(); ?>
</div><!-- form -->
This is my model:
<?php
class UserImportForm extends CFormModel
{
public $file;
/**
* #return array validation rules for model attributes.
*/
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('file', 'file',
'types'=>'csv',
'maxSize'=>1024 * 1024 * 10, // 10MB
'tooLarge'=>'The file was larger than 10MB. Please upload a smaller file.',
'allowEmpty' => false
),
);
}
/**
* #return array customized attribute labels (name=>label)
*/
public function attributeLabels()
{
return array(
'file' => 'Select file',
);
}
}
?>
And this is my function in Controller
public function actionImportCSV()
{
$model=new UserImportForm;
if(isset($_POST['UserImportForm']))
{
$model->attributes=$_POST['UserImportForm'];
if($model->validate())
{
$csvFile=CUploadedFile::getInstance($model,'file');
$tempLoc=$csvFile->getTempName();
$sql="LOAD DATA LOCAL INFILE '".$tempLoc."'
INTO TABLE `contacts`
";
$connection=Yii::app()->db;
$transaction=$connection->beginTransaction();
try
{
$connection->createCommand($sql)->execute();
$transaction->commit();
}
catch(Exception $e) // an exception is raised if a query fails
{
echo "<pre>";
print_r($e);
echo "</pre>";
exit;
$transaction->rollBack();
}
$this->redirect(Yii::app()->createUrl("/contacts/importCSV"));
}
}
$this->render("importcsv",array('model'=>$model));
}
And I have a problem with LOAD DATA, cause mySQL version don't support LOAD DATA. Anyone knows how can I replace load data to import csv file?

Follow the instructions at:
https://github.com/Ardem/yii-importcsv-extension
I followed the simple steps described in readme.md file having the 3 simple steps and it worked like a breeze.

If you are on a version of MySQL tat does not support LOAD DATA, then you are on a very old version indeed. The current online documentation includes LOAD DATA in every mentioned version, though the LOCAL clause is only supported as far back as 3.22.6.
Maybe the real problem is that if you do not specify the FIELDS clause it treats the file as if
FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\'
LINES TERMINATED by '\n' STARTING BY ''
were specified. That is a TAB separated values file in Unix(Linux) text format. To make it comma separated, specify:
LOAD DATA LOCAL INFILE 'data.txt' INTO TABLE tbl_name
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"';
And if you are expecting files from a Windows machine you might want to include
LINES TERMINATED BY '\r\n'
after the FIELDS clause.

Related

How to import excel data into mySQL in yii 1.16

I have customer table in MySQL database.I have list of customers in excel csv and i want to import excel data into MySQL customer table.I want someone show me step by step How i can do it and also tell model view and controller.
I have Written MySQL Query of customer table to show you that I will be same coloumns in excel csv.
(`CustomerID`, `FirstName`, `LastName`, `JobTitle`, `BusinessPhone`, `MobilePhone`, `FaxNumber`, `Address`, `Area`, `State`, `ZipCode`, `Country`, `Email`, `Webpage`, `Notes`, `CustomerInvoice`, `Status`)
Would you like to show me How i can import csv data into MySQL table or Yii have any plugin to import excel data into MySQL database?
If i understood correctly,you can do something in controller action
public function actionYourActionName(){
if (isset($_FILES['csv_file']) && !empty($_FILES['csv_file'])) {
$csv = array();
$file = fopen($_FILES['csv_file']['tmp_name'], 'r');
while (($line = fgetcsv($file)) !== FALSE) {
//$line is an array of the csv elements
$csv[] = $line;
}
fclose($file);
for ($i = 1; $i < count($csv); $i++) {
$model = new YourmodelName();
foreach ($csv[0] as $key => $value) {
$model->$value = $csv[$i][$key];
}
if($model->save()){
//do here what you want to do after saving model
}else{return $model->getErrors();}
}
}
}else{
$this->render('your view name');
}
and in your view file something like e.g.
echo CHtml::form('', 'post', array('id' => "verticalForm", 'class' => 'well form-vertical', 'enctype' => 'multipart/form-data'));
echo CHtml::fileField('csv_file[]', '', array('id' => 'csv_file', 'multiple' => 'multiple'));
echo '<p class="help-block">Please upload .csv files only.</p>';
echo CHtml::submitButton('Submit', array('class' => 'btn btn-primary'));
echo CHtml::endForm();
and i suppose you have created a model.for your mysql table, hope this will help you
This is best plugin with proper documentation and examples
http://phpexcel.codeplex.com/
with this plugin you can import excel data in mysql.
You can use "LOAD DATA" command.
Here is the example from yiiframework documentation.
http://www.yiiframework.com/wiki/336/importing-csv-file-to-mysql-table-using-load-data-command/
You can get reference from YII: http://www.yiiframework.com/forum/index.php/topic/23536-upload-data-excel-to-mysql/
**step1:**Define a Form model ie
class UserImportForm extends CFormModel
{
public $file;
/**
* #return array validation rules for model attributes.
*/
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('file', 'file',
'types'=>'csv',
'maxSize'=>1024 * 1024 * 10, // 10MB
'tooLarge'=>'The file was larger than 10MB. Please upload a smaller file.',
'allowEmpty' => false
),
);
}
/**
* #return array customized attribute labels (name=>label)
*/
public function attributeLabels()
{
return array(
'file' => 'Select file',
);
}
}
step2: Now you need to define a form in your view.ie
Note: i have used bootstrap form widget here.you can change it based on your needs.
<div class="form">
<?php
$form = $this->beginWidget('bootstrap.widgets.BootActiveForm', array(
'id'=>'service-form',
'enableAjaxValidation'=>false,
'method'=>'post',
'type'=>'horizontal',
'htmlOptions'=>array(
'enctype'=>'multipart/form-data'
)
)); ?>
<fieldset>
<legend>
<p class="note">Fields with <span class="required">*</span> are required.</p>
</legend>
<?php echo $form->errorSummary($model, 'Opps!!!', null, array('class'=>'alert alert-error span12')); ?>
<div class="control-group">
<div class="span4">
<div class="control-group <?php if ($model->hasErrors('postcode')) echo "error"; ?>">
<?php echo $form->labelEx($model,'file'); ?>
<?php echo $form->fileField($model,'file'); ?>
<?php echo $form->error($model,'file'); ?>
</div>
</div>
</div>
<div class="form-actions">
<?php $this->widget('bootstrap.widgets.BootButton', array('buttonType'=>'submit', 'type'=>'primary', 'icon'=>'ok white', 'label'=>'UPLOAD')); ?>
<?php $this->widget('bootstrap.widgets.BootButton', array('buttonType'=>'reset', 'icon'=>'remove', 'label'=>'Reset')); ?>
</div>
</fieldset>
<?php $this->endWidget(); ?>
</div><!-- form -->
**step3:**Now you need to write an action in your controller to import the file.ie
public function actionImportCSV()
{
$model=new UserImportForm;
if(isset($_POST['UserImportForm']))
{
$model->attributes=$_POST['UserImportForm'];
if($model->validate())
{
$csvFile=CUploadedFile::getInstance($model,'file');
$tempLoc=$csvFile->getTempName();
$sql="LOAD DATA LOCAL INFILE '".$tempLoc."'
INTO TABLE `tbl_user`
FIELDS
TERMINATED BY ','
ENCLOSED BY '\"'
LINES
TERMINATED BY '\n'
IGNORE 1 LINES
(`name`, `age`, `location`)
";
$connection=Yii::app()->db;
$transaction=$connection->beginTransaction();
try
{
$connection->createCommand($sql)->execute();
$transaction->commit();
}
catch(Exception $e) // an exception is raised if a query fails
{
print_r($e);
exit;
$transaction->rollBack();
}
$this->redirect(array("user/index"));
}
}
$this->render("importcsv",array('model'=>$model));
}

Upload pictures from Yii showing endWiget() error

Hi I also had a problem when try to upload picture using this method.
My Action/model:
class Image extends CActiveRecord
{
public $foto;
...
public function rules()
{
return array(
...
array('foto', 'file', 'types'=>'jpg, gif, png'),
...
);
}
}
My Controller:
class ImageController extends Controller
{
public function actionCreate()
{
$model=new Image;
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if(isset($_POST['Image']))
{
$model->attributes=$_POST['Image'];
$model->image=CUploadedFile::getInstance($model,'foto');
if($model->save())
$model->foto->saveAs('productimages');
$this->redirect(array('view','id'=>$model->id));
}
$this->render('create',array(
'model'=>$model,
));
}
}
My view:
<?php $form = $this->beginWidget(
'CActiveForm',
array(
'id' => 'upload-form',
'enableAjaxValidation' => false,
'htmlOptions' => array('enctype' => 'multipart/form-data'),
)
); ?>
<?php echo $form->labelEx($model, 'foto'); ?>
<?php echo $form->fileField($model, 'foto'); ?>
<?php echo $form->error($model, 'foto'); ?>
...
<div class="row buttons">
<?php echo CHtml::submitButton('Submit'); ?>
</div>
<?php $this->endWidget(); ?>
But when I run, two problems appeared:
Problem #1:
endWiget() call [SOLVED by Ivan Misic]
ImageController contains improperly nested widget tags in its view "/var/www/html/onlineshop-nimalogos/protected/views/image/_form.php". A CActiveForm widget does not have an endWidget() call.
Problem#2:
Since problem # 1 is solved, came with another problem, the image is not saving at my 'productimages' folder.
Please help me with the problem # 2. Many thanks..
You have somewhere opened redundant CActiveForm widget and you should look into views and partials.
Yii is generting three view files with gii, and these are:
create.php update.php
| |
| |
+-------+-------+
|
|
_form.php
create and update views are rendering the same partial _form, so you should look in all three to find redundant beginWidget call.
The view you supported in your question should be _form.php partial view.

How to save input in yii to database

I have this code Im trying to save the content and the title from a form I made..It has an id that autoincrement the id number adds in the database but the title and the content isn't/cant be save in the database. Can you please check my code if I've done something wrong? or what I'm lacking at.
Here is my model ContentForm.php
<?php
class ContentForm extends CActiveRecord{
public $content;
public $title;
public function tableName(){
return 'tbl_content';
}
public function attributeLabels()
{
return array(
'contentid' => 'contentid',
'content' => 'content',
'title' => 'title',
// 'email' => 'Email',
// 'usrtype' => 'Usrtype',
);
}
Here is my view content.php
<div>
<p>User: <a href="viewuserpost">
<?php
echo Yii::app()->session['nameuser'];
?>
</a>
</p>
</div>
<h1>Content</h1>
<?php
$form=$this->beginWidget('CActiveForm', array(
'id'=>'contact-form',
'enableClientValidation'=>true,
'clientOptions'=>array(
'validateOnSubmit'=>true,
),
));
?>
Title:
<div class="row">
<?php
echo $form->textfield($model,'title');
?>
</div>
</br>
Body:
<div class="row">
<?php
echo $form->textArea($model,'content',array('rows'=>16,'cols'=>110));
?>
</div>
<div class="row buttons">
<?php
echo CHtml::submitButton($model->isNewRecord? 'Create':'Save');
?>
</div>
<?php $this->endWidget(); ?>
and here is my content action in my sitecontroller.php
public function actionContent(){
$model=new ContentForm;
if(isset($_POST['ContentForm'])) {
$model->attributes=$_POST['ContentForm'];
if($model->save())
$this->redirect(array('content','contentid'=>$model->contentid));
$this->redirect(array('content','title'=>$model->title));
$this->redirect(array('content','content'=>$model->content));
}
$this->render('content',array('model'=>$model));
}
Please help.
Remove
public $content;
public $title;
from your class.
Yii uses PHP magic methods. And when you add attributes to your class, PHP doesn't call them but references to your explicitly written attributes.
Moreover, you should add some validation, if you use $model->attributes=$_POST['ContentForm'];. Another variant is to use unsecure $model->setAttributes($_POST[ContentForm], false) where false tells Yii to set all attributes, not only that are considered safe.
Note, that attributes is not real Model attribute, this is virtual attribute accessed through magic methods.
Also, you don't need three redirects. This is HTTP redirect to other page. This time, you just should just specify route to model view action and its parameter that is id, for example. Like this $this->redirect(array('content/view','id'=>$model->contentid));.
Of course, simplest way for you is to create new model and controller with actions using Gii.
you may missed rules , add this in your model ContentForm.php
public function rules()
{
return array(
array('content,title', 'safe'),
);
}
For more about model validation
http://www.yiiframework.com/wiki/56/reference-model-rules-validation/

zf2 form validation (zfcAdmin and BjyAuthorize related)

I'm facing validation problems integrating my custom module in zfcAdmin and BjyAuthorize.
My form class:
...
$formOptions = $this->settings->getFormSettings();
foreach ($formOptions as $field){
if (isset($field['field']))
$this->add($field['field']);
}
...
My filter class:
$formOptions = $this->settings->getFormSettings();
foreach ($formOptions as $filter){
if (isset($filter['filter']))
$this->add($filter['filter']);
}
...
Fields, filters and other options are retrieved from config file.
Basically everything works fine: form data can be added, edited or deleted from db.
Also after the zfcAdmin module installation no problem rose. Everything works fine using both 'site/mymodule' route and 'site/admin/mymodule' route: i can still add, edit and delete items from db.
Here the problem: I need some form elements (a Select in this particular case) editable/viewable only by administrator. (I can write a new controller/entity class 'ad hoc' for admin but i would like to use the same code for the whole site.)
I installed and configured bjyoungblood/BjyAuthorize module: it allowed me to display some form elements/fields only to admin but when i'm in edit mode a form validation error is displayed: "Value is required and can't be empty"
Here the code:
//view/mymodule/mymodule/update.phtml
<div id="page" style="margin-top: 50px;">
<?php if (isset($this->messages) && count($this->messages) > 0 ): ?>
<?php foreach ($this->messages as $msg): ?>
<div class="alert alert-<?php echo $this->escapeHtmlAttr($msg['type']); ?>">
<?php if (isset($msg['icon'])) echo '<i class="'.$this->escapeHtmlAttr($msg['icon']).'"></i> '; ?><?php echo $this->escapeHtml($msg['message']); ?>
</div>
<?php endforeach; ?>
<?php endif; ?>
<?php
$title = 'Edit Item';
$this->headTitle($title);
?>
<h1><?php echo $this->escapeHtml($title); ?></h1>
<?php
$form = $this->form;
$form->setAttribute('action', $this->url($this->route . 'mymodule/update', array('action' => 'update', 'id' => $this->id )));
$form->prepare();
$form->setAttribute('method', 'post');
$input = $form->getInputFilter();
?>
<?php echo $this->form()->openTag($form) ?>
<dl class="zend_form">
<?php foreach ($form as $element): ?>
<?php
//CHECK USER PRIVILEDGES
$elName = $element->getName();
$elResource = isset($this->form_options[$elName]['auth']) ? $this->form_options[$elName]['auth']['resource'] : "userresource";
$elPrivilege = isset($this->form_options[$elName]['auth']) ? $this->form_options[$elName]['auth']['privilege'] : "view";
//SHOW THE ELEMENT IF ALLOWED
if($this->isAllowed($elResource, $elPrivilege)):
?>
<?php if ($element->getLabel() != null): ?>
<dt><?php echo $this->formLabel($element) ?></dt>
<?php endif ?>
<?php if ($element instanceof Zend\Form\Element\Button): ?>
<dd><?php echo $this->formButton($element) ?></dd>
<?php elseif ($element instanceof Zend\Form\Element\Select): ?>
<dd><?php echo $this->formSelect($element) . $this->formElementErrors($element) ?></dd>
<?php else: ?>
<dd><?php echo $this->formInput($element) . $this->formElementErrors($element) ?></dd>
<?php endif ?>
<?php else: ?>
<?php
?>
<?php endif ?>
<?php endforeach ?>
</dl>
<?php echo $this->form()->closeTag() ?>
</div>
<div class="clear-both"></div>
My controller action
//controller
public function updateAction(){
$messages = array();
$id = (int)$this->getEvent()->getRouteMatch()->getParam('id');
$form = $this->getServiceLocator()->get('FormItemService');
$itemMapper = $this->getItemMapper();
$item = $itemMapper->findById($id);
$form->bind($item);
$request = $this->getRequest();
if($request->isPost()){
$form->setData($request->getPost());
if ($form->isValid()) {
die('c');//never here
$service = $this->getServiceLocator()->get('mymodule\Service\Item');
if ( $service->save($form->getData()) )
{
$messages[] = array(
'type' => 'success',
'icon' => 'icon-ok-sign',
'message' => 'Your profile has been updated successfully!',
);
}
else
{
$messages[] = array(
'type' => 'error',
'icon' => 'icon-remove-sign',
'message' => 'Profile update failed! See error messages below for more details.',
);
}
}else{
var_dump($form->getMessages());//Value is required and can't be empty
}
}
return array(
'messages' => $messages,
'form' => $form,
'id' => $id,
'form_options' => $this->getServiceLocator()->get('mymodule_module_options')->getFormSettings(),
'route' => $this->checkRoute($this->getEvent()->getRouteMatch()->getmatchedRouteName())
);
}
If user is not allowed to view the resource, the element is not echoed. So $request->getPost() has no value for that form element and an error is returned by isValid().
Has anyone solved a similar problem or can anyone point me to the right direction?
Thanks
The problem is that you don't do any security check in your FormFilter class, where you define your required fields.
The $form->isValid() function checks the posted data against those filter elements. So it's not enough to prevent the 'echo field' in your view, you still need to apply the security check to the filter element.
One other approach would be to make two forms one for the front end and one for the admin. Since the one for the admin will have the same fields plus one extra select field you can make the admin form extends the front end one. E.g.
class myForm
{
public function __construct(...)
{
// add fields and set validators
}
}
and the admin form could be:
class MyAdminForm extends myForm
{
public function __construct(...)
{
parent::__construct(...);
// add the extra field and extra validator
}
}
In that way even if you edit the front end form (or validators) the back end will always be up to date.
Hope this helps :),
Stoyan

Yii: Submit a value to different model

Here's a newbie question related to my latest exercise with Yii Framework.
I have a following structure in the database:
CREATE TABLE location(
id INTEGER PRIMARY KEY NOT NULL,
location TEXT);
CREATE TABLE parameter(
id INTEGER PRIMARY KEY NOT NULL,
name TEXT,
value TEXT);
CREATE TABLE temperature(
id INTEGER PRIMARY KEY NOT NULL,
locationId INTEGER,
value REAL NOT NULL,
createDate DATETIME NOT NULL,
FOREIGN KEY(locationId) REFERENCES location(id));
CREATE INDEX idx1_temperature ON temperature (createDate);
I'm trying to create a view containing both location data in a grid, but also a functionality to change a certain value in parameter-table. In practice I would have a list of all possible locations in a grid, in addition to a possibility to change the parameter.value where parameter.name="CURRENT_LOCATION".
What I've gotten so far is:
location/admin.php generating a view:
...
<h2>Change current location</h2>
<?php echo $this->renderPartial('_para', array('model'=>Parameter::model()->find('name="current_location"'))); ?>
<h2>Modify locations</h2>
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'location-grid',
'dataProvider'=>$model->search(),
'columns'=>array(
'location',
array(
'class'=>'CButtonColumn',
),
),
));
...
location/_para.php for embedding a form:
<?php
/* #var $this ParameterController */
/* #var $model Parameter */
/* #var $form CActiveForm */
?>
<div class="form">
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'parameter-form',
'enableAjaxValidation'=>false,
)); ?>
<?php echo $form->errorSummary($model); ?>
<div class="row">
<?php echo $form->labelEx($model,'value'); ?>
<?php //echo $form->textField($model,'value'); ?>
<?php echo $form->dropDownList($model,'value',CHtml::listData(Location::model()->findAll(), 'id', 'location')); ?>
<?php echo $form->error($model,'value'); ?>
</div>
<div class="row buttons">
<?php echo CHtml::submitButton('Save'); ?>
</div>
<?php $this->endWidget(); ?>
</div><!-- form -->
So, what would need is to Save(=update) a given parameter-row, but I just seem not to get it right. I have debugged so far that it seems like the Submit Button causes the Location-controller's actionAdmin-function to be executed. That would be fine by me, if I just could instruct there to save the Parameter-record instead of the Location.
Here's the actionAdmin-function from LocationController.php:
public function actionAdmin()
{
$model=new Location('search');
$model->unsetAttributes(); // clear any default values
if(isset($_GET['Location']))
{
$model->attributes=$_GET['Location'];
}
if(isset($_POST['Parameter']))
{
$model->attributes=$_POST['Parameter'];
if($model->save())
{
$this->redirect(array('view','id'=>$model->id));
}
}
$this->render('admin',array(
'model'=>$model,
));
}
I see a lot to posts covering multi model forms and such, but I just cannot get a grip on this. It may very well be that I'm trying to accomplish this in a totally wrong way.
So, punch me to right direction, please.
Okay so, I think the best thing is to put the method for updating the Parameter in the ParameterController. That makes it easier to implement and is a bit cleaner.
So to do that, change the form code to this:
You might need to adjust the action in the form for it to work, e.g. /admin/parameter/update
<?php
/* #var $this ParameterController */
/* #var $model Parameter */
/* #var $form CActiveForm */
?>
<div class="form">
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'parameter-form',
'enableAjaxValidation'=>false,
// Check that the action method below is correct
'action' => array('/parameter/update', 'id' => $model->id),
)); ?>
<?php echo $form->errorSummary($model); ?>
<div class="row">
<?php echo $form->labelEx($model,'value'); ?>
<?php //echo $form->textField($model,'value'); ?>
<?php echo $form->dropDownList($model,'value',CHtml::listData(Location::model()->findAll(), 'id', 'location')); ?>
<?php echo $form->error($model,'value'); ?>
</div>
<div class="row buttons">
<?php echo CHtml::submitButton('Save'); ?>
</div>
<?php $this->endWidget(); ?>
</div><!-- form -->
If you have an existing update method in your ParameterController, see if it works as is. If it doesn't or you don't have the update method, try something like this:
public function actionUpdate($id)
{
$model = Parameter::model()->findByPk($id);
if(isset($_POST['Parameter']))
{
$model->attributes=$_POST['Parameter'];
if($model->update())
{
// Below redirects to the previous URL
$this->redirect(Yii::app()->request->urlReferrer);
}
}
}
I changed $model->save() to $model->update() because that won't call the validation rules and make it return false. If you want to validate for some reason, you will need to change the rule so that name and value are only required when creating a new parameter, like this:
array('name, value', 'required', 'on' => 'create'),
And then when you create your new Parameter, you would need to do $model = new Parameter('create');

Categories