I'm trying to insert record into my audit table upon update of record in any other table. For example, if a user update his profile I want to store the old record and the newly updated record in my audit table. For this in my user model I'm trying to use beforeSave() and pass the value to my audit controller
public function beforeSave($insert)
{
if((parent::beforeSave($insert))){
// Place your custom code here
$query = DepCustomer::findOne($this->customer_id);
Yii::$app->runAction('audit-trial/createaudit', ['query' => $query]);
return true;
}
}
And the action code in audit controller for now
public function actionCreateaudit($query)
{
$model = new Audit();
$model->old = '';
foreach($query as $name => $value){
//$temp = $name .': '. $value.', ';
//$contentBefore[] = $temp;
$audit->old = $audit->old.$name .': '. $value. ', ';
}
// I've not yet any other code for now I'm trying to get the old value
$model->save();
}
I'm getting 404 not found error. What do I need to change in my code to make it work? Thank you!
instead of runAction() . If you want to perform operation on another model, prefer to create a static function in that model (in your case Audit model) to save the data
public function beforeSave($insert)
{
if((parent::beforeSave($insert))){
// Place your custom code here
$query = DepCustomer::findOne($this->customer_id);
Audit::saveOldDetails($query);
return true;
}
}
and write saveOldDetails function in Audit Model
public static saveOldDetails($query){
// your business logic here
}
Refer this link
http://www.yiiframework.com/doc-2.0/yii-base-controller.html#runAction()-detail
Related
I have a dynamic form where the user should be able to add or remove fields while editing.
I am able to update the exact number fields that are in the database table. But what I want is if a user clicked a 'Delete Subject' and 'Update' buttons, I want that entire row deleted from the database.
And, if he added a subject by clicking 'Add another Subject' the form and clicked 'Update' I want those subjects added. What am I missing here?
Note: I built a One-to-Many relation between New and Subjects, where a New has many subjects and many subjects belong to a New (It works fine).
My form looks like this
New Model
protected $fillable = ['name', 'address'];
public function subjects() {
return $this->hasMany(Subjects::class, 'new_id');
}
Subjects Model
protected $fillable = ['new_id', 'sub_code', 'sub_name', 'sub_img'];
public function subs(){
return $this->belongsTo(New::class, 'new_id');
}
Create Method
public function create(Request $request, New $new){
$new = New::FindorFail($id)
$subjects= [];
$sub_images = $request->file('sub_img');
$sub_name = $request->sub_name;
for ($i=0; $i < count(request('sub_code')); ++$i)
{
$subjects = new Subjects;
$subjecs->sub_code = request('sub_code')[$i];
$subjects->sub_name = request('sub_name')[$i];
$sub_img_name = uniqid() . '.' . $sub_images[$i]->getClientOriginalExtension();
$sub_images[$i]->move(public_path('/images/'), $sub_img_name);
$subjects->sub_img = '/images/'.$sub_img_name;
$new->subjects()->save($subjects);
}
}
Update Method
public function update(Request $request, $id){
$new=New::FindOrFail($id)
$subjects = Subjects::with(['subs'])->where('new_id', $new->id)->get();
$new->update($request->all());
$i=0;
foreach( $subjects as $new_subjects)
{
$sub_images =request()->file('sub_img');
$sub_name = request('sub_name');
if(isset($sub_images[$i]))
{
$pathToStore = public_path('images');
if($request->hasFile('sub_img') && isset($sub_images[$i]))
{
$sub_img_name = uniqid() . '.' . $sub_images[$i]->getClientOriginalExtension();
$sub_images[$i]->move(public_path('/images/'), $sub_img_name);
$new_subjects->sub_img = '/images/'.$sub_img_name;
$new_subjects->sub_code = request('sub_code')[$i];
$new_subjects->sub_name = request('sub_name')[$i];
$new_subjects->sub_img = "images/{$sub_img_name}";
$i++;
$new->subjects()->save($new_subjects);
}
}
}
}
Subjects Database
I want this table row be updated (added or deleted) after user edit the form.
From my experience with Laravel, I think the problem is that you call the Product model instead of the New model so maybe you need to fix it.
you reference the New model :
public function subs(){
enter code herereturn $this->belongsTo(New::class, 'new_id');
}
then you use the wrong model Product :
$new=Product::FinOrFail($id)
Another thing is to double check the fillable attribute within the Subject model also you can write the update action and do something like
Im trying to get auto increment id after save in Yii2.I tried to the following code block but its not working.
public function actionAddgroup()
{
$model = new Groups();
$model->groupName=Yii::$app->request->post('groupName');
$model->save(); // a new row is inserted into user table
return $model->id;
}
Where you are trying to return the $model->id immediately after creating a new Groups instance, the $model variable may still only have the data you put into it.
To get data added at the database level, you may need to call $model->refresh() in order for it to refresh the data in your local $model variable with the current data from the database.
In other words, try this:
public function actionAddgroup()
{
$model = new Groups();
$model->groupName=Yii::$app->request->post('groupName');
$model->save();
$model->refresh();
return $model->id;
}
public function actionAddgroup()
{
$model = new Groups();
$model->groupName=Yii::$app->request->post('groupName');
$model->save(); // a new row is inserted into user table
return $model->getPrimaryKey();
}
http://www.yiiframework.com/doc-2.0/guide-security-authorization.html#role-based-access-control-rbac
In the documentation, it says that you can assign the role to the user in the advanced template by using this code:
public function signup()
{
if ($this->validate()) {
$user = new User();
$user->username = $this->username;
$user->email = $this->email;
$user->setPassword($this->password);
$user->generateAuthKey();
$user->save(false);
// the following three lines were added:
$auth = Yii::$app->authManager;
$authorRole = $auth->getRole('author');
$auth->assign($authorRole, $user->getId());
return $user;
}
return null;
}
The problem is that I am using the basic template. Is there a way of doing this inside the basic template?
I thought about using the afterSave method; however, I am not sure how to do this.
public function afterSave($insert)
{
}
Any idea on how it can be done?
public function afterSave($insert)
{
$auth = Yii::$app->authManager;
$authorRole = $auth->getRole('author');
$auth->assign($authorRole, $this->Id());
}
I am thinking this could work, but I am not totally sure.
It does not depend on used template.
Your example is correct, except few things.
$this->Id() should be replaced with $this->id (assuming primary key of users table is named id).
Note that you need also call parent implementation of afterSave() method and you missed $changedAttributes parameter:
/**
* #inheritdoc
*/
public function afterSave($insert, $changedAttributes)
{
$auth = Yii::$app->authManager;
$authorRole = $auth->getRole('author');
$auth->assign($authorRole, $this->id);
parent::afterSave($insert, $changedAttributes);
}
For further improvements, you can wrap saving in transaction, so if something is failed in afterSave(), model is not saved (afterSave() event handler is executed after model is saved in database).
Also you can move assigning role logic to separate method.
Note that with this logic every registered user will have that role. You can wrap it with some condition, however it's better to assign role through admin interface.
You can see how it's implemented for example in this extension. For example you can create separate form, action and extend GridView ActionColumn with additional icon for assigning role.
I need to use multiple table in a single form, on form submitted the data will save in multiple tables in the data base, also wants to perform validation and update.
I suggested snippet of code, at beginning of controller class define
private $_rel = null;
controller action ,
public function actionSaveUser(){
if (!empty($_POST['Contact'])){
$model = new Contact;
$model->attributes = $_POST['Contact'];
if ($model->save()){
$this->_rel = new Address;
$this->_rel->attributes = $_POST['Contact'];
if ($this->_rel->save()){
$this->render('view_name');
} else{
throw new CHttpException(404, 'Something went wrong message..');
}
}
}
}
I hope this code help you.
Using MySQL query browser, I manually made a table called users and input some date in the fields. I set the primary key to id and set it to auto increment. There are 3 rows, the highest id is 3.
I then made the following class in the method directory to call upon the data in the table etc.
class Application_Model_DbTable_User extends Zend_Db_Table_Abstract
{
protected $_name = 'user';
public function getLatestUserId()
{
$id = $this->getAdapter()->lastInsertId();
return $id;
}
}
In the controller I do the following which gets the value generated by the method and lets the view access it:
$usersDbModel = new Application_Model_DbTable_User();
$lastUserId = $usersDbModel->getLatestUserId();
$this->view->lastUserId = $lastUserId;
In the view I then echo it to display it to the user:
echo $this->lastUserId;
However, even though my last id in the users table is 3. It displays 0.
I have also tried:
public function getLatestUserId()
{
$sql = 'SELECT max(id) FROM user';
$query = $this->query($sql);
$result = $query->fetchAll();
return $result;
}
But this just throws out a server error.
What have I done wrong?
Am I missing something?
Is there another way of doing this?
The answer was:
$sql = 'SELECT max(id) FROM user';
$query = $this->getAdapter()->query($sql);
$result = $query->fetchAll();
return $result[0]['max(id)'];
If you queried like "SELECT id FROM USERS SORT BY id DESC LIMIT 0,1"
You would get nothing but the id of the newest user, no?
if you use a select statement like
SELECT max(id) FROM USERS;
If you haven't tried having a function in the controller try something like this.
class IndexController extends Zend_Controller_Action {
public function init() {
}
public function indexAction() {
}
public function getLatestUserId()
{
$bootstrap = $this->getInvokeArg('bootstrap');
$resource = $bootstrap->getPluginResource('db');
$db = $resource->getDbAdapter();
$sqlrequest = "select max(id) as Idmax from user";
$rows = $db->fetchAll($sqlrequest);
foreach ($rows as $row)
echo $maxId = $row['Idmax'];
return $maxId;
}
}
and your bootstrap file would look something like
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initConfig()
{
$config = new Zend_Config($this->getOptions());
Zend_Registry::set('config', $config);
return $config;
}
}
Hopefully something like that works, hope it helped
The problem is that Mysql doesn't really support lastInsertId() it will in some cases return the last id of an auto incrementing primary key.
Several solutions have been presented here and most will return the last id of the primary key, which may or may not be what you really need.
This method will also do the same using the select() object.
public function getlastInsertId(){
$select = $this->select();
$select->from($this->_name, "id");
$select->order('id DESC');
$select->limit(0, 1);
$result = $this->fetchAll($select)->current();
return $result->id;
}
I think that over time you may find these kinds of methods unreliable if what you're really after is the last id you inserted. Over time as records are added and deleted the database may or may not fill in vacant id's depending on which database you are currently using and how that database is set up.
In most cases we need the id of the last item inserted very soon after inserting it, usually to update a view script. In this instance I usually just make the whole row object part of the return.
Here is an example of what I mean:
/**this method will save or update a record depending on data present in the array*/
public function saveUser(array $data) {
/**cast data array as std object for convience*/
$dataObject = (object) $data;
/**if id exists as array and has a non null value*/
if (array_key_exists('id', $data) && isset($data['id'])) {
/**find row if updating*/
$row = $this->find($dataObject->id)->current();
} else {
/**create new row*/
$row = $this->createRow();
}
$row->first_name = $dataObject->first_name;
$row->last_name = $dataObject->last_name;
$row->email = $dataObject->email;
/**save or update row*/
$row->save();
/**return the $row you just built or you can return $result = $row->save(); and get*/
/** just the primary key. Save() will throw an exception if table is marked read only*/
return $row;
}