yii2 how to make a notification by e-mail to the user after changing his status - email

yii2 how to make a notification by e-mail to the user after changing his status?? Help me, Please!
Model
class Applicants extends \yii\db\ActiveRecord
{
public $file;
public static function tableName()
{
return 'applicants';
}
public function rules()
{
return [
[['user_id', 'type_passport_id', 'passport_number', 'date', 'expiration_date', 'passport_path', 'diplom_number', 'diplom_path', 'phone_number', 'mobile_number', 'country_id', 'city_id', 'address', 'faculty_id', 'spec_id', 'stage_id', 'training_id', 'dormitories_id'], 'required'],
[['user_id', 'type_passport_id', 'country_id', 'city_id', 'status_id', 'faculty_id', 'spec_id', 'stage_id', 'training_id', 'dormitories_id'], 'integer'],
[['passport_number', 'mobile_number', 'applicants_comment'], 'string', 'max' => 250],
[['expiration_date'], 'string', 'max' => 120],
[['file'], 'file', 'skipOnEmpty' => true, 'extensions' => 'pdf'],
[['passport_path', 'diplom_path', 'address'], 'string', 'max' => 255],
[['diplom_number'], 'string', 'max' => 50],
[['phone_number'], 'string', 'max' => 30],
[['user_id'], 'unique'],
[['user_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['user_id' => 'id']],
];
}
Help me, Please!

You can use afterSave($insert,$changedAttributes) to check for changed attributes and send the email.
According to the DOCS $changedAttributes parameter has old values of attributes that had changed and were saved. You can use this parameter to take action based on the changes made for example send an email when the password had changed or implement audit trail that tracks all the changes. $changedAttributes gives you the old attribute values while the active record ($this) has already the new, updated values.
public function afterSave( $insert , $changedAttributes ) {
if ( !$insert && isset ( $changedAttributes['status'] ) ) {
$this->sendEmail ();
}
return parent::afterSave ( $insert , $changedAttributes );
}
private function sendEmail() {
//your code to email
}

public function afterSave($insert, $changedAttributes){
if (!$insert && array_key_exists('status_id', $changedAttributes) && $this->status_id != $changedAttributes['status_id']){
$this->sendEmail();
}
return parent::afterSave($insert, $changedAttributes);
}
private function sendEmail() {
//your code to email
}
The best way to check is an attribute has changed afterSave(). See Note in this answer

Related

Sendmail Subject in Laravel 5.1

I want send email with subject using variable , this is code
public function sendmail(Request $request)
{
$data = [
'subject' => $request->input('subject'),
'name' => $request->input('name'),
'phone' => $request->input('phone'),
'email' => $request->input('email')
];
Mail::send('mail.sendmail' , $data, function($msg){
$msg->from('mygmail.com', 'Avil');
$msg->to('mygmail#gmail.com', 'Avil')->subject('Welcome to Laravel 5.1');
});
return redirect()->route('contact.index');
}
I wanna subject not "Welcome to Laravel 5.1", Subject is
public function sendmail(Request $request)
{
$data = [
'subject' => $request->input('subject'),
'name' => $request->input('name'),
'phone' => $request->input('phone'),
'email' => $request->input('email')
];
Mail::send('mail.sendmail' , $data, function($msg){
$msg->from('mygmail#gmail.com', 'Hung Nguyen');
$msg->to('mygmail#gmail.com', 'Hung Manh')->subject($data['subject']);
});
return redirect()->route('contact.index');
}
When I running display error :
Undefined variable: data
Please help me. Thank you so much
You have to pass along $data to the callback in your send method. Refer the line where Mail façade is used.
public function sendmail(Request $request)
{
$data = [
'subject' => $request->input('subject'),
'name' => $request->input('name'),
'phone' => $request->input('phone'),
'email' => $request->input('email')
];
Mail::send('mail.sendmail' , function($msg) use($data){
$msg->from('mygmail#gmail.com', 'Hung Nguyen');
$msg->to('mygmail#gmail.com', 'Hung Manh')->subject($data['subject']);
});
return redirect()->route('contact.index');
}

Set unique rule to a field on update action on yii2 rest

I am creating a rest api with yii2 to create and update user information. Below is the rule function in the model class.
public function rules()
{
return [
[['name', 'emailId', 'contactNumber'], 'required'],
[['name', 'emailId', 'contactNumber'], 'string', 'max' => 255]
[['emailId', 'username', 'contactNumber'], 'unique'],
['status', 'default', 'value' => self::STATUS_ACTIVE],
['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]]
];
}
Here I mentioned emailId, username, contactNumber fields should be unique. When I try to create, it is checking whether the field is unique or not. if unique it is throwing the error else it is saving. That is fine.
But when I try to update the value there also it is checking the particular value for the field is unique or not. But it should not be like that. The unique validation should not work on update action. So I updated the rule with 'on'=>'update' as like Yii 1. Check the below function.
public function rules()
{
return [
[['name', 'emailId', 'contactNumber'], 'required'],
[['name', 'emailId', 'contactNumber'], 'string', 'max' => 255]
[['emailId', 'username', 'contactNumber'], 'unique', 'on'=>'update'],
['status', 'default', 'value' => self::STATUS_ACTIVE],
['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]]
];
}
But when i check the official documentation there is no option like on to check the particular action. When i use 'on'=>'update', both(while creating and update) places it is not validating. Might be because of the on. Just leave that. I need to add unique validation for those fields in create action only not in update action.
So, Please anybody help me with how to add unique validation to those fields only in create action.
Thanks.
You can set scenario for your REST actions in your ActiveController:
public function actions()
{
$actions = parent::actions();
$actions['update']['scenario'] = 'update';
$actions['create']['scenario'] = 'create';
return $actions;
}
And then use it in rules:
[['emailId', 'username', 'contactNumber'], 'unique', 'on'=>'create']
Also you must specify list of active attributes for each scenario in the particular model class:
public function scenarios()
{
$scenarios = parent::scenarios();
$scenarios['update'] = ['type', 'title', 'description'];
$scenarios['create'] = ['type', 'title', 'description', 'affiliate_id'];
return $scenarios;
}

WooCommerce - Add a new field to the checkout and order email

Hi I am trying to add a shiiping email field to my checkout page and I want to have it shown on the order email as well.
After having looked around I finally came up with this code that I put in the functions.php: everything worked (I have the new field in the checkout page and I have it in the administrative panel of the orders). Still it doesn't appear on the notification email. What I did wrong?
Here below is my code
// Hook in the checkout page
add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );
// Our hooked in function - $fields is passed via the filter!
function custom_override_checkout_fields( $fields ) {
$fields['shipping']['shipping_email'] = array(
'label' => __('Email', 'woocommerce'),
'placeholder' => _x('Email', 'placeholder', 'woocommerce'),
'required' => false,
'class' => array('form-row-wide'),
'clear' => true
);
return $fields;
}
/* Save Field in the DB as Order Meta Data*/
add_action('woocommerce_checkout_update_order_meta','my_custom_checkout_field_update_order_meta');
function my_custom_checkout_field_update_order_meta($order_id) {
if (!empty($_POST['shipping']['shipping_email'])) {
update_post_meta($order_id, 'Shipping email', esc_attr($_POST['shipping'] ['shipping_email']));
}
}
/* display it in the Order details screen*/
add_action('woocommerce_admin_order_data_after_billing_address', 'my_custom_billing_fields_display_admin_order_meta', 10, 1);
function my_custom_billing_fields_display_admin_order_meta($order) {
echo '
' . __('Shipping email') . ':
' . get_post_meta($order->id, '_shipping_email', true) . '
';
}
/**Add the field to order emails **/
add_filter('woocommerce_email_order_meta_keys', 'my_woocommerce_email_order_meta_keys');
function my_woocommerce_email_order_meta_keys( $keys ) {
$keys[] = 'Shipping email';
return $keys;
}
A small change is required to my_woocommerce_email_order_meta_keys function, following code will work
function my_woocommerce_email_order_meta_keys( $keys ) {
$keys['Shipping email'] = '_shipping_email';
return $keys;
}

Cake PHP custom validation rule

I got a problem with a custom validation rule in Cake 2.X
I want to check if the entered zipcode is valid and therefore a function in the class zipcode is called from the class post.
But the validation returns false all the time.
Appmodel in class post (rule-3 is it):
'DELIVERYAREA' => array(
'rule-1' => array(
'rule' => array('between', 5, 5),
'message' => 'Bitte eine fünfstellige Postleitzahl eingeben'
),
'rule-2' => array(
'rule' => 'Numeric',
'message' => 'Bitte nur Zahlen eingeben'
),
'rule-3' => array(
'exists' => array(
'rule' => 'ZipExists',
'message' => 'Postleitzahl existiert nicht!'
)
)
),
Appmodel in class zipcode:
class Zipcode extends AppModel {
var $name = 'Zipcode';
var $validate = array(
'zipcode' => array(
'length' => array(
'rule' => array('maxLength', 5),
'message' => 'Bitte einen Text eingeben'
),
'exists' => array(
'rule' => array('ZipExists'),
'message' => 'Postleitzahl existiert nicht!'
)
)
);
function ZipExists($zipcode){
$valid = $this->find('count', array('conditions'=> array('Zipcode.zipcode' =>$zipcode)));
if ($valid >= 1){
return true;
}
else{
return false;
}
}
I hope it´s something stupidly easy?
Thanks in advance
I think this:
'Zipcode.zipcode' =>$zipcode
...needs to be this:
'Zipcode.zipcode' =>$zipcode['zipcode']
Careful what you expect inside the validation rule. Use debug() etc to find out what exactly is coming in. $data is always an array here.
public function zipExists($data) {
$zipcode = array_shift($data); // use the value of the key/value pair
$code = $this->find('first', array('conditions'=> array('Zipcode.zipcode' =>$zipcode)));
return !empty($code);
}
try this for only model validation.
function ZipExists(){
$valid = $this->find('count', array('conditions'=> array('Zipcode.zipcode' =>$this->data['Zipcode']['zipcode'])));
if ($valid >= 1){
return true;
}
else{
return false;
}
I found the solution.
Cake wants the custom validation rules to be in the certain class where the rule is called. So, when you call a custom rule in class post, the custom function has to be written down in class post, otherwise cake won´t find it and validate it to false everytime.
The magic to do here is to import the appmodel-class you want to use in the class you call the validation-function. That works with the following statement:
$Zipcode = ClassRegistry::init('Class to use - in my case "Zipcode"');
But if your tables are associated with each other with hasAny or belongsTo and stuff, the custom function works without that. Another important point you mustn´t miss is, that all validation functions has to be introduced with "public function xyz" otherwise cake won´t find them too.

Symfony2 entity field type alternatives to "property" or "__toString()"?

Using Symfony2 entity field type one should specify property option:
$builder->add('customers', 'entity', array(
'multiple' => true,
'class' => 'AcmeHelloBundle:Customer',
'property' => 'first',
));
But sometimes this is not sufficient: think about two customers with the same name, so display the email (unique) would be mandatory.
Another possibility is to implement __toString() into the model:
class Customer
{
public $first, $last, $email;
public function __toString()
{
return sprintf('%s %s (%s)', $this->first, $this->last, $this->email);
}
}
The disadvances of the latter is that you are forced to display the entity the same way in all your forms.
Is there any other way to make this more flexible? I mean something like a callback function:
$builder->add('customers', 'entity', array(
'multiple' => true,
'class' => 'AcmeHelloBundle:Customer',
'property' => function($data) {
return sprintf('%s %s (%s)', $data->first, $data->last, $data->email);
},
));
I found this really helpful, and I wound a really easy way to do this with your code so here is the solution
$builder->add('customers', 'entity', array(
'multiple' => true,
'class' => 'AcmeHelloBundle:Customer',
'property' => 'label',
));
And in the class Customer (the Entity)
public function getLabel()
{
return $this->lastname .', '. $this->firstname .' ('. $this->email .')';
}
eh voila :D the property get its String from the Entity not the Database.
Passing a closure does not work yet, but will be added to Symfony soon: https://github.com/symfony/symfony/issues/4067
It seems this can be achievable by adding following block after elseif ($this->labelPath) block in ObjectChoiceList.php.
elseif (is_callable($this->labelPath)) {
$labels[$i] = call_user_func($this->labelPath, $choice);
}
Haven't tried it though :).