I want to create a backend in Wordpress for my Parse app which displays information from the app using the Parse PHP SDK.
The SDK is included and I am using the autoloader.php to load it but I keep getting the following error:
Fatal error: Class 'Parse\ParseClient' not found in http://site
I have ensured that my file path is correct.
Any suggestions.
Thanks!
define( 'PARSE_SDK_DIR', bloginfo( 'template_url' ) . '/parse/' );
// include Parse SDK autoloader
require_once('autoload.php' );
// Add the "use" declarations where you'll be using the classes
use Parse\ParseClient;
use Parse\ParseObject;
use Parse\ParseQuery;
use Parse\ParseACL;
use Parse\ParsePush;
use Parse\ParseUser;
use Parse\ParseInstallation;
use Parse\ParseException;
use Parse\ParseAnalytics;
use Parse\ParseFile;
use Parse\ParseCloud;
ParseClient::initialize('wOI4ED7sqFMI9TN9bBbwVc9WGEePcUuq15V04liY', 'lfcUvPmvT6ayZFZflLWf7rZBgbZKICuS3ppwYIxo', 'NBHXiPtiz6ECMPjnKH33P2WZwxNAMdLJEpooPCe4');
And then for the autoload.php:
<?php
/**
* You only need this file if you are not using composer.
* Adapted from the Facebook PHP SDK 4.0.x autoloader
*/
if (version_compare(PHP_VERSION, '5.4.0', '<')) {
throw new Exception('The Parse SDK requires PHP version 5.4 or higher.');
}
/**
* Register the autoloader for the Parse SDK
* Based off the official PSR-4 autoloader example found here:
* https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader-examples.md
*
* #param string $class The fully-qualified class name.
* #return void
*/
spl_autoload_register(function ($class)
{
// Parse class prefix
$prefix = 'Parse\\';
// base directory for the namespace prefix
$base_dir = defined('PARSE_SDK_DIR') ? PARSE_SDK_DIR : bloginfo( 'template_url' ) . '/parse/';
// does the class use the namespace prefix?
$len = strlen( $prefix );
if ( strncmp($prefix, $class, $len) !== 0 ) {
// no, move to the next registered autoloader
return;
}
// get the relative class name
$relative_class = substr( $class, $len );
// replace the namespace prefix with the base directory, replace namespace
// separators with directory separators in the relative class name, append
// with .php
$file = $base_dir . str_replace( '\\', '/', $relative_class ) . '.php';
echo $file;
// echo $relative_class . '<br/>';
// if the file exists, require it
if ( file_exists( $file ) ) {
require $file;
}
});
Notice that I am echoeing the $file and this points to the correct directory :/
Add the "use" declarations where you'll be using the classes. For all
of the sample code in this file:
https://github.com/ParsePlatform/parse-php-sdk
So adding use Parse\ParseClient; to your PHP file should fix the issue, add the declaration for whatever class form the Parse PHP SDK you intend to use.
if the folder structure is:
autoload.php
yourcurrentfile.php
/src
/src/Parse
you can skip / remove:
define( 'PARSE_SDK_DIR', bloginfo( 'template_url' ) . '/parse/' );
if you want to set another url just use:
define( 'PARSE_SDK_DIR', __DIR__.'/src/Parse/' );
and change to the correct URL.
Related
Using spl_autoload_register() with a class that uses namespace, causes this error message: Fatal error: Uncaught Error: Class "MyClass" not found...
Before this error message, the autoloader does echo "...MyClass.php IS found".
Two files are used: "/index.php" (in the root directory) and "/classes/MyClass.php".
Index.php:
declare(strict_types=1);
define ('ROOT_DIR', __DIR__ . '/');
define ('CLASS_DIR', ROOT_DIR . 'classes/');
spl_autoload_register(function($class) {
$filepath = CLASS_DIR . str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
if (file_exists($filepath)) {
require_once $filepath;
echo('<br /><b>' . $filepath . '</b> IS found.<br />');
} else {
echo('<br /><b>' . $filepath . '</b> not found.<br />');
exit;
}
});
$myclass = new MyClass();
MyClass.php:
declare(strict_types=1);
namespace App\Classes
class MyClass
{
// ...
}
Does anyone know how to solve this?
According to https://www.php-fig.org/psr/psr-4/, a vendor name is required, so I am using "App" as a top-level namespace name, even though it is not a directory (because my website uses the root of the server).
I also tried adding "use App/classes/Myclass" to index.php before "$myclass = new MyClass()" but this causes even more problems, because the autoloader will look for the directory "/classes/App/Classes"...
With the namespace removed from the class, everything works fine, and I can use the functions of the class through $myclass. But I would like to start using namespaces... Any help would be really appreciated! <3
Conclusion: Either the line "$myclass = new App\Classes\MyClass();"
or "use App\Classes\MyClass;" should be used.
So it is not possible to use the root of the server while also having a
top-level namespace name ("App") with this autoload function. The
function has to be expanded to allow for this possibility. And the "classes" directory will be renamed to "Classes". I will post my solution when it is ready!
For more details, read the comments below the answer by #IMSoP (Thank
you very much for your help!)
Solution:
declare(strict_types=1);
namespace App;
define ('ROOT_DIR', $_SERVER['DOCUMENT_ROOT'] . '/');
define ('BASE_DIR', __DIR__ . '/');
define ('TOP_LEVEL_NAMESPACE_NAME', __NAMESPACE__ . '/');
spl_autoload_register(function($class) {
if (BASE_DIR == ROOT_DIR . TOP_LEVEL_NAMESPACE_NAME) {
$filepath = ROOT_DIR . str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
} else {
$filepath = BASE_DIR . str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
$filepath = str_replace(TOP_LEVEL_NAMESPACE_NAME, '', $filepath);
}
if (file_exists($filepath)) {
require_once $filepath;
} else {
echo('Class <b>' . end(explode('\\', $class)) . '.php</b> was not found.');
exit;
}
});
use App\Classes\MyClass;
$myclass = new MyClass();
This solution works whether the application is in the directory with the same name as the top-level namespace name, or anywhere else!
You might want to read through the manual pages on autoloading and namespaces to make sure you understand the key concepts.
You have declared a class called MyClass inside the namespace App\Classes; that means that its fully qualified name is App\Classes\MyClass - that's the name you need to call it by from outside that namespace. There could simultaneously be a different class whose fully-qualified name was just MyClass, because it wasn't in any namespace, and any number of others in other namespaces, like App\Security\MyClass, App\UI\MyClass, etc.
Then you've attempted to reference a class in index.php called MyClass, which triggers the autoloader. The autoloader translates it to a path like .../classes/MyClass.php, and loads the right file; but that file defines your namespaced class. So after the autoloader has finished, there is no class called MyClass, only App\Classes\MyClass and the code fails.
If instead you write new App\Classes\MyClass, you'll get the opposite problem: the string passed to your autoloader is 'App\Classes\MyClass' and you translate that to a file path like '.../classes/App/Classes/MyClass.php' - but that's not where your file is. (Adding use App\ClassesMyClass does the same thing - use statements are just compiler assistance to avoid writing out the fully-qualified name as often.)
What you need to do is both:
Consistently use fully-qualified class names (or alias them with use)
Lay out your files to match your namespace structure, so that your autoloader can find them, which generally means a directory per namespace
I am trying to use Parse in a php script.
I have done to following:
Uploaded the files 'autoload.php' and the folder 'Parse' from here to the root directory of the server
https://github.com/parseplatform/parse-php-sdk
Then I created an index.php with the following test code from here: https://www.webniraj.com/2014/08/05/parse-com-using-the-official-parse-php-sdk-v1-0-x/
// define location of Parse PHP SDK, e.g. location in "Parse" folder
// Defaults to ./Parse/ folder. Add trailing slash
define( 'PARSE_SDK_DIR', './Parse/' );
// include Parse SDK autoloader
require_once( 'autoload.php' );
// Add the "use" declarations where you'll be using the classes
use Parse\ParseClient;
use Parse\ParseObject;
use Parse\ParseQuery;
use Parse\ParseACL;
use Parse\ParsePush;
use Parse\ParseUser;
use Parse\ParseInstallation;
use Parse\ParseException;
use Parse\ParseAnalytics;
use Parse\ParseFile;
use Parse\ParseCloud;
// Init parse: app_id, rest_key, master_key
ParseClient::initialize('xxx', 'xxx', 'xxx');
// save something to class TestObject
$testObject = ParseObject::create("TestObject");
$testObject->set("foo", "bar");
$testObject->save();
// get the object ID
echo $testObject->getObjectId();
echo '<h1>Users</h1>';
// get the first 10 users from built-in User class
$query = new ParseQuery("_User");
$query->limit(10);
$results = $query->find();
foreach ( $results as $result ) {
// echo user Usernames
echo $result->get('username') . '<br/>';
}
Of course I replaced the xxx with my app_id, rest_key and master_key
When I now open index.php I am getting
Fatal error: Call to undefined function Parse\curl_init() in /Parse/ParseClient.php on line 304
Did I miss to do something?
I don't have enough reputation points to simply comment, but wanted to suggest you confirm that you have the curl PHP extension installed on your server.
phpinfo();
or
if (extension_loaded("curl"))
{
echo "cURL extension is loaded<br>";
}
else
{
echo "cURL extension is not available<br>";
}
I am using classes with Wordpress and I am trying to autoload them in my functions.php file:
spl_autoload_register(function($class) {
include('classes/'.$class.'.php');
});
This is what my classes directory looks like:
classes/
project/
Application.php
Core.php
Site.php
Helpers.php
utils/
Helpers.php
Twig.php
views/
Layout.php
Modules.php
pages/
Home.php
Each class is namespaced based on the directory it is in. For example:
$homeClass = new \views\pages\Home();
When I autoload the classes, I get this error:
PHP Warning: include(classes/project\Application.php): failed to open stream: No such file or directory
Obviously the backslashes that are part of the namespacing don't work in the path. I could update my function to replace the backslashes with forward slashes like this:
spl_autoload_register(function($class) {
include('classes/'.str_replace("\\", "/", $class).'.php');
});
But it seems odd that that would be required. Am I missing something?
I have an example here.
Basically a better version of spl_autoload_register since it only tries to require the class file whenever you initializes the class.
Here it automatically gets every file inside your class folder, requires the files and initializes it. All you have to do, is name the class the same as the file.
index.php
<?php
require_once __DIR__ . '/app/autoload.php';
$loader = new Loader(false);
User::dump(['hello' => 'test']);
autoload.php
<?php
class Loader
{
public static $library;
protected static $classPath = __DIR__ . "/classes/";
protected static $interfacePath = __DIR__ . "/classes/interfaces/";
public function __construct($requireInterface = true)
{
if(!isset(static::$library)) {
// Get all files inside the class folder
foreach(array_map('basename', glob(static::$classPath . "*.php", GLOB_BRACE)) as $classExt) {
// Make sure the class is not already declared
if(!in_array($classExt, get_declared_classes())) {
// Get rid of php extension easily without pathinfo
$classNoExt = substr($classExt, 0, -4);
$file = static::$path . $classExt;
if($requireInterface) {
// Get interface file
$interface = static::$interfacePath . $classExt;
// Check if interface file exists
if(!file_exists($interface)) {
// Throw exception
die("Unable to load interface file: " . $interface);
}
// Require interface
require_once $interface;
//Check if interface is set
if(!interface_exists("Interface" . $classNoExt)) {
// Throw exception
die("Unable to find interface: " . $interface);
}
}
// Require class
require_once $file;
// Check if class file exists
if(class_exists($classNoExt)) {
// Set class // class.container.php
static::$library[$classNoExt] = new $classNoExt();
} else {
// Throw error
die("Unable to load class: " . $classNoExt);
}
}
}
}
}
/*public function get($class)
{
return (in_array($class, get_declared_classes()) ? static::$library[$class] : die("Class <b>{$class}</b> doesn't exist."));
}*/
}
You can easily manage with a bit of coding, to require classes in different folders too. Hopefully this can be of some use to you.
It's not odd at all!
Registering your autoloaders using namespaces as a means to denote a directory structure is fairly common practice. I would recommend following PSR-4 conventions, but if you you're too far in to refactor your naming conventions, then I would recommend using the DIRECTORY_SEPARATOR constant to help PHP decide whether to use '/' or '\', as Windows servers use the latter, and Linux servers use the former.
I've made a class for this requirement, compatible with PSR-4.
You can reach it here:
https://github.com/pablo-pacheco/wp-namespace-autoloader
The explanation is all there but basically it's a composer dependency. You just have to require it in your project:
"require": {
"pablo-pacheco/wp-namespace-autoloader": "dev-master"
}
And then call the class
<?php
new \WP_Namespace_Autoloader( array(
'directory' => __DIR__, // Directory of your project. It can be your theme or plugin. __DIR__ is probably your best bet.
'namespace' => __NAMESPACE__, // Main namespace of your project. E.g My_Project\Admin\Tests should be My_Project. Probably if you just pass the constant __NAMESPACE__ it should work
'classes_dir' => 'src', // (optional). It is where your namespaced classes are located inside your project. If your classes are in the root level, leave this empty. If they are located on 'src' folder, write 'src' here
) );
I appreciate any kind of feedback!
Try this class, it autoloads with or without namespaces
I am new in codeigniter . i can easily work with parse.com library on core php like this
<?php
// define location of Parse PHP SDK, e.g. location in "Parse" folder
// Defaults to ./Parse/ folder. Add trailing slash
define( 'PARSE_SDK_DIR', '../src/Parse/' );
// include Parse SDK autoloader
require_once( 'autoload.php' );
// Add the "use" declarations where you'll be using the classes
use Parse\ParseClient;
use Parse\ParseObject;
use Parse\ParseQuery;
use Parse\ParseACL;
use Parse\ParsePush;
use Parse\ParseUser;
use Parse\ParseInstallation;
use Parse\ParseException;
use Parse\ParseAnalytics;
use Parse\ParseFile;
use Parse\ParseCloud;
// Init parse: app_id, rest_key, master_key
ParseClient::initialize('id', 'id2', 'id3');
// save something to class TestObject
$testObject = ParseObject::create("TestObject");
$testObject->set("foo", "bar");
$testObject->save();
// get the object ID
echo $testObject->getObjectId();
echo '<h1>Users</h1>';
// get the first 10 users from built-in User class
$query = new ParseQuery("_User");
$query->limit(10);
$results = $query->find();
foreach ( $results as $result ) {
// echo user Usernames
echo $result->get('username') . '<br/>';
}
but i am unable to use this in codeigniter . please help me how i can add parse.com in codeigniter and use this.
please provide me some direction and example
download CI library from here
parse.com paste all code inside your application/libraries folder. make sure you have created custom config parse.php file sample
<?php
/**
* Parse keys
*/
$config['parse_appid'] = '';
$config['parse_masterkey'] = '';
$config['parse_restkey'] = '';
$config['parse_parseurl'] = 'https://api.parse.com/1/';
?>
and in your sample controller ParseSample.php try this.
<?php if (! defined('BASEPATH')) exit('No direct script access allowed');
class ParseSample extends CI_Controller {
public function index()
{
$temp = $this->load->library('parse');
$testObj = $this->parse->ParseObject('testObj');
$testObj->data = array("testcol" => "it works");
$return = $testObj->save($testObj->data);
echo "<pre>";
print_r($return);
echo "<pre>";
var_dump($return);
exit;
}
}
Hope someone might feel helpful.
This question already has answers here:
How do I use PHP namespaces with autoload?
(13 answers)
Closed 6 years ago.
I am trying to understand how to define a working autoloader for a trivial application with namespaces.
I created following structure:
public
index.php
src
Models
WordGenerator.php
Obviously, later it will grow. The WordGenerator.php file is following:
<?php
namespace Models;
class WordGenerator {
public $filename;
public function __construct($filename) {
$this->_filename = $filename;
}
}
Now I try to create instance of this object in index.php:
<?php
use \Models;
$wg = new WordGenerator("words.english");
Obviously I get fatal error because I did not define autoloader. However though, according to documentation all I can pass is $classname. How should I define the autoloader function to take namespace declared by use statement then??
[edit]
I was wrong understood a moment ago. So here's my code for index.php:
spl_autoload_register(function ($className) {
$className = ltrim($className, '\\');
$prepend = "..\\src\\";
$fileName = "{$prepend}";
$namespace = '';
if ($lastNsPos = strrpos($className, '\\')) {
$namespace = substr($className, 0, $lastNsPos);
$className = substr($className, $lastNsPos + 1);
$fileName = $prepend.str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
}
$fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
require $fileName;
});
//require '../src/Models/WordGenerator.php';
use Models;
$wg = new WordGenerator("words.english");
echo $wg->getRandomWord();
Now, this does not work and I get:
Warning: The use statement with non-compound name 'Models' has no effect in C:\xampp\htdocs\Hangman\public\index.php on line 22
Warning: require(..\src\WordGenerator.php): failed to open stream: No such file or directory in C:\xampp\htdocs\Hangman\public\index.php on line 16
Fatal error: require(): Failed opening required '..\src\WordGenerator.php' (include_path='.;C:\xampp\php\PEAR') in C:\xampp\htdocs\Hangman\public\index.php on line 16
However when I change new WordGenerator to new \Models\WordGenerator it works. Now, the question is: how can I pass namespaces declared by use statement to autoloader function to make it work properly?
Your use statement is incorrect. You want use Models\WordGenerator;
The use operator doesn't declare anything but an alias. Consider the expanded form:
use Models\WordGenerator as WordGenerator;
Which is equivalent.
You can alias a namespace rather than a class, but it doesn't work in the way you're attempting. For example:
use Models as Foo;
$wg = new Foo\WordGenerator("words.english");
Would work. However:
use Models;
Is equivalent to:
use Models as Models;
Which effectively does nothing.
For more information see Using namespaces: Aliasing/Importing in the PHP manual.
Please look at documentation. Autoloader must be defined by you at beginning of you script. At provided link there is example autoloader and more complex solution