Upload multiple files yii2 - file-upload

Tell me where I was wrong, everything is tried
my view file:
echo FileInput::widget([
'model' => $model,
'attribute' => 'files[]',
'options' => ['multiple' => true]
]);
Also i added
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>
enctype option to form element
Model:
i add two variables as property:
public $files; // files instance
public $serialize; // set string which store the files
in rules
serialize as string, and files:
[['files'], 'file', 'skipOnEmpty' => true, 'extensions' => 'gif, jpg, png, pdf, doc, docx', 'maxFiles' => 10],
and controller action:
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post())) {
$oldFiles = $model->serialize;
$files = UploadedFile::getInstance($model, 'files');
if($files === false){
$model->serialize = $oldFiles;
} else {
$serialize = [];
if($model->validate()){
foreach($files as $file){
$ext = end((explode(".", $file)));
$filename = Yii::$app->security->generateRandomString().".{$ext}";
$serialize[] = $filename;
$file->saveAs(Yii::$app->basePath . '/web/image/' . $filename);
}
} else {
}
//print_r($model->getErrors()); die();
$model->serialize = serialize($serialize);
}
$model->save();
return $this->redirect(['view', 'id' => $model->news_id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
So, $files is empty, why?
also i get a "4" code error in $_FILES array

It should be getInstances for multiple files.
$files = UploadedFile::getInstances($model, 'files');

Related

Error: getting unknown property: yii\web\Application::generateid

I have the below code in studentsController.php to add data to 2 tables from a form but im getting error. It is to add to students table, then add some data to the users table too. I feel i'm supposed to add something at the top via "use' keyword but I don't know.please help.
public function actionCreate() {
$model = new model();
$user = new Users();
if ($model->load(Yii::$app->request->post())) {
$model->id = Yii::$app->generateid->getGUID(); //this line caused the error
$model->save();
$studentId = $model->id;
if($user->load(Yii::$app->request->post()))
{
$user->id = $model->id;
$user->firstname = $model->firstname;
$user->lastname = $model->lastname;
$user->username = $model->phone;
$user->password = 'pass123'; //default password
$user->role = 'student';
$user->save(false);
}
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
'user' => $user,
]);
}
}
You seem to miss generateid in your web.php
It should be something like this
GenerateIDs.php inside #app/components folder
<?php
namespace app\components;
class GenerateIDs extends \yii\base\Component
{
public function getGUID()
{
//do your stuff here
}
//....
}
then in your #app/config/web.php you have something like
<?php
return [
'components' => [
'generateid' => [
'class'=>'app\components\GenerateIDs',
// other configurations for the component
],
],
];
then you can use it in your app as you wish
public function actionCreate() {
$model = new model();
$user = new Users();
if ($model->load(Yii::$app->request->post())) {
$model->id = Yii::$app->generateid->getGUID(); //this line caused the error
$model->save();
$studentId = $model->id;
if($user->load(Yii::$app->request->post()))
{
$user->id = $model->id;
$user->firstname = $model->firstname;
$user->lastname = $model->lastname;
$user->username = $model->phone;
$user->password = 'pass123'; //default password
$user->role = 'student';
$user->save(false);
}
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
'user' => $user,
]);
}
Please take a look at Yii2 guide on Components

Prestashop 1.7 - Overriding module class

i try to overriding a module in my custom themes, so I have copy past the original folder (from module folder in my themes > themename > modules folder)
but its not working
I have in my module folder from my theme :
ps_sharebuttons > views
and
ps_sharebuttons > ps_sharebuttons.php
which contains
<?php
if (!defined('_PS_VERSION_')) {
exit;
}
class Ps_SharebuttonsOverride extends Ps_Sharebuttons
{
public function renderWidget($hookName, array $params)
{
var_dump($params);
exit;
$key = 'ps_sharebuttons|' . $params['product']['id_product'];
if (!empty($params['product']['id_product_attribute'])) {
$key .= '|' . $params['product']['id_product_attribute'];
}
if (!$this->isCached($this->templateFile, $this->getCacheId($key))) {
$this->smarty->assign($this->getWidgetVariables($hookName, $params));
}
return $this->fetch($this->templateFile, $this->getCacheId($key));
}
public function getWidgetVariables($hookName, array $params)
{
if (!isset($this->context->controller->php_self) || $this->context->controller->php_self != 'product') {
return;
}
$product = $this->context->controller->getProduct();
if (!Validate::isLoadedObject($product)) {
return;
}
$social_share_links = [];
$sharing_url = addcslashes($this->context->link->getProductLink($product), "'");
$sharing_name = addcslashes($product->name, "'");
$image_cover_id = $product->getCover($product->id);
if (is_array($image_cover_id) && isset($image_cover_id['id_image'])) {
$image_cover_id = (int)$image_cover_id['id_image'];
} else {
$image_cover_id = 0;
}
$sharing_img = addcslashes($this->context->link->getImageLink($product->link_rewrite, $image_cover_id), "'");
if (Configuration::get('PS_SC_FACEBOOK')) {
$social_share_links['facebook'] = array(
'label' => $this->trans('Share', array(), 'Modules.Sharebuttons.Shop'),
'class' => 'facebook',
'url' => 'http://www.facebook.com/sharer.php?u='.$sharing_url,
);
}
if (Configuration::get('PS_SC_TWITTER')) {
$social_share_links['twitter'] = array(
'label' => $this->trans('Tweet', array(), 'Modules.Sharebuttons.Shop'),
'class' => 'twitter',
'url' => 'https://twitter.com/intent/tweet?text='.$sharing_name.' '.$sharing_url,
);
}
if (Configuration::get('PS_SC_GOOGLE')) {
$social_share_links['googleplus'] = array(
'label' => $this->trans('Google+', array(), 'Modules.Sharebuttons.Shop'),
'class' => 'googleplus',
'url' => 'https://plus.google.com/share?url='.$sharing_url,
);
}
if (Configuration::get('PS_SC_PINTEREST')) {
$social_share_links['pinterest'] = array(
'label' => $this->trans('Pinterest', array(), 'Modules.Sharebuttons.Shop'),
'class' => 'pinterest',
'url' => 'http://www.pinterest.com/pin/create/button/?media='.$sharing_img.'&url='.$sharing_url,
);
}
return array(
'social_share_links' => $social_share_links,
);
}
}
But prestashop still use the orignal file module because i get this error :
'Undefined index: product', '/home/xxxxxxxx/www/modules/ps_sharebuttons/ps_sharebuttons.php',
I've already clear cache
Thanks for help
Ok im stupid, the override view goes to theme > module folder but the class should be in override > module folder

How to implement kartik yii2 FileInput in form Update while using different models

I have followed this solution in working with multiple models to upload using files using kartik fileinput during actionCreate.
My problem is achieving the same during actionUpdate, I keep on receiving the error below:
Either 'name', or 'model' and 'attribute' properties must be specified.
My form view is as follows:
echo $form->field($document,'document[]')->widget(FileInput::classname(), [
'options' => ['multiple' => true],
'pluginOptions' => [
// 'previewFileType' => 'any',
'showPreview' => false,
'showUpload' => false
], ]);
Whereas my controller actionUpdate is as follows
public function actionUpdate($id)
{
//$document = new EmployeeDocuments();
$model = $this->findModel($id);
$document = EmployeeDocuments::find()->indexBy('employee_id')->all();
$empavatar=$model->avatar;
$oldavatar=Yii::$app->session['oldavatar'] = $empavatar;
if ($model->load(Yii::$app->request->post()) ) {
// print_r($model); exit;
// $attachments = UploadedFile::getInstances($document, 'document');
// print_r($attachments); exit;
if($model->avatar==""){
$model->avatar=$oldavatar;
}
if ($model->save()){
if(!empty($attachments)){
foreach($attachments as $attachment):
$ext = end((explode(".", $attachment)));
$filename=end((explode(">", $attachment)));
$filename = ucwords(substr($filename, 0, strpos($filename, '.')));
// generate a unique file name
$file2save = Yii::$app->security->generateRandomString().".{$ext}";
$path=Yii::getAlias('#loc').'/uploads/employees/docs/'; //set directory path to save image
$attachment->saveAs($path.$model->id."_".$file2save); //saving img in folder
$attachment = $model->id."_".$file2save; //appending id to image name
\Yii::$app->db->createCommand()
->insert('lcm_hrm_employee_documents', ['document' => $attachment, 'name'=>$filename,'employee_id'=>$model->id])
->execute(); //manually update image name to db /* */
endforeach;
}
return $this->redirect(['view', 'id' => $model->id]);
}
else {
return $this->render('update', [
'model' => $model, 'document'=>$document
]);
}
} else {
return $this->render('update', [
'model' => $model, 'document'=>$document
]);
}
}
Change your form view to
echo $form->field($document,'document[]')->widget(FileInput::classname(), [
'options' => ['multiple' => true],
'attribute' =>'document[]',
'pluginOptions' => [
// 'previewFileType' => 'any',
'showPreview' => false,
'showUpload' => false
], ]);

`Skip on empty` not working in Yii2 file upload

I have a provision to upload logo for companies in my application. Uploading and saving on creating profile works fine. But on update, logo goes empty if I am not uploading it again!
Here's my update form
<?php $form = ActiveForm::begin([
'options' => ['enctype'=>'multipart/form-data']
]); ?>
.....
<?= $form->field($model, 'logo')->fileInput() ?>
...
My Controller action
if ($model->load($_POST) ) {
$file = \yii\web\UploadedFile::getInstance($model, 'logo');
if($file){
$model->logo=$file; }
if($model->save()){
if($file)
$file->saveAs(\Yii::$app->basePath . '/web/images/'.$file);
}
return $this->redirect(['profile']);
} else {
return $this->renderPartial('update', [
'model' => $model,
]);
}
My Rules:
public function rules()
{
return [
[['logo'], 'image', 'extensions' => 'jpg,png', 'skipOnEmpty' => true],
[['name'], 'required'],
[['name', 'description'], 'string'],
];
}
Any ideas????
skipOnEmpty does not apply here because in the update action the $model->logo attribute will not be empty, it will be a string with the file name.$file is still an array with only keys, but not values if not uploaded again. So checked the $file->size instead of checking !empty($file). Fixed the issue by modifying the controller code as follows!
$model = $this->findModel($id);
$current_image = $model->featured_image;
if ($model->load(Yii::$app->request->post())) {
$image= UploadedFile::getInstance($model, 'featured_image');
if(!empty($image) && $image->size !== 0) {
//print_R($image);die;
$image->saveAs('uploads/' . $image->baseName . '.' .$image->extension);
$model->featured_image = 'uploads/'.$image->baseName.'.'.$image->extension;
}
else
$model->featured_image = $current_image;
$model->save();
return $this->redirect(['update', 'id' => $model->module_id]);
} else {
return $this->render('add', [
'model' => $model,
]);
}
'skipOnEmpty' => !$this->isNewRecord
For update it can be skipped.

Yii CForm, Nested Forms Ajax Validation

I have created the following nested forms array;
return array(
'elements' => array(
'contact' => array(
'type' => 'form',
'elements' => array(
'first_name' => array(
'type' => 'text',
),
'last_name' => array(
'type' => 'text',
)
),
),
'lead' => array(
'type' => 'form',
'elements' => array(
'primary_skills' => array(
'type' => 'textarea',
),
),
),
),
'buttons' => array(
'save-lead' => array(
'type' => 'submit',
'label' => 'Create',
'class' => 'btn'
),
)
);
i have view page like this
echo $form->renderBegin();
echo $form['lead'];
echo $form['contact'];
echo $form->buttons['save-lead'];
echo $form->renderEnd();
my actionCreate is like this
$form = new CForm('application.views.leads.register');
$form['lead']->model = new Lead;
$form['contact']->model = new Contact;
// how can i perform ajax validation only for $form['contact']
$this->performAjaxValidation($model);
//if contact form save btn is clicked
if ($form->submitted('save-lead') && $form['contact']->validate() &&
$form['lead']->validate()
) {
$contact = $form['contact']->model;
$lead = $form['lead']->model;
if ($contact->save()) {
$lead->contact_id = $contact->id;
if ($lead->save()) {
$this->redirect(array('leads/view', 'id' => $lead->id));
}
}
}
ajax validation method is
protected function performAjaxValidation($model)
{
if (isset($_POST['ajax']) && $_POST['ajax'] === 'contact') {
echo CActiveForm::validate($model);
Yii::app()->end();
}
}
so my question is how can i perform ajax validation on $form['contact'] and $form['lead'] elements individually?
You can have several forms in a page but they should not be nested.
Nested forms are invalid.
You should make your own validation
in actionCreate and actionUpdate of your controller you must add (i have main model "Invoice" and secondary "InvoiceDetails", and there could be more than 1 form for InvoiceDetails). But of course forms cannot be nested!
public function actionCreate()
{
...
$PostVar = 'Invoices';
if (Yii::app()->request->isAjaxRequest)
{ // if ajax
$this->performAjaxValidation($model, strtolower($PostVar) . '-form');
$PostVar = ucfirst($PostVar);
if (isset($_POST[$PostVar]))
{
$model->attributes = $_POST[$PostVar];
$dynamicModel = new InvoiceDetails(); //your model
$valid = self::validate($model, $dynamicModel);
if (!isset($_POST['ajax']))
{
if (isset($_POST['InvoiceDetails']))
{
$allDetails = array();
$allDynamicModels = $_POST['InvoiceDetails'];
//your own customization
foreach ($allDynamicModels as $key => $value)
{
$InvDet = InvoiceDetails::model()->findByPk($_POST['InvoiceDetails'][$key]['id']);
if (!isset($InvDet))
{
$InvDet = new InvoiceDetails();
}
$InvDet->attributes = $_POST['InvoiceDetails'][$key];
$InvDet->save();
$allDetails[] = $InvDet;
}
}
$model->invoicedetails = $allDetails;
if ($model->save())
{
echo CJSON::encode(array('status' => 'success'));
Yii::app()->end();
}
else
{
echo CJSON::encode(array('status' => 'error saving'));
Yii::app()->end();
}
}
// Here we say if valid
if (!isset($valid))
{
echo CJSON::encode(array('status' => 'success'));
}
else
{
echo $valid;
}
Yii::app()->end();
}
else
{
$this->renderPartial('_form', ...);
}
}
else
{
// not AJAX request
$this->render('_form', ...));
}
Nested Forms are invalid. You can use scenarios to validate the form at different instances.
Example:
`if ($form->submitted('save-lead'){
$form->scenario = 'save-lead';
if($form->validate()) {
$form->save();
}
} else {
$form->scenario = 'contact';
if($form->validate()){
$form->save();
}
}
$this->render('_form', array('form'=>$form);`