how to process stored requests in CI - php

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.

Related

Can I get a PHP object to run code if a method is not found?

I have a master class, DBAPI which contains all the interaction with the database. It's not singleton per se, but is designed to only be instantiated once as $DBAPI.
When I alter the database, I obviously have to add functions to DBAPI to let the site use the new functionality, however, since there are a lot of different actions that can be taken, instead of including everything in a single massive class file, I've split them out by functionality/permission level as traits, and the DBAPI class file is dynamically created by adding traits flagged based off of permission level (read only, read-write etc.). Since the only time the file needs to be created is when new traits are added, I only create the class file if it doesn't exist for that specific user permission level, otherwise I use the already generated file. (If there's a better way to do this I'm all ears).
The issue I'm running into now is that if I add some functions in a new trait, the previously generated classes are obviously not aware of it, and I don't find out about that until I try to use the function in the code somewhere and it fails. It's pointless to write wrappers around every single function call made to check if it is a function first- is there some way to get the DBAPI class to do some action if code attempts to access a method it can't find?
for example, if code calls some function $DBAPI->newfunction() $DBAPI handles the exception itself, running some code that will attempt to update itself, which will cause newfunction() to run if it can be found.
(N. B. This architecture has a really bad code smell. I'm sure there's a better way to do this.)
PHP classes can implement the __call magic method that is used when there is no matching method name.
function __call( $name, $arguments ) {
// Code to run...
}

Selectivley expose functions based on external or internal calls to methods

This question closely resembles what I'm trying to achieve, but as has been indicated in excruciating detail in almost every answer to the question, it is bad-design.
PHP, distinguish between internal and external class method call
Here's what I'm trying to achieve:
Track all actions performed on low-activity configuration tables so that the changes can be propagated to production and QA databases. (configuration tables = Configuration is stored in tables.)
Here's a synopsis of my problem:
All models in Yii extend from the CActiveRecord class which provides some methods to manipulate instances of Models.
Let's break these into 2 categories:
Non-Primitives - Which trigger events like onBeforeDelete, onAfterFind, onAfterSave etc. (ex: https://github.com/yiisoft/yii/blob/1.1.13/framework/db/ar/CActiveRecord.php#L1061)
Primitives - Which directly create and execute commands without triggering events - i.e. act as query generators. (ex: https://github.com/yiisoft/yii/blob/1.1.13/framework/db/ar/CActiveRecord.php#L1684)
Now, these primitives are also public members and thus can be called from outside the class at the users' discretion - And they will modify the table without triggering any events.
These are the solutions I have come up with:
Lay down guidelines for all developers to use Non-primitive methods only.
Encapsulate CActiveRecord in my own model class and expose only non-primitives.
Case 1 will be easier to implement but will be more error prone since at some time some developer might forget the restriction and use a primitive method.
Case 2 will require me to write a lot of code / methods exposing methods I wish to be used. Also, this might cause confusion if both the Yii CActiveRecord and my ActiveRecord class don't have the same interface.
A better solution, in my opinion will be to allow usage of primitives internally while restricting external calls, i.e. using the private/public access specifiers. (This is already contradicted by the reason I provided in case 2, but this is the only solution I can come up with.) Since I cannot use private/public specifiers without encapsulating, and I cannot encapsulate, I'd like to distinguish within the method whether the function is an external call or an internal. debug_backtrace is a viable solution, but I'm here for a more elegant, less hacky solution, or a definitive statement that this cannot be done.
First you should take a step back and think about why there is such a difference in behavior. The methods you call non-primitive are supposed to be called on a model instance:
$ar = new Something();
$ar->update(...);
While the methods you call primitive are supposed to be called on the model itself:
Something::model()->updateByPk(...);
It stands to reason that it doesn't make sense to raise events in the second case because
you are not supposed to work directly with ::model() at all, and
depending on the method, the operation can affect multiple records for which there are no corresponding model instances in PHP
So the quest for a solution should start with you answering these two questions:
In a perfect world, how would you be notified when calling any method on the model? (Obviously the method would need to be primitive for the call to make sense).
In a perfect world, how would you be notified of an operation that affects an unknown (in PHP) number of records?

Calling multiple functions with Zend AMF and one NetConnection?

I have Zend AMF working great in my application, but I'm trying to figure out how to call multiple asynchronous functions with a single connection. For example, let's say I have a service called "MyService" and two functions called "init" and "getData". Can I create a connection, call "MyService.init" THEN "MyService.getData" within the same remote object? If so, how...if not, what is a better solution?
Of course, in this scenario, I can just combine init and getData into one function...but, the problem in the actual scenario is that there are many more methods that will need to run after "init". Thanks!
I have an unanswered question that I asked here I believe for the same reason as yours. I would love to know how to call multiple methods or even better, classes over one connection.
Anyway, in your case where you are talking about methods, with no answer on how to call them from the flex side, I would either make a 3rd method that calls those two, or allow some kind of object or parameter passing for init and let init call getData.
Another thought - maybe you need to consider what is happening in init and whether you really need it or need to call it directly from the client - for example, in order to getData (or put or etc), you always have to have been initialized? So getData should probably check to see if it has been initialized and init if it has not.

How can i handle a form submit using REAL OOP in PHP

Im used to java and creating UML.. and i was wondering how can PHP be OOP, the objects live only until you make a request.. then they destroy, so if im using a database is useless to create a class and add the members (variables) to the class, they will be useless.. i cant pass the main system object from one page to another, or similar so how can PHP be compare to jave? you never do OOP .. i mean REAL OOP.. not creating classes , in fact your index will be a procedural file with some object instance and then ? how about if i make a html form and i want to submit the data.. i have to call a file which is not a class is a php procedural file were i grab the submited data with POST, from that file you will instance a class and do some logic there.. but for me thats not pure OOP.. can somebody point me to the right way of OOP using a form submit example ?
Thanks!
You're labouring under a misapprehension that object oriented programming by definition includes a persistent environment with objects that exist independantly of page requests. I'm afraid it doesn't.
PHP does do "real" object-oriented programming. But PHP's execution environment is like executing a CGI program: upon a page request, the program starts and it ends when the page is finished. Within that paradigm, objects can exist only as long as the page is producing content. Therefore, the first thing the page must do is to load the framework to define and instantiate the required objects, such as a database handler and object mappers that must load and save their data within a page request cycle. Some frameworks will also create objects with the page-request data that your code and objects can then access, sometimes from within objects.
But PHP does not provide this natively because it does not enforce a framework. It is by nature procedural so a framework must be added so as to define and create the desired objects if you don't want to work that way.
There is an advantage to doing things this way. It means a page's code need only concern itself with a single page request. Almost all issues to do with data-sharing and multiply-threaded execution is pushed out to things that can handle it invisibly, like the database and the web server.
Check out any of the latest php framework and how they handle forms. (like ZF or Yii).
b.t.w the "problem" you refer too is client-server architecture and not a minus of PHP.
Each request is a new process with a new MAIN or new Class with static main function which are practically the same.
"so if im using a database is useless
to create a class and add the members
(variables) to the class, they will be
useless"
It sounds like you want an object-relational mapper. There are several popular ones for PHP, as discussed at this previous question.

My logger keeps getting destructed while I am trying to log errors and exceptions

I am just now switching back to PHP after enterprise open-source Java development for three years. Now I am tasked with updating our platform for better logging.
I now understand better how the PHP object lifecycle regarding when objects are garbage collected and have trapped my problem. I am trying to invoke the logger after its already been destructed, when a fatal error occurs. My question is, how do I fix this? How can I stop an object from being destroyed until the end of the request?
Ideally I would like to keep this logger around in memory like I would in Java but is that even possible with PHP? Is there anything shared between two different threads or requests?
With PHP, each request is processed by a different process -- which means you quite cannot keep some object arround between requests (you could serialize it and store it in a file or something like that, and un-serialize it when another requests comes ; but that's not really the way things are generally done)
This means each time your PHP script receives a request, you have to re-instanciate your logger.
Now, if you want to use your logger from several different classes/methods/functions in the same script, you have to know that variables are not global "by default" in PHP : a variable declared outside of a function is not accessible from inside a function, unless you said so using the global keyword.
In this kind of situation, when you want one and only one instance of a specific class (your logger) available from anywhere in your application, people often use the Singleton Design Pattern.
It'll allow to use something like this :
My_Logger_Class::log('blah');
From any portion of your code, and the log method will deal with :
instanciating the class if there was not already one existing instance
the actual logging
And, yes, the first time this method is called for one HTTP request, it'll have to re-open the log file (if logging to a file).
As a sidenote : there are already some existing great logging components, like PEAR::Log or Zend_Log.
Maybe using one of those might help you spend less time re-inventing some wheel ?

Categories