Yii2 Captcha Image not showing - yii2

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

Related

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 multi captcha in one page

I have a page that contains multi captcha in separated forms form example login and register modals , etc.
if I use below codes the problem is that when refresh one captcha then another captcha will be unusable because they use same session varible:
1) Login
login modal (view):
echo Captcha::widget([
'id' => 'Login-captcha',
'name' => 'LoginModel[captcha]',
'captchaAction' => '/site/captcha'
]);
LoginModel :
public function rules()
{
return [
['captcha', 'captcha'],
];
}
2) Register
register modal (view):
echo Captcha::widget([
'id' => 'register-captcha',
'name' => 'RegisterModel[captcha]',
'captchaAction' => '/site/captcha'
]);
RegisterModel:
public function rules()
{
return [
['captcha', 'captcha'],
];
}
to solve session problem I used different captcha actions to set different session variables:
1)Login
login modal view:
echo Captcha::widget([
'id' => 'Login-captcha',
'name' => 'LoginModel[captcha]',
'captchaAction' => '/site/captcha-login'
]);
LoginModel :
public function rules()
{
return [
['captcha', 'captcha', 'captchaAction' => 'site/captcha-login',],
];
}
2) Register
register modal (view):
echo Captcha::widget([
'id' => 'register-captcha',
'name' => 'RegisterModel[captcha]',
'captchaAction' => '/site/captcha-register'
]);
RegisterModel:
public function rules()
{
return [
['captcha', 'captcha', 'captchaAction' => 'site/captcha-register',],
];
}
until now everything is ok but when I move sessions from regular php files to database by below config in commponent section of main config file:
'session' => [
'class' => 'yii\web\DbSession',
],
then captchas in the first page load not works and have to refresh them to work correctly.
what is the problem?
Try this, it is for yii1 but you can get the idea, more detail
public function rules()
{
return array(
...
array('verifyCode1', 'captcha', ...
array('verifyCode2', 'verifycaptcha2', ...
);
}
public function verifycaptcha2($attribute, $params)
{
$captcha2 = Yii::app()->getController()->createAction('captcha2nd');
if (!$captcha2->validate($this->verifyCode2, false))
{
$this->addError('verifyCode2', 'invalid captcha.');
}
}
Also see this

Capcha always show incorrect

I have used capcha in one of my forms. It always give verification code incorrect error.
Below is my code:
SchoolsController.php
public function actions() {
return [
'captcha' => [
'class' => 'yii\captcha\CaptchaAction',
'fontFile' => '#yii/captcha/SpicyRice.ttf',
'padding' => '0',
]
];
}
Model:
['verifyCode', 'captcha', 'captchaAction' => 'schools/captcha'],
View:
echo $form->field($modelSchoolRequestEarlyAccess, 'verifyCode')->widget(Captcha::className(), [
'options' => [
'placeholder' => 'Enter characters in the image',
'autocomplete' => 'off',
'maxlength' => 20
],
'captchaAction' => 'schools/captcha',
'template' => "<div class='field'><span><strong>*</strong>".Yii::t('frontend/quicksignup','VerifyCodeLabel').":</span></span>\n<div>{image}{input}<i class='refresh-code-icn' id='get-new-code'></i></div></div>"
])->label(false);
I have specified the captcha action as schools/captcha in model as well as view. But it always show verification incorrect.
What am I doing wrong??
You wrote SchoolController.php and your route is to schools. So you probably need to adjust your route to school/captcha
Did you add the rules?
public function rules()
{
$rules = parent::rules();
$rules[] = ['captcha', 'required'];
$rules[] = ['captcha', 'captcha'];
return $rules;
}

yii2 createUrl is duplicating the route

i'm building multi lingual site with English and Arabic
url for English
url for Arabic
I want to switch language from any page exactly to the same page of the other language
so i made code like below.
$route = Yii::$app->controller->route;
$params = $_GET;
array_unshift($params, '/'.$route);
<?php if(Yii::$app->language == 'ar'){ ?>
<?= Html::a('English', [Yii::$app->urlManager->createUrl($params), 'language'=>'en']); ?>
<?php }else{?>
<?= Html::a('Arabic', [Yii::$app->urlManager->createUrl($params), 'language'=>'ar']); } ?>
and my url generating like below
/multi/backend/web/en/multi/backend/web/ar/site/index?val=hii&net=good
English
don't know what is wrong?
I'm using this for language management.
please check my main.php under backend/config
<?php
$params = array_merge(
require(__DIR__ . '/../../common/config/params.php'),
require(__DIR__ . '/../../common/config/params-local.php'),
require(__DIR__ . '/params.php'),
require(__DIR__ . '/params-local.php')
);
return [
'id' => 'app-backend',
'basePath' => dirname(__DIR__),
'controllerNamespace' => 'backend\controllers',
'language' => 'en',
'sourceLanguage' => 'en_UK',
'bootstrap' => ['log'],
'modules' => [],
'components' => [
'user' => [
'identityClass' => 'common\models\User',
'enableAutoLogin' => true,
],
'log' => [
'traceLevel' => YII_DEBUG ? 3 : 0,
'targets' => [
[
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning'],
],
],
],
'errorHandler' => [
'errorAction' => 'site/error',
],
'i18n' => [
'translations' => [
'app' => [
'class' => 'yii\i18n\DbMessageSource',
'sourceLanguage' => 'en_UK',
],
],
],
'urlManager' => [
'class' => 'codemix\localeurls\UrlManager',
'languages' => ['en', 'ar'],
'enableDefaultLanguageUrlCode' => false,
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
],
],
],
'params' => $params,
];
If you are doing it as in your example, you have to think about it on every link you create. This can be automated easily.
URL-Rule
You can solve this with an url-rule in your config file like so:
'<language:[\w]{2,2}>/<controller:\w+>/<action:\w+>'=>'<controller>/<action>',
This will assert the proper routing to your controller and provide you the desired language in the language-variable.
Custom UrlManager
You can extend the UrlManager-class and make sure the current language is always appended to the params:
class MyUrlManager extends \yii\web\UrlManager
{
// ...
/**
* #inheritdoc
*/
public function createUrl($params)
{
if (!isset($params['language'])) {
$params['language'] = Yii::$app->language;
}
return parent::createUrl($params);
}
// ...
}
This will automate the process of adding the language to the links you create.
Custom Application
Now you should also override the Application-class and always set the language to the one provided or choose a default (in this case en):
class MyApplication extends \yii\web\Application
{
// ...
/**
* #inheritdoc
*/
public function init()
{
parent::init();
$lang = Yii::$app->request->get('language', 'en');
Yii::$app->language = $lang;
}
// ...
}
Now your language will always be set to the default value or the one provided viathe query param as specified above.
Final thoughts
This should give you the basic idea on how to solve your problem. Adjust as necessary...especially the last part with the Application-class and how you retrieve the value of the language-var. I hope it helped!
Possible problems with your code and the extension provided
If you read the docs of the extension the urls are generated differently. It tells you to create the urls as follows:
Url::to(['demo/action', 'language'=>'ar'])
You are createing a simple link-tag and overwrite the $params. Try this instead:
echo Html::a('Arabic', Url::to(['site/index', 'language'=>'ar']));
For redirection to the current page just replace the first part with the current route.
after lots of trying ..i found a solution.. now its worked for me.
$route = Yii::$app->controller->route;
if(Yii::$app->language == 'ar'){
$_GET['language'] = 'en';
}else{
$_GET['language'] = 'ar';
}
$params = $_GET;
array_unshift($params, '/'.$route);
<?php if(Yii::$app->language == 'ar'){ ?>
<?= Html::a('English', Yii::$app->urlManager->createUrl($params)); ?>
<?php }else{?>
<?= Html::a('Arabic', Yii::$app->urlManager->createUrl($params)); } ?>
its working for the url like
http://localhost/multi/backend/web/site/index?page=2&per-page=6
and
http://localhost/multi/backend/web/site/index

yii2: get relation data in kartik editable widget

I am using kartik yii2 editable extension to edit inline in gridview.
The extension is working fine.
Please refer this screen-shot link [http://awesomescreenshot.com/00753dvb73][1]
In this screen-shot the source field is a dropdown and I want the value of source instead id its id
My View
use kartik\editable\Editable;
[
'attribute'=>'source',
'format'=>'raw',
'value'=> function($data){
//$s = $data->getBacklog_source();//var_dump($s);exit;
return Editable::widget([
'name'=>'source',
'model'=>$data,
'value'=>$data->source,
'header' => 'Source',
'type'=>'primary',
'size'=> 'sm',
'format' => Editable::FORMAT_BUTTON,
'inputType' => Editable::INPUT_DROPDOWN_LIST,
'data'=>$data->getSource(), // any list of values
'options' => ['class'=>'form-control', 'prompt'=>'Select Source'],
'editableValueOptions'=>['class'=>'text-danger'],
'afterInput' => Html::hiddenInput('id',$data->id),
]);
}
],
The relation I made is:
public function getSource()
{
$source = BacklogSource::find()->all();
return ArrayHelper::map($source, 'id', 'Source');
}
public function getBacklog_complexity()
{
return $this->hasOne(BacklogComplexity::className(), [
'id' => 'complexity'
]);
}
Thanks for help in advance
I got the solution something like this:
[
'attribute'=>'status',
'format'=>'raw',
'value'=> function($data){
$s = BacklogStatus::findOne($data->status);
return Editable::widget([
'name'=>'status',
'model'=>$data,
'value'=>$s->Status,
'header' => 'Status',
'type'=>'primary',
'size'=> 'sm',
'format' => Editable::FORMAT_BUTTON,
'inputType' => Editable::INPUT_DROPDOWN_LIST,
'data'=>$data->getStatus(), // any list of values
'options' => ['class'=>'form-control', 'prompt'=>'Select Source'],
'editableValueOptions'=>['class'=>'text-danger'],
'afterInput' => Html::hiddenInput('id',$data->id),
]);
}
],