Call to a member function saveAs() on a non-object - yii2

I am trying to upload image and database table.
on database table basic_info field name 'photo' that i want to store file name.
here is model
public function rules()
{
return [
[['photo'], 'string', 'max' => 255],
[['image'], 'safe'],
[['image'], 'file', 'extensions'=>'jpg, gif, png'],
];
}
here is controller
public function actionCreate()
{
$model = new BasicInfo();
if ($model->load(Yii::$app->request->post()))
{
$model->image = UploadedFile::getInstance($model, 'image');
$filename = pathinfo($model->image , PATHINFO_FILENAME);
$ext = pathinfo($model->image , PATHINFO_EXTENSION);
$newFname = $filename.'.'.$ext;
$path=Yii::getAlias('#membersImgPath');
if(!empty($newFname)){
$model->image->saveAs($path.$newFname);
$model->image = $newFname;
if($model->save()){
return $this->redirect(['view', 'id' => $model->id]);
}
}
}
return $this->render('create', [
'model' => $model,
]);
}
here is view
echo FileInput::widget([
'name' => 'photo',
'options' => ['accept' => 'image/*'],
]);

from your comment here,
$form = ActiveForm::begin(['type'=>ActiveForm::TYPE_VERTICAL],['opti‌​ons'=>['enctype'=>'m‌​ultipart/form-data']‌​]);
ActiveForm::begin does not have a second parameter. you need to use a single options array.
$form = ActiveForm::begin([
'type' => ActiveForm::TYPE_VERTICAL,
'opti‌​ons' => [
'enctype' => 'm‌​ultipart/form-data'
]‌
​]);

First of all, you have to check if there's a file. To do it try:
if(UploadedFile::getInstance($model, 'image')) {
// here should go your code with $model->image
}
Youre using pathinfo to get filename and extension. Remember, that youre using powerfull framework, you just initialized class UploadedFile which can do everything for you:
if(UploadedFile::getInstance($model, 'image')) {
$model->image = UploadedFile::getInstance($model, 'image');
$newFname = $model->image->name; // UploadedFile have properties like `name`, `tempName`, even `size`!
}
After doing this small fixes to your code (you should always check if something is set) - we can go to main problem.
Your input field name is photo, but youre trying to get image with name image.
Change this:
UploadedFile::getInstance($model, 'image');
To this:
UploadedFile::getInstance($model, 'photo'); // remeber to change it in `if` statement aswell!!
Theres also posibility that youre trying to upload file bigger than your post_max_size and upload_max_filesize allows. Change this properties in your php.ini, restart server and try again. If still something is not right, try to debug this thing, for start by doing var_dump($_FILES);die; in your controller.

Related

Yii2 upload multiple success but save only first value to database

I'm coding a multiple upload function for my website. The upload was successful. But it's only save the first value to my database. Example i upload 3 files name 1.jpg, 2.jpg, 3.jpg. Then it will upload the 3 files successfully but save only the 1.jpg's name to database.
My controllers
public function actionCreate()
{
$model = new Resource3d();
if ($model->load(Yii::$app->request->post())) {
$model->files = UploadedFile::getInstances($model, 'files');
foreach ($model->files as $files){
$files->saveAs('uploads/resource3d/' . $files->baseName . $files->extension);
$model->path = '../web/uploads/resource3d/'. $files->baseName . $files->extension;
$model->name = $files->baseName;
$model->save();
}
return $this->redirect(['index']);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
My models:
public $files;
public function rules()
{
return [
[['name', 'path'], 'string', 'max' => 255],
[['files'], 'file', 'skipOnEmpty' => false, 'maxFiles' => 0],
];
}
Please help.
Thank you.
You are creating single object of your model Resource3d. You need to create multiple object if you want to save multiple records.
Try this :
public function actionCreate()
{
$model = new Resource3d();
if ($model->load(Yii::$app->request->post())) {
$model->files = UploadedFile::getInstances($model, 'files');
foreach ($model->files as $files){
$res_model = new Resource3d();
$res_model->load(Yii::$app->request->post());
$files->saveAs('uploads/resource3d/' . $files->baseName . $files->extension);
$res_model->path = '../web/uploads/resource3d/'. $files->baseName . $files->extension;
$res_model->name = $files->baseName;
$res_model->save();
}
return $this->redirect(['index']);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
This is just an example, change it according to your need.

Yii 2 error - Trying to get a property of non object

I was trying to search the needed information, but couldn't find any of that. Somehow, I get this error and I don't know where I'm doing a mistake.
Here is my action:
public function actionFilter()
{
$filterParams = Yii::$app->request->get();
unset($filterParams['r']);
$model = new Sale();
$dataProvider = $model->filterParameters($filterParams);
return $this->render('filter', [
'dataProvider' => $dataProvider,
'filterParams' => $filterParams,
]);
}
And here is my view:
'attribute' => 'sale_id',
'width' => '14%',
'value' => function (Sale $model) {
return $model->sale->client->getClientName();
}
],
[
'attribute' => '',
'value' => function (Sale $model) {
return $model->sale->client->getClientSale();
}
],
I'm getting the error on the 'value' return line. The function getClientName() is in client model. Could someone explain what I'm doing wrong? Thanks for any help.
Propably there's no model linked to your main $model. You should check if it's set by:
return $model->debtor && $model->debtor->client ? $model->debtor->client->getFullName() : null;
AND
return $model->debtor && $model->debtor->user ? $model->debtor->user->getFullName() : null;
The answer is simple:
Turn-off PHP Notice Errors in PHP.ini
error_reporting E_ALL & ~E_NOTICE
In your view; just add # before the $model to override the problem. Find an example below:
return #$model->sale->client->getClientName();

Trying to get property of non-object while using kartik-v for image uploading in Yii2

I'm using yii2-widget-fileinput for an image uploading in a form.
When I click on upload or the create button I get Trying to get property of non-object error in controller.
Controller
public function actionCreate()
{
Yii::$app->params['uploadPath'] = Yii::$app->basePath . '/uploads/';
$model = new Ads();
$provinces = ArrayHelper::map(Province::find()->all(), 'name', 'name');
if ($model->load(Yii::$app->request->post())){
$image = UploadedFile::getInstances($model, 'image');
$model->filename = $image->name;
$ext = end((explode(".", $image->name)));
$avatar = Yii::$app->security->generateRandomString().".{$ext}";
$path = Yii::$app->params['uploadPath'].$avatar;
if ($model->save()) {
$image->saveAs($path);
$model->image_adr = $path;
return $this->redirect(['view', 'id' => $model->id]);
}else{
echo "error on saving the model";
}
}
return $this->render('create', [
'model' => $model,
'provinces'=>$provinces,
]);
}
model rules
public function rules()
{
return [
[['type', 'explanation', 'cost', 'province_name', 'address'], 'required'],
[['type', 'explanation', 'image_adr', 'address'], 'string'],
[['cost'], 'integer'],
[['province_name'], 'string', 'max' => 20],
[['province_name'], 'exist', 'skipOnError' => true, 'targetClass' => Province::className(), 'targetAttribute' => ['province_name' => 'name']],
[['image'],'safe'],
[['image'], 'file', 'extensions'=>'jpg, gif, png', 'maxFiles'=>3,],
];
and finnally the view
<?= $form->field($model, 'image[]')->widget(FileInput::classname(), [
'options'=>['accept'=>'image/*', 'multiple'=>true],
'pluginOptions'=>['allowedFileExtensions'=>['jpg','gif','png'], 'overwriteInitial'=>false,]
]); ?>
the problem should refer to this part in the controller I think
$image = UploadedFile::getInstances($model, 'image');
An image of the error might be helpful
You should check first is image in post or not.
....
$image = UploadedFile::getInstances($model, 'image'); //getInstanceByName
if (!empty($image))
$model->filename = $image->name;
.....
if ($model->save()) {
if (!empty($image))
$image->saveAs($path);
.........
Make sure in your form ency type is added:
$form = ActiveForm::begin([
'id' => 'form_id',
'options' => [
'class' => 'form_class',
'enctype' => 'multipart/form-data',
],
]);
The problem is when you're using UploadedFile::getInstances($model, 'image'); you should work with foreach or treat it like an array.
Something that made me a problem was that even if you're using UploadedFile::getInstanc (notice the obsoleted s in the end) you should still treat it like an array and in all parts you should use $image[0], not $iamge lonely.

Yii2 ActiveForm unique validation not show error message

This is my model contacts,
public function rules()
{
return [
[['fname', 'status','mobile',], 'required'],
[['user_id', 'contact_type','group_type','passport_no','trip_id','group_id','state',], 'integer'],
[['fname', 'mname', 'lname', 'status', 'street', 'location', 'post', 'city', 'district','email','job_title','company_name','source'], 'string', 'max' => 500],
[['department'], 'string', 'max' => 40],
[['pincode'], 'string', 'max' => 15],
[['mobile'],'unique'],
Here the required validation of mobile works and show error message, but unique rule works but it doesn't show any error message
Help me plz.
1) Unique validation work with database.
2) Once form was submitted then validation was checked and model not saved because of unique validation fails.
3) If you want to unique validation on form then use Ajax.
For this, You need to set 'enableAjaxValidation' => true,
$form = ActiveForm::begin([
'id' => 'contact-form',
'enableAjaxValidation' => true,
]);
Controller:
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post()))
{
Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
Reference
Maybe you should also set targetClass:
['email', 'unique', 'targetClass' => '\common\models\User']
I am assuming your view page as register.php. So,
register.php (View)
1) Remove use yii\bootstrap\ActiveForm; (if present)
2) Add use yii\widgets\ActiveForm;
3) Add 'enableAjaxValidation' => true in that field (Where you are validating it. Like below)
<?= $form->field($model, 'mobile',['enableAjaxValidation' => true])->textInput(['class'=>'form-control']) ?>
Controller
See below (Add this line wherever I have written //Add This Line)
.
.
use yii\web\Response; // Add This line
use yii\widgets\ActiveForm; //Add This Line
.
.
Class SomeClass
{
.
.
.
public function actionRegister() {
$model = new Candidate();
//Add This For Ajax Mobile Exist Validation
if(Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())){
Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
else if ($model->load(Yii::$app->request->post())) {
.
// Your code
.
.
}
}
}
Model
[['mobile'],'unique','message'=>'Mobile No Already Exist'],
For Reference - Click Validate unique value from database in Yii2
if ($model->validate()) {
//SAVE YOUR DATA
} else {
// HERE YOU CAN PRINT THE ERRORS OF MODEL
$data = $model->getErrors();
Yii::$app->session->setFlash('message', $data['password'][0]);// its dislplays error msg on your form
}
This rule in my model worked for me:
['email', 'required'],
['email', 'email'],
['email', 'unique', 'targetClass' => '\app\models\Student', 'message' => 'This email address has already been taken.'],

Yii2 Kartik-V Typeahead Advanced Widget: How to store result in Mysql

Tearing my hair out at this point, hopefully someone can help me out!
I am using the Kartik-V Typeahead Advanced widget with Yii2.
The plugin works, in that the functionality is working perfectly on the page, I search and the results appear in the auto complete list.
Unfortunately, I am unable to store the result in my database. I am seeing an issue on the following line:
->where([ 'name' => $model->name ])//This variable is returning null
Am I trying to store the data incorrectly? I have tried everything I can think of, but I am sure someone here will come up with something better!
See below for the full code.
My controller:
public function actionIndex()
{
$model = new Member();
if ($model->load(Yii::$app->request->post())) {
$test = Test::find()
->where([ 'name' => $model->name ])//This variable is returning null
->one();
$test->updateCounters(['times_used' => 1]);
}
return $this->render('index', [
'model' => $model,
]);
}
/*************
* Initial prefetch of results
*************/
public function actionPrefetchlist() {
$query = new Query;
$query->select('name')
->from('test_table')
->limit(10)
->orderBy('times_used');
$command = $query->createCommand();
$data = $command->queryAll();
$out = [];
foreach ($data as $d) {
$out[] = ['value' => $d['name']];
}
echo Json::encode($out);
}
/*************
* Remote results
*************/
public function actionRemotelist() {
$query = new Query;
$query->select('name')
->from('test_table')
->where('name LIKE "%' . $q .'%"')
->limit(10)
->orderBy('times_used');
$command = $query->createCommand();
$data = $command->queryAll();
$out = [];
foreach ($data as $d) {
$out[] = ['value' => $d['name']];
}
echo Json::encode($out);
}
The view file:
echo $form->field($model, 'name')->label(false)->widget(Typeahead::classname(), [
'name' => 'name',
'options' => ['placeholder' => 'Filter as you type ...'],
'pluginOptions' => ['highlight'=>true],
'dataset' => [
[
'datumTokenizer' => "Bloodhound.tokenizers.obj.whitespace('value')",
'display' => 'value',
'prefetch' => Url::to(['prefetchlist']),
'remote' => [
'url' => Url::to(['remotelist']) . '?q=%QUERY',
'wildcard' => '%QUERY'
]
]
]
]);
you ask here for a new model:
$model = new Member();
so you get a empty model
so the $model->name is empty
if you set the model $model->name='test';
than it will be filled so, fill the model first
So it turns out it was a massive rookie error.
If anyone else stumbles upon something similar, I removed the attribute name from the model's "rules()"
I need an integer in the database but I wanted users to enter in a string (I would then convert it in the controller). Removing it from the rule broke everything.
Hopefully this helps someone else :)