Call additional method on DB::update or DB::delete (laravel, eloquent) - php

I'm in the process of trying to create a logging interface for our application. I need to track when a change happens in the database through the application. So when someone updates a field I need to insert a row into the log with the table, columns original value, columns new value, timestamp, and user that made change. To me the logical way of doing this is to tie into the DB class in laravel so everytime it's called and an update / delete method is used it runs my new method of getting the needed info and inserting it in the log.
I need it to work at the DB level I believe as it needs to happen for updates / deletes called from DB or eloquent.
How would I go about doing this?

Eloquent provides you with some nice events, they're even in the docs ! Who knew you can find so much in there.
http://laravel.com/docs/eloquent#model-events

Instead of trying to attach something onto the DB layer, have you considered using Model Observers (http://laravel.com/docs/eloquent#model-observers) to watch all update and delete events and put your logic in that observer?

Upon searching and trial and error I accomplished my goal the following way.
I created an Event listener that I for organizational purposes placed in /app/events/database.php
With the following
<?php
Event::listen('illuminate.query', function($query, $bindings, $time, $name)
{
// Code to log query goes here
});
I then placed in my /app/start/global.php the following line
include(app_path().'/events/database.php');
This now captures all requests to query the database using either DB, or Eloquent.

Related

Phalcon model saves everything except new added attributes

I received an update of a Phalcon model class and I had to update my local data table with the new attributes the model contains. Usually this kind of operation is not a problem, I simply launch an alter SQL query on the to add the columns, assign values to the object, call save and that's it.
However this time something strange happened: when I call save() on the model, everything is updated/created except the two new attributes I've added in my table. I checked the logs to take a look at the raw SQL query and the two new attributes are missing, the funny thing is that this operation worked the first times I tested it.
I think this error might come from the framework, after debugging my code I see clearly that the model takes the new values but for some reason cannot pass it to the SQL query.
Thus my question is the following: is there a way to force the Phalcon model to be sync again with my table?

Is it ever right to call a PHP MVC model from a different model?

I am currently adding a notification feature to a website and need it to update it's data whenever a user is added to a table. The way I think is correct is to go through each of my controllers and whenever a call to the model is made that will change that table, I will follow that up with a second function call updateNotificationTable() or something like that.
The site is quite large however, and while I can make sure to follow all of these controller calls with an update function, I can easily see this being missed for any future changes that interact with the table.
It seems the most fool proof way to do this would be to include a function inside the model itself so that once it inserts or deletes a row from the table it would update the notifications there. The problem is that the notification process pulls data from a separate second model I would have to load up inside the starting model.
I don't believe it's supposed to work that way but the alternative would present problems too. In this instance would it be right to load another model inside my model to process the notification update?
edit: sample code
function addToTable(){
//There's probably a dozen or more functions like this scattered throughout various controllers, they all need to be followed by updateNotifications()
$this->other_model->Insert_stuff();
$this->updateNotifications();
}
function updateNotifications(){
$var1 = $this->model1->get_important_info();
$var2 = $this->model2->get_more();
$this->Notifications_Model->doTheUpdate($var1,$var2);
}
If I could instead take doTheUpdate() and have it directly call model1 and model2 to get it's required data then any future function that need to call $this->other_model->Insert_stuff(); will not need a follow up updateNotifications() call. If another programmer is working on it chances are good it won't happen.
There's probably a dozen or so controllers that I add this function to and call after various functions are executed. If Notifications_Model could directly call model1 and model2 then doTheUpdate

Force doctrine to always refresh

I've got a script that fetches data from a database using doctrine. Sometimes it needs to fetch the data for the same entity, the second time however it uses the identity map and therefor might go out of sync with the database (another process can modify the entities in the db). One solution that we tried was to set the query hint Query::HINT_REFRESH before we run the DQL query. We however would like to use it also with simple findBy(..) calls but that doesn't seem to work? We would also like to be able to set it globally per process so that all the doctrine SELECT queries that are run in that context would actually fetch the entities from the DB. We tried to set the $em->getConfiguration()->setDefaultQueryHint(Query::HINT_REFRESH, true); but again that doesn't seem to work?
Doctrine explicitly warns you that it is not meant to be used without a cache.
However if want to ignore this, then Cerad's comment (also mentioned in in this answer) sound right. If you want to do it on every query though you might look into hooking into a doctrine event, unfortunately there is no event for preLoad, only postLoad, but if you really don't care about performance you could create a postLoad listener which first gets the class and id of the loaded entity, calls clear on the entity manager and finally reloads it. Sounds very wrong to me though, I wash my hands of it :-)

Attach user ID to save/update/create in a clean way in Laravel 5.1

So I have a lot of controllers that will be created by one user. So on every save/create/update I want the user's ID to be saved the resource's user_id column in the database.
I know that before the actual database update I could go like
$resource->user_id = Auth::user()->id;
but this seems pretty unclean and I don't wanna do this for all the create/update actions I have spread across multiple controllers.
What would be the best and cleanest way to approach this issue?
If you are using Eloquent ORM to define $resource you can define Events for that model, that will be executed (if you wish) after or before every create, update, save, delete or restore action on that model. You can see the documentation here: Laravel 5.1 Model Events Documentation
Create a trait that hooks into the model’s saving event, and set the user ID there.

DB Transaction in Controllers

I have created a crud system. Here I have a main model and then dependent details model. So their are multiple rows (some times > 100 ) entered into details model related to parent model. All operations handled through grid ( inline edit ). So create, update, delete operations are performed through single request (logical checking via DB).
Now I am considering to use DB transaction to whole operations. But I am confused, how I can implement this using same structure. I already have suggestions to move my all code to one model, So transaction can be applied there. But I am thinking, if any other approach can be used for retain separation of main and details model code.
Are you using AJAX for the changes or does it rely on manual form submissions?
You can use what's called a UnitOfWork pattern.
Save any changes that the user makes to each line of the grid but don't actually commit them to the DB. Then, place a geneic save button on the page that will cause your server to actually commit all the changes through a transaction.
You can keep a list server side of each row that the user changes. You don't need to track all the rows because if they don't change anything you don't need to save anything.
What sort of approach are you using in your Models? Do your models know about their own persistence (do you do things like $user->save()), or are you doing a more data-mapper approach ($userManager->save($userEntity))? The latter makes transaction handling a lot easier.
If you're doing the active-record type of patter ($user->save()), your best bet is probably just to manually grab your db connection and manage the transaction in your controller.
If you're doing data-mapper stuff, you have more options, up to and including doing a whole unit-of-work implementation.
As for my last comment, Moving code to parent model is my solution for now. So I think I should mark this thread answered.

Categories