I have a PHP script used for AJAX queries, but I want them to be able to operate under the umbrella of Joomla's (2.5) framework so I can have session id's, user id's etc available to me.
For example:
$(function () {
$.ajax({
url: 'ajax.php', //the script to call to get data
dataType: 'json' //data format
...
});
});
Where ajax.php has code such as:
$user =& JFactory::getUser();
From what I understand it's best to make your AJAX/JSON calls to a standard Joomla component. I don't know much about developing a MVC component but from what I can see it is way overkill for what I want to do.
Is there something else I could be using?
if you create a component you can create new view for raw queries for example compoments/com_yourcomponent/views/ajax/view.raw.php and put all logic and output in there
url will be index.php?option=com_yourcomponent&view=ajax&format=raw
or
you can to create new method in controller.php with exit() after print information and url will be index.php?option=com_yourcomponent&task=ajax
This is absolutely possible by way of the Joomla Platform. The example I'll give you below is actually for J1.5, but is easily adaptable to J2.5 with some adjustment to the included files.
Create a joomla platform file to include as shown below:
Include that file in your script
Use the now-available Joomla environment for your functions.
Another strong recommendation is to implement a ReSTful API instead of your custom scripts. It's outrageously simple using Luracast Restler. I had it up and running in about 10 minutes, then added the Joomla Framework as shown below, and had an extremely flexible Joomla based API using AJAX calls for my site in under an hour! Best spent development time in years, as far as I'm concerned.
yourscript.php
require_once('joomla_platform.php');
/* Get some of the available Joomla stuff */
$config = new JConfig();
$db = &JFactory::getDBO();
$user =& JFactory::getUser();
if($user->gid <25) {
die ("YOU CANT BE HERE");
}
echo "<pre>".print_r($config,true)."</pre>";
joomla_platform.php
<?php
/* Initialize Joomla framework */
if (!defined('_JEXEC')) {
define( '_JEXEC', 1 );
// define('JPATH_BASE', dirname(__FILE__) );
define ('JPATH_BASE', "c:\\wamp\\www");
define( 'DS', DIRECTORY_SEPARATOR );
/* Required Files */
require_once ( JPATH_BASE .DS.'includes'.DS.'defines.php' );
require_once ( JPATH_BASE .DS.'includes'.DS.'framework.php' );
/* To use Joomla's Database Class */
require_once ( JPATH_BASE .DS.'libraries'.DS.'joomla'.DS.'factory.php' );
require_once ( JPATH_LIBRARIES.DS.'joomla'.DS.'import.php'); // Joomla library imports.
/* Create the Application */
global $mainframe;
$mainframe =& JFactory::getApplication('site');
}
?>
You don't need to create any custom files and add them into Joomla script. You just need a controller to serve ajax request. You don't even need a view (one way).
Your ajax call should be like these:
$(function () {
$.ajax({
url: 'index.php?option=com_<component_name>&no_html=1task=<controller_name>.<controller_action>', //not_html = 1 is important since joomla always renders it's default layout with menus and everything else, but we want the raw json output
dataType: 'json' //data format
...
});
});
And your controller:
/*
* #file admin/controller/<controller_name>.php
*/
class <component_name>Controller<controller_name> extends JController
{
public function <controller_action>()
{
//do something
$respnse['message'] = 'Your message for the view';
die(json_encode($reponse));
}
}
...
This is just one of the examples of how it's could be done.
Related
I am using Symfony v 2.8, and it uses bundle class functions to process web-page requests.
I've created an include file that I load with a require statement that isolates the code that I use to create several of variables that I use though my web-app, such as the path of my web-app, whether the site is running in the development or production environment, and the URI of the web-site that was navigated from to get to a page in my web-site or between the pages in my web-site. Currently, these variables are local to the function that required the include file, so I have to re-include the file in each function that needs these variables.
My goals are:
Include this file only in the bundle xxxxAction function that is
executed to handle the web-page request.
After being created in the bundle xxxxAction function, have the
variables seen in-scope in all of the functions that the bundle
xxxAction function calls or the functions that they call, without
needing to prefix them as SELF::, like _POST works.
In the functions other than the xxxAction bundle function, I'd
rather not have to use the global statement or the $GLOBALS
associative array.
Have these variables read-only or constants, so that they can't be
modified after set in the include file.
My site has a number of pages, and each has its own bundle Action function, and each of these require the include file.
I already looked at Variable scope at php.net web-site, but unless I missed something, I didn't see how to create Supper-Global read-only variables.
Here is the code that I'm using to create the local variables:
$request = $this->get( 'request_stack' )->getCurrentRequest();
$session = $request->getSession();
$context = $this->container->get( 'router' )->getContext();
$site = $this->get( 'request' )->getSchemeAndHttpHost();
//
// The regular expression checks if the referring web-spage's URL matches one of
// following:
//
// http://mysite.name.com/app.php or
// http://mysite.dev.name.com/app_dev.php or
// https://mysite.name.com/app.php or
// https://mysite.dev.name.com/app_dev.php.
//
$isFromMySite = ( preg_match( '/https?:\/\/mysite.(dev\.)?name.com\/app(_dev)?.php/',
$_SERVER[ 'HTTP_REFERER' ] ) === 1 );
// baseURL: /app{_dev}.php True = Development Environment, False = Production Environment.
$baseURL = $context->getBaseUrl();
$isDev = ( $baseURL == '/app_dev.php' );
$isProd = ( $baseURL == '/app.php' );
Thank you.
Through a Wordpress plugin I have a form that collects user values and compares them against values stored in a Google Sheet.
Setup:
A PHP file for a class has a construct that connects to Google Client and assigns a variable for the class methods to use. These methods get data and compare data. When a user fills out and submits the form, an AJAX call posts the values to a php file where a new instance of this class is initiated and form values are compared against Google Sheet values via class methods.
Issue:
This all works as expected until I involve Wordpress. When I set the ajax url to admin-ajax.php and hook in with wp_ajax_{my_function}/ wp_ajax_nopriv_{my_function} it doesn't work. After some digging, this is the issue I found in the Wordpress debug log:
PHP Fatal error: Uncaught InvalidArgumentException: file "google-api/credentials.json" does not exist in wordpress\wp-content\plugins\myplugin\google-api\php-client-2.4.0\src\Google\Client.php:904
Stack trace:
#0 wordpress\wp-content\plugins\myplugin\my-class.php(37): Google_Client->setAuthConfig('google-api/cred...')
#1 wordpress\wp-content\plugins\myplugin\my-class.php\my-php-file.php(25): MyObject->__construct()
#2wordpress\wp-content\plugins\myplugin\FileContainingMyAjaxHookFunction.php: require_once('my-class.php')
#3 C:\xampp\htdocs\wordpress\wp-includes\class-wp-hook.php(288): MyAddActionsObject->MyAjaxHookFunction('')
#4 wordpress\wp-includes\class-wp-hook.php(312): WP_Hook->apply_filters('', Array)
#5 wordpress\wp-includes\plugin.php(478): WP_Hook->do_action(Array)
#6 C in C:\xampp\htdocs\wordpress\wp-content\plugins\myplugin\google-api\php-client-2.4.0\src\Google\Client.php on line 904
I don't have any issues when I call the php file directly in the url of my AJAX call. This leads me to believe it's the way I'm handling AJAX via Wordpress hooks.
My class looks like this:
require_once 'google-api/php-client-2.4.0/vendor/autoload.php';
class My_Object {
protected static $googleService;
public function __construct() {
$client = new \Google_Client();
$client->setApplicationName ('My Name');
$client->setScopes([\Google_Service_Sheets::SPREADSHEETS]);
$client->setAccessType('offline');
$client->setAuthConfig('google-api/credentials.json');
self::$googleService = new Google_Service_Sheets($client);
}
public static function get_sheet_data() {
$service = self::$googleService;
}
public static function do_stuff() {...}
}
The Ajax:
$.ajax( {
type: "POST",
url: myAjax.ajaxurl,
data: {
action: 'MyAjaxHookFunction',
myDataOne: myDataOne,
myDataTwo: myDataTwo
},
success: function(results) {
$("#MyId").append(results);
jQuery( document.body ).trigger( 'post-load' );
}
});
MyAjaxHookFunction:
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'my-php-file.php';
die();
Note: I tried adding the class instance in MyAjaxHookFunction but that didn't work.
My php file:
require_once ('my-class.php');
$data = new My_Object;
$data::dostuff();
Notes: I'm working locally via XAMPP. The Google PHP API is included in the plugin directory. I'm using PHP as I don't want the data stored in Google Sheets viewable.
Any help or insight appreciated. Thanks.
After a sleep and looking at this again, the solution seemed straitghtforward.
Why there was a problem: AJAX is being executed through admin-ajax.php in the wp-include directory. My class construct refers to a credentials file relative to the location of class file itself. I needed to specify a path that could be used from anywhere in the directory.
To solve I edited the url parameter in $client->setAuthConfig('url') in the class construct:
require_once 'google-api/php-client-2.4.0/vendor/autoload.php';
class My_Object {
protected static $googleService;
public function __construct() {
$client = new \Google_Client();
$client->setApplicationName ('My Name');
$client->setScopes([\Google_Service_Sheets::SPREADSHEETS]);
$client->setAccessType('offline');
$client->setAuthConfig( plugin_dir_path(__FILE__) . 'google-api/credentials.json');
self::$googleService = new Google_Service_Sheets($client);
}
public static function get_sheet_data() {
$service = self::$googleService;
}
public static function do_stuff() {...}
}
Now it works as expected.
What was learned: always use a Wordpress directory path function, like plugin_dir_path(), when specifying paths in plugin files.
If there are any issues with my implementation or better ways of doing things, I look forward to hearing them.
I tried to call the jooomla triggerEvent function for rsform Pro's payment plugin from an external php file.
But I keep getting 500 errors and my server error log didn't cache the error code.
Below is my code and I also added my reference.
Please help me to find out the error source.
Thank you in advance.
define( '_JEXEC', 1 );
define('JPATH_BASE', '../');
require_once ( JPATH_BASE .'/includes/defines.php' );
require_once ( JPATH_BASE .'/includes/framework.php' );
require_once (JPATH_BASE. '/plugins/system/rsfppayment/rsfppayment.php');
jimport('joomla.application.component.controller');
$updatedSubmissionId = 168;
$mainframe = JFactory::getApplication();
$mainframe->triggerEvent('rsfp_afterConfirmPayment', array($updatedSubmissionId));
Its better to make your own function for your plugin then to use a function from another plugin. But I will give a short note on method to call plugins inside your own plugin code(latest for Joomla 3+):
Step 1:
Call JPluginHelper::importPlugin( 'plugingroup' );
plugingroup can be system or plugin folder where rsfppayment plugins are located.
Step 2:
$dispatcher = JEventDispatcher::getInstance();
Step 3:
$results = $dispatcher->trigger( 'rsfp_afterConfirmPayment', array($updatedSubmissionId) );
The below code should do the trick - a 'little' more information can be found on the docs.joomla.org site https://docs.joomla.org/Triggering_content_plugins_in_your_extension.
// Note JDispatcher is deprecated in favour of JEventDispatcher in Joomla 3.x however still works.
JPluginHelper::importPlugin('system');
$dispatcher = JDispatcher::getInstance();
$dispatcher->trigger('rsfp_afterConfirmPayment', array($updatedSubmissionId));
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)
How do I go about integrating Simpletest with Kohana 3? I have checked out this answer but I like to use the autorun.php functionality from SimpleTest.
After some hours of looking over the code, I have discovered how to do it
Create a new copy of index.php, and name it test_index.php
disable the error_reporting line in test_index.php
Create a new copy of bootstrap.php, and name it test_bootstrap.php
comment out the request at the bottom
Ensure that test_index.php includes test_boostrap.php instead of bootstrap.php
Add simpletests to the directory structure
Write the test case - include 'test_index.php' and 'autorun.php' (from simpletests) and code test cases as usual.
My example:
<?php
include_once ("../../test_index.php");
include_once ("../simpletest/autorun.php");
class kohana_init_test extends UnitTestCase
{
function testTrue()
{
$this->assertTrue(true);
}
function testWelcome()
{
$response = Request::factory('main/index')->execute()->response;
$this->assertEqual($response->content, 'testing');
}
}
?>
Some notes: the $response variable depends on if you are using a View or pure text output. If you are using the template controller or a view, then $response is the view which you have used to render the content. Variables in the view are avaliable , as shown above (the variable content is defined inside the view).