doctrine: call symfony method based on Entity DateTime age - php

I'm new to Symfony and Doctrine.
I got a project where I need a method inside a Symfony service to be called with data from the DB whenever a dateTime object saved in that DB table "expires" (reaches a certain (dynamic) age).
As I'm just starting out I do not have any code yet. What I need is a start point to get me looking in the right direction as neither the life cycle callbacks nor the doctrine event listener / dispatcher structure seems to be able to solve this task.
Am I missing something important here or is it maybe just a totally wrong start to my problem which actually can't be solved by doctrine itself?
What came to my mind is a cron-job'ish structure, but that kind of implementation is not as dynamic as required but bound to specific time frames which may be not reactive enough and maybe even immensly decreases the performance in different situations.

If I'm getting your problem right: You want something that executes when a record's datetime expires.
The main problem is that you would have to call PHP based on a DB event which is not straight forward...
One possible solution can be a Symfony command that's executed periodically(using cron) and you select the expired entities and do the required actions.

So as far as I found out doctrine is really not able to do this task in the descriped way. Of course the DB can't react to a part of a record it saved without an external action triggering the lookup.
So what I will propably go with is a shell programm called at.
It actually is something like I (and katon.abel) mentioned. It is able to enter one time crons which are then executed according to the provided time (that I then do not need to save in the DB but just pass it to at).
This way I can easily create the crons via symfony, save the needed data via doctrine and call the callback method via a script triggered by at.

Related

Symfony - Checking something without method execution

In my Symfony project I have and idea to check for my entity field "created". When the creation date of that date is more into the past than two weeks I want to update that entity with some data.
As this is new functionality for me, I was planing to write a function that with DateTime object that will check that.
Other thing I wanted to ask is, how to do it without firing that specific method? Can it be checked regularly on page load or something like that?
What is the right approach here?
Is it an Event Listener the right thing or am I missing something else?
I would suggest to use Symfony console commands / cronjobs.
You could schedule the command/cronjob to run once every day (or when you need it to).
In your console command you you could get all the articles that have a creation date and are older than your specified date. Use Doctrine Query Language (DQL) for this. I don't think you will need DateTime object for this. You can do it all in DQL
(Optional) If needed, you could dispatch an Event after an entity is updated (or put to expired), and build Listeners to do something extra.

What object i should have in command?

I writing system following hexagonal architecture.
I have asynchronous commands and synch query objects split in UseCase.
My src folder look like:
-src
--Entity
---Task.php
--UseCase
---Command
----CreateTask
-----CreateTaskUseCase.php
-----CreateTaskCommand.php
My Question is: What i can/should use to send data via Command in constructor of UseCase\Command\CreateTask\CreateTaskCommand
\Entity\Task
create UseCase\Command\CreateTask\Request\Task that would have all needed data
only string/int/float
This is trivial example to show problem.
Right now i'm using object from Domain (Entiti\Task etc)
In real situation, i have UseCase\Command\CreateProcess that need
Uuid
Instance[id, name]
Source[node_id, node_name, leaf_id, leaf_name]
Resource[id,name,type etc. normal types Person[name,lastname]]
By following DDD, Process is my aggregate. All entities exists only due construct Process(Node,Leaf,Resource,Person). Then i don't want separate way, to create the others entities, because that way works my business logic.
Due that problem, question is: what should i to choose? Breaking some rules?
Problems:
bind command with Object from inside Domain, will bind higher layer more to core. Any change in core, will chain react with all layers
Creating Request\* make me alot of classes, but clear way of use command, and much more work - unitTest etc.
Using only standard type(int,string etc.) will make __counstruct with 20 arguments. I don't want multilevel array, as will no be clear of use this command.
Thanks for help.
After some time, and experience - Best option is to use standard data from PHP. Eventually, it is good to create objects for that Command (second option), but this will consume time to create classes and tests.
Never use something from domain - this is huge drawback in future.

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 :-)

Create Project Log(History) Module in symfony with event dispatchers

I'm developing a project management tool in Symfony, right now I'm creating a module to recording the logs i.e, to capture every event like New project create, task create, task status changes, deletion of projects and task, etc.
I have a log table where I have planned to insert new rows whenever any of the above event occurs. But for doing this, I need to go into each controller and call the log model to execute the insert query. Its almost like I'm going to work on all the actions in the controller again for appending this code. is there any other way to call the model only once using some event dispatcher like class in Symfony.
Glad your are using Propel, there is a bunch of plugins and/or behavior for tracking what happend to your object. I will give you a list of what I've found:
pmPropelObjectLogBehaviorPlugin: Maintains a class changelog (the changes of each instance).
AuditableBehavior: Add ability to log activity for propel objects
propel-listener-behavior: Makes you attach listeners to propel generated objects that inform you about updates on those.
ncPropelChangeLogBehaviorPlugin: a Behavior for Propel objects that allows you to track any changes made to them.
JMSAOPBundle does exactly that.
If I may suggest, I think it's better to add custom events for each action, with this way you can extend your app with more listener without losing control. If you use doctrine you can also work with doctrine event system

how to process stored requests in CI

I have been using a controller method post directly to perform some db and social network operations but im finding a few points of failure between it and the hardware — so I came up with the idea of storing all the request in a db table to be used as a queuing system instead so I can process them in my own time rather than real time
The thing I'm struggling with now is handling my requests . I know this isn't very MVC — but its quick fix.
How do I call another controller's method from within my process queue method? I have tried including the file and instantiating it — then passing it the variables i would have done from the web.
function process(){
$result = $this->mque->get_all();
include('post.php');
$get = new post();
foreach($result->result_array() as $item){
$get->index($item['rfid'],$item['station_id'],$item['item']);
}
}
but i get an error- when i call the normal index method- it runs fine but i get an undefined method error when call it through the instantiated class method- (this is my problem)
Message: Undefined property: post::$db
The why
I am setting the process queue method to run based on a cron job running at a set interval of time.
Originally everything ran to index method of post — but since post::index() can take 10-15 seconds to run and the reader is not multi threaded — someone could use the reader within 7 seconds and the script wouldn't have run completely.
Is there a better way of doing this rather than using my current process method?
update
there is two ways to do this- either use php to fopen/get from the web
or do it sprogramming using $class->method()- i would prefer to do this the first method but dont really see any option with the error i mentioned before
That's easy: you don't have one controller call another. As a rule, if you need something to exist in two different places, you have two options:
Have them both subclass the same object
pro: That way the method is already there
con: You can only subclass one thing, and you have to build your own class loading system (NOT GOOD)
Have a library (or model) which they both share
pro: The method can then be tested better (it is (or it was at one point) easier to unit test models than it is to test controllers), the code can be shared without a custom class-loading syntax.
con: This may involve a little refactoring (but it should be as easy as moving the code from the controller's method to a library's method and then simply calling the library in the public controller method).
Either one of those would solve your particular problem. Personally, because of how CI loads controllers, my preference is to create libraries.
CodeIgniter: Load controller within controller
Is this something that could help you out quickly? Check the bottom reply.

Categories