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

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();

Related

Yii2 virtual attribute out of an attribute of a SqlDataProvider

My AddressController:
public function actionIndex() {
$searchModel = new AddressSearch;
$dataProvider = $searchModel->search($_GET);
return $this->render('index', [
'dataProvider' => $dataProvider,
'searchModel' => $searchModel,
]);
}
My model AddressSearch:
class AddressSearch extends Model {
public function search($params) {
$dataProvider = new SqlDataProvider([
'sql' => '
SELECT
name
FROM...
View:
GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
'name2',
I have an attribute called name in this dataProvider. I would like to create a new virtual attribute called name2 out of name by preg_replace()-ing a few parts of it.
The function itself is working. I have tried a lot of different things, but I still can't make it to fill the attribute name2 with data. name2 is always empty. Can you please point me to the right direction? Many thanks!
UPDATE: based on the brilliant ideas of #Imaginaroom and #rob006 I've done the following:
moved getName2() and the attributes I'm filling with SqlDataProvider from base model Address to AddressSearch
deleted the empty base model Address because I don't need it anyway. Less is more!
in search() I've added:
foreach ($dataProvider->getModels() as $row) {
$model = new AddressSearch;
$model->setAttributes($row, false);
$models[] = $model;
}
$dataProvider->setModels($models);
It works! Many thanks guys! It's fantastic that you are there and help!!!
The problem is that you're using SqlDataProvider which returns rows from the table as array instead of model instance. So that's why your getter (virtual-attribute) does not work in GridView - GridView does not work on Address model instance, but on raw array without name2 field.
You should change your SearchModel to use ActiveQuery:
$dataProvider = ActiveDataProvider([
'query' => Address::find()->select(['name']) //and whatever your query contains besides this
])
...
UPDATE: If you don't want to do it like this, you can add your logic directly in GridView like so:
GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
[
'header' => 'Name 2',
'value' => function($model) {
if (isset($this->_name2)) {
return $this->_name2;
}
return $this->_name2 = preg_replace([...
}
]
If you really need Address model instance and use SqlDataProvider at the same time, you may convert array to model instance manually:
$models = [];
foreach ($dataProvider->getModels() as $row) {
$model = Address::instantiate($row);
Address::populateRecord($model, $row);
$models[] = $model;
}
$dataProvider->setModels($models);
You can place this in AddressSearch::search() or create custom SqlDataProvider and override prepareModels().

Yii2 Captcha Image not showing

<?php echo $form->field($model, 'captcha')->widget(Captcha::className(), [
]); ?>
Passed requirement in yii2 requirement like GD and imagick liberies but captcha image is not showing.
} else {
ob_clean(); //Add this line, can solve this problem. Or add in other suitable places
$this->setHttpHeaders();
Yii::$app->response->format = Response::FORMAT_RAW;
return $this->renderImage($this->getVerifyCode());
}
This will help,
please change in \vendor\yiisoft\yii2\captcha\CaptchaAction.php and will show image.
you have to set 'captcha' rules in your model .
['captcha', 'captcha', 'captchaAction' => 'site/captcha']
first captcha is your property and next one is the type of rules
be sure to set controller
public function actions()
{
return [
'error' => [
'class' => 'yii\web\ErrorAction',
],
'captcha' => [
'class' => 'yii\captcha\CaptchaAction',
'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
],
];
}
} else {
ob_clean(); //Add this line, can solve this problem. Or add in other suitable places
$this->setHttpHeaders();
Yii::$app->response->format = Response::FORMAT_RAW;
return $this->renderImage($this->getVerifyCode());
}

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

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.

Yii2 Gii generated create view not working / saving but update does

Just started with Yii (two weeks ago).
TL;DR
Creating through Gii generated views not working, but update does, even they share the form and controller not edited.
Problem:
I use the Yii2 advanced app template.
Then I generated a model through the model generator and controller/views through the CRUD generator.
The only thing I changed is removing the two datetime fields "created_at" and "created_by" from the form and added a TimestampBehavior:
public function behaviors()
{
return [
[
'class' => TimestampBehavior::className(),
'attributes' => [
ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'],
ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'],
],
// if you're using datetime instead of UNIX timestamp:
'value' => new Expression('NOW()'),
],
];
}
The strange case I have is, that the update is working, but the create not. It shows no error, it just stay on the page or renders it newly?
This is the untouched code from the controller:
(Am I getting it right that the "$model->save" in the if should save it to the databse?)
CREATE:
public function actionCreate()
{
$model = new Seminar();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
UPDATE:
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
If further informations are needed please comment.
Thanks.
UPDATE - Solution
After the two helpful answers I tried dump the error and it shows
array(1) { ["created_at"]=> array(1) { [0]=> string(32) "Created At darf nicht leer sein." } }
As suggested I left the "created_at" in the "required" section of the rules. After cleaning it out the create works.
I think it did not show me the error because I deleted the field in the form, since the user should not enter data dirctly.
The Controllers you showed are ok.
There must be something wrong with the model. You can check what the problem is by editing the actionCreate:
public function actionCreate()
{
$model = new Seminar();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
var_dump($model->getErrors());
/*return $this->render('create', [
'model' => $model,
]);*/
}
}
Now, about your changes: since you are using the column names created_at and updated_at you can simplify the behavior by setting:
public function behaviors()
{
return [
TimestampBehavior::className()
];
};
Also, check your model rules() if the fields created_at or updated_at are there, and remove it. They are not needed anymore.
Check the rules in your model and try again. Also, try with $model->save(false). It will save the form without check validation, so the problem is that data doesn't validate.

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 :)