I'm working on converting my standard PHP project to OOP but I ran into a wall about how to handle AJAX calls with PHP Classes. I'm not happy with the way I'm doing this now. I have a TillAjax.php file which I call from my TillUI.php file from a AJAX call.
In the TillAjax.php file I do this to get the information passed from the ajax call.
$till = new Till();
if(isset($_POST['data']))
$till->doStuff($_POST['data']);
I think this ruins the OOP.
I have worked with ASP.NET MVC and here its possible to call a specific action in a controller without i have to check for the post value. So I want to know if there is a smarter PHP way to solve the above problem?
The method I use for this is to have an Ajax class.
Your php file calls Ajax::Process($_GET['handle']), where 'handle' contains the name of a static class method, so perhaps 'Till::Process'. The Ajax class checks the function against a list of permitted functions (i.e. functions that you are allowing to be called via ajax), and then uses call_user_func_array to call the function (my code uses the contents of $_POST as arguments to pass to the function). The return of that function is automatically encoded as json and outputted to the client.
This means that your target php file looks like this:
<?php
//File: ajax.php
include ("Ajax.php");
Ajax::Process($_GET['handle']);
?>
Which I think is pretty simple.
Then you can have javascript that looks like this (jquery) :
$.get('ajax.php?handle=Till::Process', {}, function(result) {
//called on page response
});
So then result now contains whatever data is returned from the php method Till::Process.
Have you considered using a PHP MVC framework such as CodeIgniter, CakePHP, Kohana, etc? They will let you route requests to specific controller methods. It will be a much cleaner solution if migrating to one of these frameworks is an option for you.
Related
I have a PHP-class handling authorization and requests to an API and I would like to use those functions in Angular. When the PHP is loaded I create a controller which initializes a variable which should contain the response from the API. I think it should look something like this:
$scope.jsonData = <?php echo json_encode(PHPClass::getData("Argument")); ?>;
Is there any way to do this and use the PHP-class and refrain from using $http?
I realize I've been going about this the wrong way. I'll instead start looking into it properly authorizing the requests through angularjs.
I'm taking an application I wrote, a form, and rewriting it in Silex. It was, for various reasons, written like:
page1.php
page1_process.php
page2.php
page2_process.php
page3.php
page3_process.php
Where pageX.php is an HTML form with little PHP code, that passes data to the process script. The process script stores data to a Form object, and serializes the object in the Session.
Currently, I have the pageX.php pages as TWIG template files and they work, but I don't know how to incorporate the logic of the procedural process scripts.
I'm sure I don't copy the actual logic to the controllers.
If I follow your requirements, you just need the same route twice: one for get (displaying the form) and one for post to handle it. In the post controller you just need to include your pageX_process.php and you should be ready to go.
Translated in Silex code it should be something like:
<?php
/**
* if you're using silex-skeleton
* from: https://packagist.org/packages/fabpot/silex-skeleton)
* this file should be src/controllers
*/
// standard setup, like error handling and other route declarations
$app->get('/page1', function() use ($app) {
// you're currently using this (somehow)
$params = []; //set up your template parameters here
return $app['twig']->render('page1.twig', $params);
});
$app->post('/page1_proccess', function() use($app) {
ob_start();
require PATH_TO_LEGACY_FILES_DIR . '/page1_process.php';
return ob_get_clean();
});
From now on, and if you want / find it adequate, you can start to refactor your pageX_process.php pages in a more OOP / Silex way, but you have a starting point with this application architecture.
NOTICE:
you should move your php files away from the web directory (for example legacy/ in the root of your project)
you must point your form handling script (the action parameter) to the new route (you can make it to work using the old route also but requires some little more effort)
I'm completely new to jQuery and Ajax, but I've managed to learn how to do the Hello World, populate a select tag, etc, etc...
Problem is, I don't like to use structural PHP. The way I learned I have to call some PHP file with $.getJSON and that file has to "echo" my result.
What I want is to be able to call a PHP file that is actually a class with some methods and the return of the method would be what JavaScript would receive instead of just an echo result.
Thanks for your attention.
Ps.: I have a lot of experience with PHP-OOP and Flex+PHP using Amfphp. I'm trying to build a different version of view and I would like to re-use the classes that Flex already use.
jQuery runs on your computer, and PHP runs on the server. PHP and jQuery can only communicate via a series of well-crafted strings. On the server, you are free to create objects, run methods, manipulate output, and anything else. However, if you're going to be feeding that data back into your jQuery application (still running on the client's machine), you'll need to echo (or output) the results of your PHP script.
You may consider something like this:
$.post('server.php', { 'class':'foo', 'method':'bar' }, function( response ) {
/* do something with the output of $foo->bar(); */
});
As you can see here, I can define the class and method I'd like to have called on the server. From server.php, we would look to $_POST['class'] and $_POST['method'] to determine what we will instantiate, and which methods we will run.
The AMF is somehow different from HTTP, they're different protocols.
When using AJAX (jQuery or not), you're calling HTTP methods on URIs, not OOP methods. So everything ends up in a minimum of two mappings:
Your application logic mapped to methods and URIs.
Your Javascript code mapped to methods and URIs.
Here is a sample using Respect\Rest:
$router->get('/users/*', function($userName) {
return MyDatabaseLayer::fetchUser($userName); //Illustrative
})->accept(
'application/json' => function($data) {
header('Content-type: application/json');
return json_encode($data);
}
);
Now the jQuery part:
$.getJSON('/users/alganet', function(user) {
alert(user.name);
});
You should use appropriate HTTP methods for different actions. Saving an user would be something like:
$router->post('/users/*', function($userName) {
return MyDatabaseLayer::saveUser($_POST['user']); //Illustrative
});
jQuery:
$.post('/users', $("$userform").serialize());
There are four main HTTP methods: GET, POST, PUT and DELETE. GET and POST are the most common ones.
There is a nice trivia: Both HTTP, REST and AMF were written by the same guy: Roy Fielding.
I need to run a php script once before my zend framework application is bootstrapped and run. This works now by calling this initial script in my /public/index.php, however the script is run for all subsequent zend framework page requests as well. I need this script to only be run once on the initial request and not again when additional pages are loaded via ajax.
My initial attempts were to set some php constants in the /public/index.php file like so:
if (!defined('SOME_VAR')) require_once 'path/to/script/to/run/once.php';
define('SOME_VAR', '1);
However, when another page is loaded via ajax, even though I've defined 'SOME_VAR', it doesn't persist and stay as defined and the script is executed again.
I'm using Zend Framework 1.11, Apache (Xampp).
Executing this script AFTER Zend has been bootstrapped and run (inside Zend Framework) is not an option.
Constants don't work because they only exist for the duration of the request.
It sounds like you want to figure out if the current request is a regular request or an XmlHttpRequest (AJAX) request.
You could try something like this at the top of your index.php:
<?php
define('IS_AJAX_REQUEST', isset($_SERVER['HTTP_X_REQUESTED_WITH'])
&& strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest');
if (! IS_AJAX_REQUEST){
// run your code.
}
If you're using sessions, you could also just set a flag in the session once you special code has been run, and test for that.
According to the Zend Framework Documentation:
However, should custom initialization be necessary, you have two choices. First, you can write methods prefixed with _init to specify discrete code to bootstrap. These methods will be called by bootstrap(), and can also be called as if they were public methods: bootstrap(). They should accept an optional array of options.
If your resource method returns a value, it will be stored in a container in the bootstrap. This can be useful when different resources need to interact (such as one resource injecting itself into another). The method getResource() can then be used to retrieve those values.
The other option is to use resource plugins. Resource plugins are objects that perform specific initializations, and may be specified:
When instantiating the Zend_Application object
During initialization of the bootstrap object
By explicitly enabling them via method calls to the bootstrap object
Resource plugins implement Zend_Application_Resource_ResourceAbstract, which defines simply that they allow injection of the caller and options, and that they have an init() method.
I'm going to write a booking website using php and ajax and I really can't figure how to mix these two tools with a strict object oriented design.
I was used to make a call using ajax to a php web page that returns the right set of values (string, xml, json) in a procedural way.
With object oriented programming how is it supposed to work?
The simplest solution that i can think is to call through ajax a php page that should only instantiate a new object of the right class and then make an echo on the result of a simple call with the data received but this doesn't look very oo...
For example to implement the register function I should make an ajax call to a register.php web page that, in turn, will instantiate a new Registration object r and then simply calls r.register() with the right data.
Is there a better solution to this problem?
I want specify that I can't use any php framework because it's a didactic project and I have this rule that I should respect.
Another specification: I've read a lot of tutorials that describe how to write your own mvc framework but doing this seems to be an overkill for my problem.
Thank you for your help, every idea will be appreciated.
As you already said you don't really need a PHP framework and don't need to build your own MVC implementation
(especially if you are e.g. working with JSON or XML).
Basically you are pretty free on how to do your OO model, so your idea is not necessarily wrong.
Some OO anti patterns I have seen people using in PHP:
Use global variables in classes
Create classes without member
variables resulting in method calls
being the same as in a produral style
Directly accessing $_GET, $_POST etc.
in a class
Echoing html output (imho this should
be done in view templates)
An example for what you might want to do for the registering process processing some $_POST variables
and returning a JSON success message:
<?php
class Registration
{
private $_data;
public function __construct($registrationdata)
{
$this->_data = $registrationdata;
}
public function validate()
{
// ...
}
public function register()
{
// ...
if($this->validate())
return array("registered" => true, "username" => $this->_data["username"],
"message" => "Thank you for registering");
else
return array("registered" => false, "username" => $this->_data["username"],
"message" => "Duplicate username");
}
}
$reg = new Registration($_POST);
echo json_encode($reg->register());
?>
There is no reason to create any classes if all you are doing is calling a couple of unrelated stateless php functions.