Error with saved method running migration - elasticsearch

In my laravel 5.7 app I use Elasticsearch and in model I use saved and deleted methods of the related Model :
<?php
namespace App;
use DB;
use App\MyAppModel;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
class Vote extends MyAppModel
{
protected $table = 'votes';
protected $elasticsearch_type = 'vote';
protected $primaryKey = 'id';
public $timestamps = false;
public function getTableName(): string
{
return $this->table;
}
protected static function boot() {
parent::boot();
static::deleted(function ($vote ) {
// return; // TO UNCOMMENT
$elastic = app(\App\Elastic\Elastic::class);
$elasticsearch_root_index = config('app.elasticsearch_root_index');
$elasticsearch_type = with(new Vote)->getElasticsearchType();
$elastic->delete([
'index' => $elasticsearch_root_index,
'type' => $elasticsearch_type,
'id' => $vote->id,
]);
});
static::saved(function ($vote) {
// return; // TO UNCOMMENT
$elastic = app(\App\Elastic\Elastic::class);
$elasticsearch_root_index = config('app.elasticsearch_root_index');
$elasticsearch_type = with(new Vote)->getElasticsearchType();
$elastic->delete([
'index' => $elasticsearch_root_index,
'type' => $elasticsearch_type,
'id' => $vote->id,
]);
if ($vote->status == 'A') { // only active votes must be saved in elasticsearch
$elastic->index([
'index' => $elasticsearch_root_index,
'type' => $elasticsearch_type,
'id' => $vote->id,
'body' => [
'id' => $vote->id,
'slug' => $vote->slug,
'name' => $vote->name,
'description' => $vote->description,
]
]);
} // if ($vote->status == 'A') { // only active votes must be saved in elasticsearch
When I modify my data in my editor it works ok, but running seeder command
php artisan migrate:refresh --seed -v
I got error :
...
Migrating: 2018_07_13_150151_create_votes_table
Elasticsearch\Common\Exceptions\Missing404Exception : {"_index":"select_vote","_type":"vote","_id":"2","_version":1,"result":"not_found","_shards":{"total":2,"successful":1,"failed":0},"_seq_no":18,"_primary_term":23}
at /mnt/_work_sdb8/wwwroot/lar/Votes/vendor/elasticsearch/elasticsearch/src/Elasticsearch/Connections/Connection.php:607
603| $exception = new AlreadyExpiredException($responseBody, $statusCode);
604| } elseif ($statusCode === 403) {
605| $exception = new Forbidden403Exception($responseBody, $statusCode);
606| } elseif ($statusCode === 404) {
> 607| $exception = new Missing404Exception($responseBody, $statusCode);
608| } elseif ($statusCode === 409) {
609| $exception = new Conflict409Exception($responseBody, $statusCode);
610| } elseif ($statusCode === 400 && strpos($responseBody, 'script_lang not supported') !== false) {
611| $exception = new ScriptLangNotSupportedException($responseBody. $statusCode);
Exception trace:
1 Elasticsearch\Connections\Connection::process4xxError([])
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/elasticsearch/elasticsearch/src/Elasticsearch/Connections/Connection.php:279
2 Elasticsearch\Connections\Connection::Elasticsearch\Connections\{closure}()
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/react/promise/src/FulfilledPromise.php:25
3 React\Promise\FulfilledPromise::then(Object(Closure))
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/guzzlehttp/ringphp/src/Future/CompletedFutureValue.php:55
4 GuzzleHttp\Ring\Future\CompletedFutureValue::then(Object(Closure))
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/guzzlehttp/ringphp/src/Core.php:341
5 GuzzleHttp\Ring\Core::proxy(Object(GuzzleHttp\Ring\Future\CompletedFutureArray), Object(Closure))
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/elasticsearch/elasticsearch/src/Elasticsearch/Connections/Connection.php:299
6 Elasticsearch\Connections\Connection::Elasticsearch\Connections\{closure}(Object(Elasticsearch\Connections\Connection), Object(Elasticsearch\Transport), [])
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/elasticsearch/elasticsearch/src/Elasticsearch/Connections/Connection.php:177
7 Elasticsearch\Connections\Connection::performRequest("DELETE", "/select_vote/vote/2", [], [], Object(Elasticsearch\Transport))
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/elasticsearch/elasticsearch/src/Elasticsearch/Transport.php:110
8 Elasticsearch\Transport::performRequest("DELETE", "/select_vote/vote/2", [], [])
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/elasticsearch/elasticsearch/src/Elasticsearch/Client.php:1553
9 Elasticsearch\Client::performRequest(Object(Elasticsearch\Endpoints\Delete))
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/elasticsearch/elasticsearch/src/Elasticsearch/Client.php:265
10 Elasticsearch\Client::delete([])
/mnt/_work_sdb8/wwwroot/lar/Votes/app/Elastic.php:33
11 App\Elastic\Elastic::delete(["select_vote", "vote"])
/mnt/_work_sdb8/wwwroot/lar/Votes/app/Vote.php:142
12 App\Vote::App\{closure}(Object(App\Vote))
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php:360
13 Illuminate\Events\Dispatcher::Illuminate\Events\{closure}("eloquent.saved: App\Vote")
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php:209
14 Illuminate\Events\Dispatcher::dispatch("eloquent.saved: App\Vote")
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasEvents.php:162
15 Illuminate\Database\Eloquent\Model::fireModelEvent("saved")
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:692
16 Illuminate\Database\Eloquent\Model::finishSave([])
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:663
17 Illuminate\Database\Eloquent\Model::save()
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php:790
18 Illuminate\Database\Eloquent\Builder::Illuminate\Database\Eloquent\{closure}(Object(App\Vote))
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/laravel/framework/src/Illuminate/Support/helpers.php:1027
19 tap(Object(App\Vote), Object(Closure))
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php:791
20 Illuminate\Database\Eloquent\Builder::create()
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/laravel/framework/src/Illuminate/Support/Traits/ForwardsCalls.php:23
21 Illuminate\Database\Eloquent\Model::forwardCallTo(Object(Illuminate\Database\Eloquent\Builder), "create")
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:1608
22 Illuminate\Database\Eloquent\Model::__call("create")
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:1620
23 Illuminate\Database\Eloquent\Model::__callStatic("create")
/mnt/_work_sdb8/wwwroot/lar/Votes/database/seeds/votesInitData.php:92
24 votesInitData::run()
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:29
25 call_user_func_array([])
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:29
...
If in saved and deleted methods to uncomment return that it works ok (without coping to elasticsearch).
Why Error and how to fix it?
Is there is a way to check that it is called from migration command and exit? Could this salve the problem ?
Thanks!

In similar case I set flag in my settings table in the beginning of Migrations scripts, like
DB::table('settings')->insert([
'name' => 'elastic_automation',
'value' => 'N',
]);
In the last migration script I change the key
Settings::where('name', 'elastic_automation')->update(['value' => 'Y']);
and I check this key in my model events. That works for me!

Related

Type error: Too few arguments to function Illuminate\Mail\Mailer::__construct(), 0 passed - Laravel 5.5

I keep getting while trying to use the mailer
FatalThrowableError in Mailer.php line 93:
Type error: Too few arguments to function Illuminate\Mail\Mailer::__construct(), 0 passed in /var/www/app/app/Services/SendOtpMail.php on line 42 and at least 2 expected
in Mailer.php line 93
at Mailer->__construct() in SendOtpMail.php line 42
at SendOtpMail->send('test#company.com', array('from' => 'no-reply#company.com', 'from_name' => 'Some Company', 'subject' => 'Login Verification', 'data' => array('token' => '3486', 'user' => object(User)), 'view' => 'emails.password')) in GetOtpForLoginService.php line 59
at GetOtpForLoginService->sendEmail('3486', object(User))
Send mail function
public function sendEmail($otp, $user)
{
$user = User::where('email', $user->email)->firstOrFail();
(new SendOtpMail())->send($user->email, [
'from' => env('MAIL_DEAFULT_SENDER'),
'from_name' => env('MAIL_DEAFULT_SENDER_ALIAS'),
'subject' => 'Login Verification',
'data' => [
'token' => $otp,
'user' => $user
],
'view' => 'emails.password'
]);
return true;
}
SendOtpMail.php
<?php
namespace App\Services;
use Illuminate\Mail\Mailer;
class SendOtpMail
{
public function send($to, array $options = array())
{
$callback = function($message) use ($options, $to) {
$message->from($options['from'], isset($options['from_name']) ? $options['from_name'] : null);
$message->to($to, isset($options['to_name']) ? $options['to_name'] : null);
if(isset($options['subject'])) $message->subject($options['subject']);
if(isset($options['priority'])) $message->priority($options['priority']);
if(isset($options['priority'])) $message->priority($options['priority']);
if(isset($options['files'])) {
if (is_array($options['files'])) {
foreach ($options['files'] as $file) {
$message->attach($options[$file]);
}
} else {
$message->attach($options['files']);
}
}
if(isset($options['cc'])) $message->subject($options['cc'], isset($options['cc_name']) ? $options['cc_name'] : null);
if(isset($options['bcc'])) $message->subject($options['bcc'], isset($options['bcc_name']) ? $options['bcc_name'] : null);
};
if(isset($options['view'])) {
$data = isset($options['data']) ? $options['data'] : array();
(new Mailer())->send($options['view'], $data, $callback);
} else {
(new Mailer())->raw($options['message'], $callback);
}
}
}
You are seeing that error because you are instantiating an Illuminate\Mail\Mailer object without specifying its required parameters in the constructor:
// from Laravel source code
public function __construct(string $name, Factory $views, TransportInterface $transport, Dispatcher $events = null)
{
$this->name = $name;
$this->views = $views;
$this->events = $events;
$this->transport = $transport;
}
I suggest you don't send emails this ways. Pls check the docs and follow the instructions.

Laravel 8: Passing Factory properties into children relationships

we are currently working on a laravel 8 application. We are trying to create factories to create some dummy data for manual / developer based application testing.
The current code of my main Database-Seeder is below:
class DatabaseSeeder extends Seeder
{
public function run()
{
$this->call([
UserTableSeeder::class,
]);
\App\Models\User::factory(10)->create();
\App\Models\Activity::factory(5)->create();
/* 1. try
$tenFact = \App\Models\Tenant::factory(2)->has(
\App\Models\Project::factory(2)->state(
function (array $attributes, \App\Models\Tenant $tenant) {
return ['tenant_id' => $attributes['id']];
}
)->hasTasks(5)->hasLocation()
)->hasContracts(3)->create();
*/
/* Currently being used: */
\App\Models\Tenant::factory(10)->has(
\App\Models\Project::factory(5)->hasTasks(5)->hasLocation()
)->hasContracts(3)->create();
}
ProjectFactory.php:
class ProjectFactory extends Factory
{
protected $model = Project::class;
public function definition()
{
return [
'name' => 'Projekt: '. $this->faker->name,
'budget' => $this->faker->randomDigitNotNull*1000,
'progress' => $this->faker->randomDigitNotNull*10,
'budget_used' => $this->faker->randomDigitNotNull*50,
//'tenant_id' => Tenant::factory(),
'location_id' => Location::factory()->hasTenant(1),
];
}
}
LocationFactory.php:
class LocationFactory extends Factory
{
protected $model = Location::class;
public function definition()
{
return [
'name' => 'Standort: ' . $this->faker->company,
'street' => $this->faker->streetName,
'house_number' => $this->faker->buildingNumber,
'house_addition' => $this->faker->secondaryAddress,
'zip' => $this->faker->postcode,
'city' => $this->faker->city,
'tenant_id' => Tenant::factory(),
];
}
}
Our relationships look like this:
Tenant
|-- Project (has: tenant_id, but also has location_id)
| | -- Task (has: project_id)
|-- Locations (has: tenant_id)
|-- Contracts (has: tenant_id)
When creating datasets with the above named Tenant-Factory the following happens:
Tenant->id is being passed to Project(tenant_id)
but: Tenant->id is not being passend to Location (which depends on the tenants id but is also used for Project).
How can we pass the id of \App\Models\Tenant::factory(10) to Project::factory(5)->hasTasks(5)->hasLocation()?
Additionally we do have the problem, that even though we request 10 tenants, we will get around 60, because Location/Project create new objects when they should be using existing ones.
I gave up using the chained usage of the Tenant-Factory - I finally used some for-Loop that connected the related objects to each user by using laravels for() and state() methods:
for ($i=0; $i < 10 ; $i++) {
$tenant = \App\Models\Tenant::factory()->hasContracts(3)->create();
for ($j=0; $j < 5; $j++) {
$location = \App\Models\Location::factory(1)->for($tenant)->create();
$project = \App\Models\Project::factory(1)->state([
'location_id' => $location->first()['id'],
'tenant_id' => $tenant['id']])->hasTasks(5)->create();
}
}
class ProjectFactory extends Factory
{
$location_ids = App\Models\Location::pluck('id')->toArray();
protected $model = Project::class;
public function definition()
{
return [
'name' => 'Projekt: '. $this->faker->name,
'budget' => $this->faker->randomDigitNotNull*1000,
'progress' => $this->faker->randomDigitNotNull*10,
'budget_used' => $this->faker->randomDigitNotNull*50,
//'tenant_id' => Tenant::factory(),
'location_id'=> $faker->randomElement($location_ids),
];
}
}
class LocationFactory extends Factory
{
$tenant_ids = App\Models\Tenant::pluck('id')->toArray();
protected $model = Location::class;
public function definition()
{
return [
'name' => 'Standort: ' . $this->faker->company,
'street' => $this->faker->streetName,
'house_number' => $this->faker->buildingNumber,
'house_addition' => $this->faker->secondaryAddress,
'zip' => $this->faker->postcode,
'city' => $this->faker->city,
'tenant_id'=> $faker->randomElement($tenant_ids),
];
}
}

laravel DB update get changes column

i want to save log of changes when i update something on the database.
there is elegant way to get the column that will be updated (just if there is change).
i want to save the old column value in log..
for example:
$updateUser = DB::table('users')->where('id','1')->update(array('email' => 'new#email.com', 'name' => 'my new name'));
from this i want to get back the old email was in database (if changed) and the old name (again, only if changed)
thanks!
As others have mentioned, Eloquent is a great way to go if using Laravel. Then you can tap directly into Laravel's events using Observers. I have used a method very similar to what is below. Of course, you would need to set up Models for User and AuditLog.
See more info regarding Observers.
https://laravel.com/docs/5.8/eloquent#observers
In Controller Method
$user = User::find(1);
$user->update([
'email' => 'new#email.com',
'name' => 'my new name'
]);
App/Providers/EventServiceProvider.php
class EventServiceProvider extends ServiceProvider
{
// ...
public function boot()
{
User::observe(UserObserver::class);
}
}
App/Observers/UserObserver.php
class UserObserver
{
/**
* The attributes to exclude from logging.
*
* #var array
*/
protected $except = [
'created_at',
'updated_at'
];
/**
* The attributes to mask.
*
* #var array
*/
protected $masked = [
'password',
];
/**
* Listen for model saved event.
*
* #var array
*/
public function saved($model)
{
// search for changes
foreach ($model->getChanges() as $key => $new_value) {
// get original value
$old_value = $model->getOriginal($key);
// skip type NULL with empty fields
if ($old_value === '' && $new_value === null) {
continue;
}
// attribute not excluded and values are different
if (!in_array($key, $this->except) && $new_value !== $old_value) {
// mask designated fields
if (in_array($key, $this->masked)) {
$old_value = '********';
$new_value = '********';
}
// create audit log
AuditLog::create([
'user_id' => auth()->user()->id,
'model_id' => $model->id,
'model' => (new \ReflectionClass($model))->getShortName(),
'action' => 'update',
'environment' => config('app.env'),
'attribute' => $key,
'old_value' => $old_value,
'new_value' => $new_value,
]);
}
}
}
}
I hope this helps!
EDIT: See comment regarding update.
I will suggest 2 options:
1) to use the Eloquent model on every changes,
and then to use the existing methods like :
model->isDirty()
model->getChanges()
you can implement it on the model life cycle of updating / updated events listeners
more information and example you can see here:
https://laravel.com/docs/5.8/events
https://medium.com/#JinoAntony/10-hidden-laravel-eloquent-features-you-may-not-know-efc8ccc58d9e
https://laravel.com/api/5.3/Illuminate/Database/Eloquent/Model.html
2) if you want to log changes even if you are running regular queries and not only via model life cycle,
you can use MySql Triggers on every table updates and then to check OLD vs NEW and insert directly to the log changes db
more information you can find here:
https://dev.mysql.com/doc/refman/8.0/en/trigger-syntax.html
MySQL Trigger after update only if row has changed
Why not just something like this:
$changeArr = ['email' => 'new#email.com', 'name' => 'my new name'];
$id = 1;
$table = 'users';
foreach($changeArr as $key => $value){
DB::table('updateTable')->insert(['table' => $table, 'id' => $id, 'col' => $key, 'oldVal' => $value]);
}
$updateItem = DB::table($table)->where('id', $id)->update($changeArr);
Check for the changed values and update accordingly, saving the old values to log table if changed
$newData = ['email' => 'new#email.com', 'name' => 'my new name'];
$user = App\User::find(1);
$log = [];
if ($user->email != $newData['email']) {
$log['user_id'] = $user->id;
$log['email'] = $user->email;
$user->email = $newData['email'];
} elseif ($user->name != $newData['name']) {
$log['name'] = $user->name;
$user->name = $newData['name'];
$logged = DB::table('log')->insert($log);
}
$updateUser = $user->save();
//try this. hpe it helps out:
function Update(Request $request, $id)
{
$dbrecord = DB::table('users')->where('id',$id)->first();
$oldemail = $dbrecord->email;
$oldname = $dbrecord->name;
if(($oldemail==$request->input('email'))&&($oldname==$request->input('name')))
{
//do nothing
}
elseif(($oldemail!=$request->input('email'))or($oldname!=$request->input('name')))
{
$updateUser = DB::table('users')->where('id',$id)->update(array('email' => $request->input('email'), 'name' => $request->input('name')));
if($updateUser)
{
DB::table('log')->where('id',$id)->insert(array('email' => $oldemail, 'name' => $oldname));
}
}
}

Extend Laravel package

I've searched around and couldn't find a definitive answer for this...
I have a package DevDojo Chatter and would like to extend it using my application. I understand I'd have to override the functions so that a composer update doesn't overwrite my changes.
How do I go about doing this?
UPDATE
public function store(Request $request)
{
$request->request->add(['body_content' => strip_tags($request->body)]);
$validator = Validator::make($request->all(), [
'title' => 'required|min:5|max:255',
'body_content' => 'required|min:10',
'chatter_category_id' => 'required',
]);
Event::fire(new ChatterBeforeNewDiscussion($request, $validator));
if (function_exists('chatter_before_new_discussion')) {
chatter_before_new_discussion($request, $validator);
}
if ($validator->fails()) {
return back()->withErrors($validator)->withInput();
}
$user_id = Auth::user()->id;
if (config('chatter.security.limit_time_between_posts')) {
if ($this->notEnoughTimeBetweenDiscussion()) {
$minute_copy = (config('chatter.security.time_between_posts') == 1) ? ' minute' : ' minutes';
$chatter_alert = [
'chatter_alert_type' => 'danger',
'chatter_alert' => 'In order to prevent spam, please allow at least '.config('chatter.security.time_between_posts').$minute_copy.' in between submitting content.',
];
return redirect('/'.config('chatter.routes.home'))->with($chatter_alert)->withInput();
}
}
// *** Let's gaurantee that we always have a generic slug *** //
$slug = str_slug($request->title, '-');
$discussion_exists = Models::discussion()->where('slug', '=', $slug)->first();
$incrementer = 1;
$new_slug = $slug;
while (isset($discussion_exists->id)) {
$new_slug = $slug.'-'.$incrementer;
$discussion_exists = Models::discussion()->where('slug', '=', $new_slug)->first();
$incrementer += 1;
}
if ($slug != $new_slug) {
$slug = $new_slug;
}
$new_discussion = [
'title' => $request->title,
'chatter_category_id' => $request->chatter_category_id,
'user_id' => $user_id,
'slug' => $slug,
'color' => $request->color,
];
$category = Models::category()->find($request->chatter_category_id);
if (!isset($category->slug)) {
$category = Models::category()->first();
}
$discussion = Models::discussion()->create($new_discussion);
$new_post = [
'chatter_discussion_id' => $discussion->id,
'user_id' => $user_id,
'body' => $request->body,
];
if (config('chatter.editor') == 'simplemde'):
$new_post['markdown'] = 1;
endif;
// add the user to automatically be notified when new posts are submitted
$discussion->users()->attach($user_id);
$post = Models::post()->create($new_post);
if ($post->id) {
Event::fire(new ChatterAfterNewDiscussion($request));
if (function_exists('chatter_after_new_discussion')) {
chatter_after_new_discussion($request);
}
if($discussion->status === 1) {
$chatter_alert = [
'chatter_alert_type' => 'success',
'chatter_alert' => 'Successfully created a new '.config('chatter.titles.discussion').'.',
];
return redirect('/'.config('chatter.routes.home').'/'.config('chatter.routes.discussion').'/'.$category->slug.'/'.$slug)->with($chatter_alert);
} else {
$chatter_alert = [
'chatter_alert_type' => 'info',
'chatter_alert' => 'You post has been submitted for approval.',
];
return redirect()->back()->with($chatter_alert);
}
} else {
$chatter_alert = [
'chatter_alert_type' => 'danger',
'chatter_alert' => 'Whoops :( There seems to be a problem creating your '.config('chatter.titles.discussion').'.',
];
return redirect('/'.config('chatter.routes.home').'/'.config('chatter.routes.discussion').'/'.$category->slug.'/'.$slug)->with($chatter_alert);
}
}
There's a store function within the vendor package that i'd like to modify/override. I want to be able to modify some of the function or perhaps part of it if needed. Please someone point me in the right direction.
If you mean modify class implementation in your application you can change the way class is resolved:
app()->bind(PackageClass:class, YourCustomClass::class);
and now you can create this custom class like so:
class YourCustomClass extends PackageClass
{
public function packageClassYouWantToChange()
{
// here you can modify behavior
}
}
I would advise you to read more about binding.
Of course a lot depends on how class is created, if it is created using new operator you might need to change multiple classes but if it's injected it should be enough to change this single class.

How to make the field reuired in Yii2 recaptcha google extension himiklab

I am using extension himiklab for yii2 recaptcha, which is similar to the google one. I want to set this field as required field in my rules. When I set it as below it is not validating even If I don't click the checkbox.
[['reCaptcha'], 'required'],
['reCaptcha', \himiklab\yii2\recaptcha\ReCaptchaValidator::className(), 'secret' => '***','skipOnEmpty' => false],
view
<?= $form->field($model, 'reCaptcha')->widget(
\himiklab\yii2\recaptcha\ReCaptcha::className(),
['siteKey' => '6LeY1BAUAAAAALThRhBQ-sJaXbP0Z5i9XFuaz_VW']
)->label(false); ?>
action
public function actionSignup()
{
$browser = new Browser;
if( $browser->getBrowser() == Browser::BROWSER_IE && $browser->getVersion() < 11 )
{
return $this->render('browser');
}
$company = new Company();
$model = new SimUser(['scenario' => SimUser::SCENARIO_REGISTER]);
if ($model->load(Yii::$app->request->post())&& $model->validate() && $company->load(Yii::$app->request->post())&& $company->validate()) {
$model->scenario = SimUser::SCENARIO_REGISTER;
$model->setPassword($model->user_password_hash);
// $model->setCaptcha($model->captcha);
$model->generateAuthKey();
$token = Yii::$app->security->generateRandomString();
$model->user_access_token = $token;
$model->user_verify = 1;
// $company->save();
$model->company_id = 3;
// $model->save();
$model->user_id = 44;
var_dump($model->validate());exit();
if ($model->validate()){
// $auth = Yii::$app->authManager;
// $authorRole = $auth->getRole('Company Admin');
// $auth->assign($authorRole, $model->user_id);
$path = 'C:/wamp/www/test.qsims.com/web/gentelella-1.2.0/production/images/DCMLogo.png';
Yii::$app->mailer->compose('#app/mail/layouts/verify',['model' => $model, 'path' => $path,'token' => $model->user_access_token])
->setTo($model->user_email)
->setFrom('test.qsims#gmail.com')
->setSubject('Welcome to Qsims'.$model->user_fname." ".$model->user_lname.'. Verify your account to continue')
->setTextBody('Verify Account')
->send();
}
// \Yii::$app->user->login($model);
return $this->redirect(['site/verify-new']);
}
return $this->render('signup', [
'model' => $model,
'company' => $company,
]);
}
Where am I going wrong?
Add this to the model
Public $reCaptcha;
add this to rules
['reCaptcha', 'reCaptchaValidator']
call the custom validation
public function reCaptchaValidator($attribute)
{
$validator = new ReCaptchaValidator;
if (!$validator->validate($this->reCaptcha, $error)) {
$this->addError($attribute, $error);
}
}

Resources