Whether require and use are similiar in php? - php

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.

Related

amphp auto-load class not working as expected

I'm trying to use a custom class in a worker using amphp but it doesn't seem to be working. The below class is already auto-loaded using composer. Please help me out with this issue. My code is below:
Class (this implements Task as mentioned on their docs):
<?php
namespace Jobs;
require '/home/xxx/vendor/autoload.php';
use Amp\Parallel\Worker\Environment;
use Amp\Parallel\Worker\Task;
class GetMarketJob implements Task {
/**
* #var callable
*/
private $function;
/**
* #var mixed[]
*/
private $args;
public function __construct($function, ...$args) {
$this->function = $function;
$this->args = $args;
}
/**
* {#inheritdoc}
*/
public function run(Environment $environment)
{
if ($this->function instanceof \__PHP_Incomplete_Class) {
throw new \Error('When using a class instance as a callable, the class must be autoloadable');
}
if (\is_array($this->callable) && ($this->callable[0] ?? null) instanceof \__PHP_Incomplete_Class) {
throw new \Error('When using a class instance method as a callable, the class must be autoloadable');
}
if (!\is_callable($this->function)) {
$message = 'User-defined functions must be autoloadable (that is, defined in a file autoloaded by composer)';
if (\is_string($this->function)) {
$message .= \sprintf("; unable to load function '%s'", $this->function);
}
throw new \Error($message);
}
return ($this->function)(...$this->args);
}
public function testMe($url = NULL) {
$test = file_get_contents($url);
return $test;
}
}
File using amphp to assign worker using above class:
<?php
require '/home/xxxx/vendor/autoload.php';
use Jobs\GetMarketJob;
// Example async producer using promisor
use Amp\Parallel\Worker;
use Amp\Promise;
use Amp\Loop;
use Amp\Parallel\Worker\DefaultPool;
use Amp\Parallel\Worker\Task;
use Amp\Parallel\Worker\Environment;
use Amp\Parallel\Worker\TaskFailureError;
use Amp\Parallel\Worker\DefaultWorkerFactory;
Amp\Loop::run(function () {
$factory = new DefaultWorkerFactory();
$worker = $factory->create();
$result = yield $worker->enqueue(new GetMarketJob('testMe', ['https://www.syhtek.com']));
print($result);
$code = yield $worker->shutdown();
\printf("Code: %d\n", $code);
});
running this script gives me the below output:
[26-May-2021 01:23:11 UTC] PHP Fatal error: Uncaught
Amp\Parallel\Worker\TaskFailureError: Uncaught Error in worker with
message "User-defined functions must be autoloadable (that is, defined
in a file autoloaded by composer); unable to load function 'testMe'"
and code "0"; use
Amp\Parallel\Worker\TaskFailureError::getOriginalTrace() for the stack
trace in the worker in
/home/xxxx/vendor/amphp/parallel/lib/Worker/Internal/TaskFailure.php:60
Thank you so much for reading!
The issue here is that you're passing 'testMe' and then check if (!\is_callable($this->function)) {, while it should be if (!\method_exists($this, $this->function)) {.
And return ($this->function)(...$this->args); should be return ($this->{$this->function})(...$this->args); if you're trying to call that method. You might also call that method directly instead of giving it to the constructor.
If everything you do in the worker is an HTTP request, you should look into amphp/http-client instead of amphp/parallel, as non-blocking I/O is much more efficient than several chlid processes with blocking I/O.

How can I use HTMLPurifier inside a PHP class?

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.

Yii2 dynamically loading class from name

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.

Trouble Importing PHP Class within the same project

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.

Troubles with GO! Aspect-Oriented Framework

If someone work with GO! framework, can you help me.
I install framework on php 5.3.13. Demo example is working.
But my own example doesn't work. Aspect(method beforeMethodExecution) is not perfomed.
Here is my code.
Main file:
//1 Include kernel and all classes
if (file_exists(__DIR__ .'/../../vendor/autoload.php')) {
$loader = include __DIR__ .'/../../vendor/autoload.php';
}
// 2 Make own ascpect kernel
use Go\Core\AspectKernel;
use Go\Core\AspectContainer;
class Kernel extends AspectKernel{
/**
* Configure an AspectContainer with advisors, aspects and pointcuts
*
* #param AspectContainer $container
*
* #return void
*/
public function configureAop(AspectContainer $container)
{
}
}
//3 Initiate aspect kernel
$Kernel = Kernel::getInstance();
$Kernel->init();
//4 Include aspect
include(__DIR__.'/aspectclass/AspectClass.php');
$aspect = new DebugAspect();
//5 register aspect
$Kernel->getContainer()->registerAspect($aspect);
//6 Include test class
include(__DIR__.'/class/class1.php');
//7 Execute test class
$Class = new General('test');
$Class->publicHello();
File with test class:
class General{
protected $message = '';
public function __construct($message)
{
$this->message = $message;
}
public function publicHello()
{
echo 'Hello, you have a public message: ', $this->message, "<br>", PHP_EOL;
}
}
File with aspect:
use Go\Aop\Aspect;
use Go\Aop\Intercept\FieldAccess;
use Go\Aop\Intercept\FunctionInvocation;
use Go\Aop\Intercept\MethodInvocation;
use Go\Lang\Annotation\After;
use Go\Lang\Annotation\Before;
use Go\Lang\Annotation\Around;
use Go\Lang\Annotation\Pointcut;
use Go\Lang\Annotation\DeclareParents;
use Go\Lang\Annotation\DeclareError;
class DebugAspect implements Aspect{
/**
* Method that should be called before real method
*
* #param MethodInvocation $invocation Invocation
* #Before("execution(General->*(*))")
*
*/
public function beforeMethodExecution(MethodInvocation $invocation)
{
$obj = $invocation->getThis();
echo 'Calling Before Interceptor for method: ',
is_object($obj) ? get_class($obj) : $obj,
$invocation->getMethod()->isStatic() ? '::' : '->',
$invocation->getMethod()->getName(),
'()',
' with arguments: ',
json_encode($invocation->getArguments()),
PHP_EOL;
}
}
As you know, go-aop isn't a PHP extension, so it couldn't transform classes that were loaded directly via require or include. Internally it tries to overwrite the source code on-the-fly, but it should receive a control (via integration with composer or custom autoloader class).
So, you have an error here:
//6 Include test class
include(__DIR__.'/class/class1.php');
You explicitly load this class into memory and there is no way to transform it from userland. To pass a control to the framework, you should make this explicitly. Look at the line AopComposerLoader.php#L99 to have an idea how it works. Here we include a source file via the stream source filter that pass control to the framework and it can transform the class to weave an aspects.
To fix your example just change an include to the following:
include (FilterInjectorTransformer::rewrite(__DIR__.'/class/class1.php'));

Categories