Someone could help me on the issue of referencing php files within the same project (calling classes) using "namespace","use" ( php v5.3 or higher)
[My Screenshoot][http://i.imgur.com/6GC4UUK.png?1]
Fatal error: Class 'Zoho\CRM\Common\HttpClientInterface' not found in
C:\root\zohocrm-master\src\Zoho\CRM\index.php on line 73
<?php namespace Zoho\CRM;
use Zoho\CRM\Common\HttpClientInterface;
use Zoho\CRM\Common\FactoryInterface;
use Zoho\CRM\Request\HttpClient;
use Zoho\CRM\Request\Factory;
use Zoho\CRM\Wrapper\Element;
.
.
.
public function __construct($authtoken, HttpClientInterface $client =null , FactoryInterface $factory = null )
{
$this->authtoken = $authtoken;
// Only XML format is supported for the time being
$this->format = 'xml';
$this->client = new HttpClientInterface();
$this->factory = $factory ;
$this->module = "Leads";
return $this;
}
Robinson, you are calling the class "Zoho\CRM\Common**HttpClientInterface**" from this position: "C:\root\zohocrm-master\src\Zoho\CRM**index.php**".
This means the way you are trying to use the namespace is not correct.
Remember, if you do:
use App\namespace\class_name
It means your class "class_name" has to be in a folder like this: App/namespace/.
So define very well the path to your class when you are calling use.
Related
As the title states; how can I use the HTMLPurifier library inside my class?
I'm trying to get to grips with OOP and PHP classes for the first time and have successfully built a class that connects to my database using my database class and returns a blog article.
I would now like to parse the HTML markup for the blog article using HTMLPurifier but I would like to achieve this inside my blog class and I'm wondering how it can be achieved, as HTMLPurifier is a class.
My class so far:
namespace Blog\Reader;
use PDO;
use HTMLPurifier_Config; <--- trying to include it here
use \Database\Connect;
class BlogReader {
private static $instance = null;
private static $article = null;
private static $config = null;
private static $db = null;
private static function InitDB() {
if (self::$db) return;
try {
$connect = Connect::getInstance(self::$config['database']);
self::$db = $connect->getConnection();
} catch (Throwable $t) {}
}
private function __construct($config) {
self::$config = $config;
}
public static function getInstance($config) {
if (!self::$instance) {
self::$instance = new BlogReader($config);
}
return self::$instance;
}
public static function getArticle($id) {
self::InitDB();
try {
if (self::$db) {
$q = self::$db->prepare("
// sql
");
$q->bindValue(':id', (int) $id, PDO::PARAM_INT);
$q->execute();
self::$article = $q->fetchAll(PDO::FETCH_ASSOC);
//////////// <----- and trying to use it here
$HTMLPurifier_Config = HTMLPurifier_Config::createDefault();
$purifier = new HTMLPurifier($HTMLPurifier_Config);
///////////
} else {
throw new Exception("No database connection found.");
self::$article = null;
}
} catch (Throwable $t) {
self::$article = null;
}
return self::$article;
}
private function __clone() {}
private function __sleep() {}
private function __wakeup() {}
}
However, I get the following error log when trying anything like this:
Uncaught Error: Class 'HTMLPurifier_Config' not found in
....../php/classes/blog/reader/blogreader.class.php
And the line number of the error is on this line:
$HTMLPurifier_Config = HTMLPurifier_Config::createDefault();
My class directory structure:
[root]
[blog]
blog.php <--- using classes here
[php]
afs-autoload.php
[classes]
[blog]
[database]
[vendor]
[htmlpurifier-4.10.0]
[library]
HTMLPurifier.auto.php <--- this is what I used to `include` on blog.php to autoload HTMLPurifier_Config::createDefault() and new HTMLPurifier($purifier_config).
My Autoloader (afs-autoload.php) file:
define('CLASS_ROOT', dirname(__FILE__));
spl_autoload_register(function ($class) {
$file = CLASS_ROOT . '/classes/' . str_replace('\\', '/', strtolower($class)) . '.class.php';
if (file_exists($file)) {
require $file;
}
});
I literally started learning classes today, so I'm really baffled as to how I can achieve this, especially with the namespace system I used.
I hope somebody with better experience can guide me in the right direction.
Rewritten answer:
1) Your auto loader is looking for <class>.class.php files; but your HTMLPurifier_Config is in a HTMLPurifier.auto.php file.
2) Still in your autoloader: str_replace('\\' You do not need to escape characters when in single quotes, so this should be: str_replace('\'.
3) This excellent answer should help you learn when and how to use the use PHP keyword.
4) Your issue is not the scope of your use (I don't think you even need to use use). But is that your autoloader is looking for the wrong type of files. Try manually loading the class using require and seeing if it works properly.
Original Answer
namespace Blog\Reader;
use PDO;
use HTMLPurifier_Config;
What you're actually doing here is using the values within the defined namespace; so you're using:
Blog\Reader\HTMLPurifier_Config
If you're HTMLPurifier_Config file is within its own namespace you need to specify that so that the "use" grabs the right data!
If its not in its own namespace then it will be in the global namespace which is identified with a slash:
namespace Blog\Reader;
use PDO;
use \HTMLPurifier_Config;
If it is in the namespace HTMLPurifier, for example:
namespace Blog\Reader;
use PDO;
use \HTMLPurifier\HTMLPurifier_Config;
to load the correct data reference.
Just to wrap this up, if you are using namespaces inside a class which as been placed in a namespace, this is how you create your purifier objects:
$config = \HTMLPurifier_Config::createDefault();
$purifier = new \HTMLPurifier($config);
$clean_html = $purifier->purify($dirty_html);
You do not have to use a use command since the HTMLPurifier classes themselves are not in a namespace. But when your code is in a namespace, you need to pre-pend '\' to non-namespaced classes.
namespace \Tdiscus; // This is the line that makes the difference.
use \Tsugi\Util\Net;
class Threads {
...
$config = \HTMLPurifier_Config::createDefault();
...
$retval = new \stdClass();
...
$dbh = new \PDO($dsn, $user, $password);
}
Because you placed the class in a namespace, any "non-namespaced" classes need a "" prefix - like PDO and stdClass in the above example.
The HTMLPurifier folks could have put their classes in a namespace - but they chose not to do that.
Using namespaces is a common practice when developing libraries intended for use with composer. But HTMLPurifier existed before composer was in common use and their classes have a nice unique prefix because they started out in a global class namespace - so they decided to leave well enough alone and not break the non-dynamic loading / non-namespace legacy adopters of their library.
I struggle with this problem for a while - and the reason is probably trivial.
Background
I've created parser module for my Yii2 application so I can call it from other places (mobile app, etc.) to get data from various websites. There may be many parser classes, all implementing same interface.
Project structure
...
/modules
\_ parser
\_components
\_parsers
\_SampleParser.php
\_controllers
\_DefaultController.php
\_Parser.php
...
I've removed some code for better readability.
DefaultController.php:
namespace app\modules\parser\controllers;
use Yii;
use yii\web\Controller;
use app\modules\parser\components\parsers;
use app\modules\parser\components\parsers\SampleParser;
/**
* Default controller for the `parser` module
*/
class DefaultController extends Controller
{
private function loadParser($parserName){
return new SampleParser(); // if I leave this here, everything works okay
$className = $parserName.'Parser';
$object = new $className();
if ($object instanceof IParseProvider){
return $object;
}
}
...
public function actionIndex()
{
$url = "http://google.com";
$parser = 'Sample';
$loadedParser = $this->loadParser($parser);
$response = $loadedParser->parse($url);
\Yii::$app->response->format = 'json';
return $response->toJson();
}
...
SampleParser.php:
<?php
namespace app\modules\parser\components\parsers;
use app\modules\parser\models\IParseProvider;
class SampleParser implements IParseProvider {
public function canParse($url){
}
public function parse($url){
}
}
Right now everything works more or less ok, so I guess I'm importing correct namespaces. But when I remove return new SampleParser(); and let the object to be created by string name, it fails with error:
PHP Fatal Error – yii\base\ErrorException
Class 'SampleParser' not found
with highlighted line:
$object = new $className();
What am I doing wrong here? Thanks!
Try again with help of Yii:
private function loadParser($parserName)
{
return \yii\di\Instance::ensure(
'app\modules\parser\components\parsers\\' . $parserName . 'Parser',
IParseProvider::class
);
}
Remember that ensure() throws \yii\base\InvalidConfigException when passed reference is not of the type you expect so you need to catch it at some point.
If you are using PHP < 5.5 instead of IParseProvider::class you can use full class name with it's namespace.
P.S. remove use app\modules\parser\components\parsers; unless you have got class named parsers you want to use.
i want to create object of class base on string which come from URL parameter.
for example :
http://localhost/CSWeb/api/search/Slideshare
in above URL Slideshare is parameter which get in apiController->indexAction.
slideshare.php class
<?php
namespace App\Http\API;
class slideshare
{
public function index()
{
return 'any data';
}
}
apiController.php
namespace App\Http\Controllers\API;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Auth;
use App\Http\API\Slideshare;
class apiController extends Controller
{
public function index($source)
{
$controller= new $source;
return $controller->index();
// if i change code to $controller= new Slideshare; it works fine
}
}
laravel error when i use parameter string to create class object
FatalErrorException in apiController.php line 17: Class
'Slideshare' not found
if i change code to
$controller= new Slideshare; it works fine
Thank you in advance
When creating PHP objects with strings, you must provide the full qualified name of the class (a.k.a include the namespace). So, you should have something like this:
$className = 'App\\Http\\API\\' . $source;
$controller = new $className;
return $controller->index();
Another way to do it, if you are sure that the class you want to instantiate lives in the same namespace as your code, you can use:
$className = __NAMESPACE__ . '\\' . $source;
$controller = new $className;
return $controller->index();
A more elaborated way of achieving the same results is through the Factory Design Pattern. Basically you create a class that is responsible for instantiating elements, and you delegate the task of actually creating those objects to that class. Something along those lines:
class Factory {
function __construct ( $namespace = '' ) {
$this->namespace = $namespace;
}
public function make ( $source ) {
$name = $this->namespace . '\\' . $source;
if ( class_exists( $name ) ) {
return new $name();
}
}
}
$factory = new Factory( __NAMESPACE__ );
$controller = $factory->make( $source );
The advantage of this approach is that the responsability of creating the objects now lies in the Factory, and if you ever need to change it, maybe allow for aliases, add some additional security measures, or any other thing, you just need to change that code in one place, but as long as the class signature remains, your code keeps working.
An interesting tutorial on factories:
http://culttt.com/2014/03/19/factory-method-design-pattern/
Source:
http://nl3.php.net/manual/en/language.oop5.basic.php#language.oop5.basic.new
http://php.net/manual/en/language.namespaces.nsconstants.php
I'm trying to run this code on the same file:
namespace Foo1\Bar\SubBar;
class SubBarClass {
public function __construct() {
echo 'From Foo1';
}
}
namespace Foo2\Bar\SubBar;
class SubBarClass {
public function __construct() {
echo 'From Foo2';
}
}
use Foo1\Bar\SubBar;
$foo1 = new SubBarClass;
use Foo2\Bar\SubBar;
$foo2 = new SubBarClass;
The ideia is to change namespaces and echo the related value.
But it's returning the following error:
( ! ) Fatal error: Cannot use Foo2\Bar\SubBar as SubBar because the name is already in use in C:\wamp\www\xxx\namespaces.php on line 30
Line 30: use Foo2\Bar\SubBar;
How can I interchange namespaces on the same file?
Thks!
use keyword is used to import that namespace to be accessed in your current file scope. It does not act as a namespace "instance constructor".
You're current under Foo2\Bar\SubBar namespace. Like a directory of classes, while you're here, you should access other namespaces from the root (\):
$foo2 = new SubBarClass;
$foo1 = new \Foo1\Bar\SubBar\SubBarClass;
There is no need to use use for those namespaces (although you can, specially when they share parent namespaces), they are already declared in the same file you're using them.
For more information about this, consider reading the manual, where it describes using multiple namespaces in the same file.
This happens because the last defined namespace is the one currently active.
So, when I type:
use Foo1\Bar\SubBar;
I'm still on the last defined namespace: Foo2\Bar\SubBar.
Hence, when I type:
use Foo2\Bar\SubBar;
I'm trying to use the currently active namespace. That's why the Fatal error is returned.
On possible solution is:
namespace Foo1\Bar\SubBar;
class SubBarClass {
public function __construct() {
echo 'From Foo1';
}
}
namespace Foo2\Bar\SubBar;
class SubBarClass {
public function __construct() {
echo 'From Foo2';
}
}
use Foo1\Bar\SubBar;
$foo1 = new SubBar\SubBarClass;
echo '<br>';
$foo2 = new SubBarClass;
Cheers!
use RingCentral\SDK;
or
require('/home/developer/workspace/ringcentral/demo/SDK.php');
Instead of using 'use' - php 5.6 command ,it is better to use require - php 5.3 ?
SDK class file contains following code
class SDK
{
const VERSION = '0.5.0';
/** #var Platform */
protected $platform;
/** #var Context */
protected $context;
public function __construct($appKey, $appSecret, $server)
{
$this->context = new Context();
$this->platform = new Platform($this->context, $appKey, $appSecret, $server);
}
public function getPlatform()
{
return $this->platform;
}
public function getSubscription()
{
return new Subscription($this->context, $this->platform);
}
public function getContext()
{
return $this->context;
}
}
You have to require an autoloader to allow SPL autoload to resolve use statements:
// if you use Composer
require('vendor/autoload.php');
// or just require a PHAR
require('path-to-sdk/ringcentral.phar');
use RingCentral\SDK\SDK;
$sdk = new SDK(...);
You actually may omit use statement and use fully-qualified class name:
$sdk = new RingCentral\SDK\SDK(...);
require() is used to require another file while use is used to use a class from another namespace, so those both commands are totally different and not comparable.
In your case you will need to use require() unless you are using any kind of autoloading like composer to make the class available in your file.