Difference between afterSave and a Event in yii2? - yii2

I wanted to send an email to admin when a new user registers. I think i can do it using two ways. one way is to use events and other is by using afterSave.
By using Events
Controller code
public function actionCreate()
{
$model = new Registeration();
if ($model->load(Yii::$app->request->post()))
{
if($model->save())
{
$model->trigger(Registeration::EVENT_NEW_USER);
}
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
Model code
const EVENT_NEW_USER = 'new-user';
public function init(){
$this->on(self::EVENT_NEW_USER, [$this, 'sendMail']);
}
public function sendMail($event){
// code
}
I can do the same using the afterSave method
Model code
public function afterSave($insert)
{
//code
return parent::afterSave($insert);
}
So is there any difference between the two methods? Which one is better using Events or afterSave() ?

I am new to Yii,
It depends on what you are trying to implement.
When you use afterSave email will be sent on updates also.
So event would be a better choice to your problem.
Thanks & Regards
Paul P Elias

Related

how can i login to yii2 based on md5 encryption?

I have a table with a large number of users whose passwords are stored as md5,
How can I change my login to the site based on md5 encryption?
I want forgiveness for a weak English language!
Take a look here: http://www.yiiframework.com/doc-2.0/guide-security-authentication.html
Here you can find guidelines on how to create user model to support authentication, the methods who actually login/logout such users; all the burden to fetch a user and compare password is up to you based on your data model and controllers flow.
I arrived at the result like the following.
change sitecontroller file and actionlogin to:
public function actionLogin()
{
if (!Yii::$app->user->isGuest) {
return $this->goHome();
}
$model = new LoginForm();
if (yii::$app->request->post())
{
$model->username = $_POST['username'];
$model->password = $_POST['password'];
if($model->login())
{
$this->goBack();
}
}
else
{
return $this->renderPartial('login.tpl', [
'model' => $model,
]);
}
}
and then common/models/LoginForm.php change login method to :
public function login()
{
if ($this->validate()) {
return Yii::$app->user->login($this->getUser(), 0); // remember me changed to 0
}
return false;
}
and in rules method comment rememberme =====>>
// ['rememberMe', 'boolean'],
Explanation: I know this is not the right way, but it's not a problem to carry out your project!
I will suggest following solution
class User extends \yii\db\ActiveRecord implements \yii\web\IdentityInterface {
...........
public function validatePassword($password) {
return $this->password === md5($password);
}
.........
}
You just need to modify the validatePassword() methode as shown above.

(1/1) FatalErrorException Call to a member function all() on null in laravel 5.4

4 and i have a form when submitted i want to validate its fields, what happened is when i submit the form this is what it gets
(1/1) FatalErrorException
Call to a member function all() on null
This is my code below
$validator = app('validator')->make($this->request->all(),[
'postTitle' => 'required',
'postContent' =>'required']);
In laravel 5.2 this validator works well but in laravel 5.4 it returns null
can someone help me figured this thing out?
Any help is muchly appreciated. TIA
this is my full code
<?php
namespace App\Repositories;
use App\Repositories\Contracts\addPostRepositoryInterface;
use Validator;
use Illuminate\Http\Request;
use DB;
use Session;
use Hash;
class addPostRepository implements addPostRepositoryInterface{
protected $request;
// Intialize request instance
public function __contruct(Request $request){
$this->request = $request;
}
public function addPosts(Request $request){
//validate posts
echo "test";
$validator = Validator::make($request->all(), [
'postTitle' => 'required',
'postContent' =>'required',
]);
//if validation fails return error response
if($validator->fails())
return redirect()->route('get.addPost')->withErrors($validator)->withInput();
try{
}catch(\Exception $e){
return redirect()->route('get.addPost')->withErrors(["error"=>"Could not add details! Please try again."])->withInput();
}
}
public function postCreate($screen){
switch($screen){
case 'add':
return $this->addPosts($screen);
break;
}
}
//getAddPost View
public function getAddPost(){
return view('addPost');
}
}
Seems an issue with the method injection (in the constructor) or something.
You may try creating the request object on the local(addPosts()) function.
Please try below alternative solution.
<?php
namespace App\Repositories;
use App\Repositories\Contracts\addPostRepositoryInterface;
use Validator;
use DB;
use Session;
use Hash;
class addPostRepository implements addPostRepositoryInterface{
public function addPosts(Request $request){
//validate posts
$reqeust = new \Illuminate\Http\Request;
$validator = Validator::make($request->all(), [
'postTitle' => 'required',
'postContent' =>'required',
]);
//if validation fails return error response
if($validator->fails())
return redirect()->route('get.addPost')->withErrors($validator)->withInput();
try{
}catch(\Exception $e){
return redirect()->route('get.addPost')->withErrors(["error"=>"Could not add details! Please try again."])->withInput();
}
}
public function postCreate($screen){
switch($screen){
case 'add':
return $this->addPosts($screen);
break;
}
}
//getAddPost View
public function getAddPost(){
return view('addPost');
}
// REST OF THE CODE GOES HERE...
}
Given the information you gave, I will demonstrate you how to validate a request properly in Laravel 5.4
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'postTitle' => 'required',
'postContent' =>'required',
]);
if ($validator->fails()) {
return redirect('your.view')
->withErrors($validator)
->withInput();
}
// Store the blog post...
}
This will successfully validate the request for you wherever need be. If the validation fails, you will be forwarded to your view with the according errors.
Make sure you use Validator; on top of your file.
For more information, you can read up on https://laravel.com/docs/5.4/validation

return afterSave in model yii2

If there is one controller yii2 with one model in which, for example, the outline only:
class MyController class extends Controller {
public function actionCreate() {
$valid = $model->validate();
}
}
Need the return from aftersave, which is a message indicating if the email was able to be sent or not, and all the attributes were inserted.
afterSave in the model:
public function afterSave($insert, $changedAttributes) {
if(!$this->isNewRecord) {
try {
Yii::$app->mailer->compose()
// email composition here
->send();
return 'mail sent';
catch (\Swift_SwiftException $exception) {
return 'email undeliverable'. $exception->getMessage();
}
}
}
Can the return from afterSave be accessed by the controller?
No, you will not be able to access any of those messages, because:
In the controller you are calling $model->validate() and afterSave() will never be called. You would need to call $model->save().
afterSave() is not supposed to return anything, so the value you are returning is lost. See the function definition in the official documentation here
No, it's not gonna trigger the afterSave event with your code. \yii\db\BaseActiveRecord::afterSave is being triggered in 2 places
\yii\db\BaseActiveRecord::updateInternal
\yii\db\ActiveRecord::insertInternal
and if you take a look at \yii\base\Model::validate you'll see that afterSave isn't calling in here.

Yii2 property mapping to tablename

I use Yii2 2.0.9 basic template and I try to set up my class.
I my class I use references of other classes in my property.
/**
*
*#property Contact contact
*/
class User extends ActiveRecord {
public static function tableName() {
return "user";
}
/**
* This is want I need
*/
public function databaseMapping(){
return [
"contact" => "contact_id"
];
}
}
Is there in Yii2 a solution for my problem?
Thanks Marvin Thör
In Grails I can write this:
class User {
Contact contact
Boolean passwordExpired
static mapping = {
contact(column: 'contact_id')
passwordExpired(column: 'password_expired')
}
}
User user = new User();
user.passwordExpired = true
user.contact = new Contact();
and I want the same
You might want to use the method attributeLabels() inside your model class to define label names to show to the end user.
public function attributeLabels() {
return [
'contact_id' => 'Contact',
];
}
However, there are times like when creating a RESTful API using Yii2 that you need to return a json with fields with specific field names. For these ocasions, you can use the fields() method:
public function fields() {
return [
'contact' => 'contact_id',
];
}
This method returns the list of fields that should be returned by default by toArray(). You can check more about it HERE.
Change your labels and db column remain unchanged.
public function attributeLabels()
{
return [
'contact_id' => Yii::t('app', 'Use your name here'),
];
}

create Notification in yii2

I am new to yii. I have created two table, user and notification. The table notification has userid as a foreign key. I want to create notification against user in user model just like I get notification from user model
public function getnotifications()
{
return $this->hasMany(Notification::className(), ['user_id' => 'id']);
}
Use this function in your model.
public function addNotification() {
$notification = new Notification();
$notification->user_id = $this->id;
$notification->message = "Notification";
$notification->save();
}
Apart from the name of your function ( should be getNotifications() not getnotifications() ), I see nothing wrong in your code.
public function getNotifications()
{
return $this->hasMany(Notification::className(), ['user_id' => 'id']);
}
What is the problem now?