Yii 2: Using a class from inside a require_once - php

I'm using a 3rd party extension like so:
(This is inside my controller)
require_once Yii::$app->basePath.'/vendor/campaignmonitor/createsend-php/csrest_subscribers.php';
$wrap = new CS_REST_Subscribers($list_id, $auth);
However, this is returning an error that CS_REST_subscribers class is not found.
How do I use this class correctly when the class is inside the file. Unfortunately this extension is older and is not namespaced.

You need to install it using composer with the following command
composer require "campaignmonitor/createsend-php" "6.0.0"
It uses the simplest way, i.e autoloads each class separately. we define the array of paths to the classes that we want to autoload in the composer.json file and if you see the vendor/campaignmonitor/createsend-php/composer.json file inside the package directory
"autoload": {
"classmap": [
"csrest_administrators.php",
"csrest_campaigns.php",
"csrest_clients.php",
"csrest_general.php",
"csrest_events.php",
"csrest_lists.php",
"csrest_people.php",
"csrest_segments.php",
"csrest_subscribers.php",
"csrest_templates.php",
"csrest_transactional_classicemail.php",
"csrest_transactional_smartemail.php",
"csrest_transactional_timeline.php"
]
}
so you won't need the include or require statement, you can directly call any class you want for instance adding the following lines inside your action or view
$authorize_url = CS_REST_General::authorize_url(
'1122',//'Client ID for your application',
'http://example.com/redirect-page',//Redirect URI for your application,
'ViewReports'//The permission level your application requires,
);
print_r($authorize_url);
prints the following
https://api.createsend.com/oauth?client_id=1122&redirect_uri=http%3A%2F%2Fexample.com%2Fredirect-page&scope=ViewReports
For knowledge base if you want to use a Third-party code that is not using autoloader or psr4 you can go through the Yii tutorial

Related

Disambiguating a PHP namespace used by two vendors

I have two composer packages in my app that are creating a namespace collision in a third party module. I'm trying to determine the least disruptive way to disambiguate within the third party module so that I don't have to fork the packages.
First package from Vendor X, located in a directory structure like
path/to/vendor/VendorX/MailPackageA:
<?php
namespace MailPackageA;
class Mail {
...
}
My existing third-party module, which lists VendorX/MailPackageA as a dependency, located in structure like
moduleDirectory/MailingModule/mail.inc:
<?php
class ThirdPartyMailMod implements CoreMailSystem {
$mail_object = new MailPackageA\Mail();
. . .
}
For slightly different mailing functionality used in another module, I had to add a package that uses the same namespace identifier (MailPackageA), but from a different vendor, "VendorY". Like VendorX/MailPackageA, it's placed in a directory structure like
path/to/vendor/VendorY/MailPackageA:
<?php
namespace MailPackageA;
class Mail {
...
}
After adding this, I get errors in MailingModule/mail.inc at $mail_object = new MailPackageA\Mail(); because of the obvious namespace collision between MailPackageA\Mail classes from VendorY and VendorX.
Routes I've already been down, but failed:
Modify PSR-4 autoload rules in composer.json for either of the packages to create new namespaces. (I'm getting the sense my framework -- Drupal 7 -- does not respect the composer autoload rules, and simply defaults to stock php 7 namespacing), so I've abandoned that for the moment.
Try to add a vendor prefix alias to the MailingModule/mail.inc file with use.
<?php
use VendorX\MailPackageA;
\\ also tried the `use VendorX\MailPackageA as MailPackageA;` pattern to no effect
class ThirdPartyMailMod implements CoreMailSystem {
$mail_object = new MailPackageA\Mail();
}
I suspect that my app doesn't know about the vendor directories. Not sure how to force that.
What's the least disruptive way (i.e. minimal forking/patching) to make sure MailingModule only uses the MailPackageA\Mail class from Vendor X?
to overcome this problem use alias when you use the namespace .
use as keyword like this
use VendorX\MailPackageA as newPackageName;
and if you need to call the class from this namespace you will have it like this
$packageName = new newPackageName\Mail();

Composer: looking for namespaced class in multiple locations

I'm trying to figure out how to get composer to look for classes for a specific namespace under 2 directories. What I'm thinking of is this:
Default location: /src/MyModule/myClass.php
Override location: /config/override/MyModule/myClass.php
Now, I'd like to use composer to configure the autoloader to check if a class exists under the Override location. If it does, use this class. If not, load the class from the default location.
Is this possible using composer or would I have to implement this logic using my own autoloader?
From Composer documentation:
If you need to search for a same prefix in multiple directories, you
can specify them as an array as such:
{
"autoload": {
"psr-4": { "Monolog\\": ["src/", "lib/"] }
}
}
You would add that to your composer.json file of course. To do it programatically you can do this:
$autoloader = require __DIR__.'/../vendor/autoload.php';
$autoloader->addPsr4('MyModule\\', [ '/first/dir/MyModule', '/another/dir/MyModule' ]);

laravel 5 Class implements Iterator

I am trying to integrate an existing library into Laravel5 which itself is not namespaced and uses its own classes in subfolders using require.
I have placed it at 'app/API/libname/mainlibclass.php'.
with sibling directory at 'app/API/libname/toolkit' which contains the classes the library uses.
Calling from a Laravel controller I am unable to create the class using a require statement (correct?) before
$objectinstance=new Mainlibclass();
so in the main Laravel app I have
use app/API/libname/Mainlibclass
then later the usual
$objectinstance=new Mainlibclass();
In the existing library and each of its own used classes I set
namespace app/API/libname
and 'use' where needed.
I now have no class not found but one of the files uses 'implements Iterator' - I am getting error Interface 'App\API\libname\Iterator' not found.
Try adding \ in front of that so it looks like this:
class ABC implements \Iterator {
Edit:
I think it would be better practice to keep external non-psr-4/0 libraries untouched (for easier update if needed in future) and outside of app/ directory.
You could use composer classmap autoload feature for this.

Autoload Helper folder Laravel 5

I would like to call statics methods in a helpers folders.
I have tried many tutos but it's always for just one file.
My config
/app/Helpers/Languages.php -> my static class
composer.json
"autoload": {
"classmap": [
"database",
"app/Helpers/" <- I understand, L5 add in own autoload
app.php
'aliases' => [ ...., 'Languages' => 'App\Helpers\Languages',
What I tried :
Add autoload classmap, HelpersServiceProviders class, namespace (work just in blade template, not in a Controller)
Add autoload psr-4 with and without classmap, namespace
For all the method, I need to put the use 'app/Helpers/Languages' but I would like call just Languages::myFunction() without 'use' . Is it possible ?
I already the 'app/' folder in psr-4 so it will be load folder and my file, isn't it ?
If it's can help when in load a page without I've :
FatalErrorException Class 'App\Http\Controllers\Languages' not found
When I updated composer.json, I did't forgot composer dump-autoload
I don't think the problem you have is because the class is not being autoloaded, but rather because you try to use it the wrong way. Even with the alias you added, when using the class from within a namespace (like App\Http\Controllers) you have to either add an import statement:
use App\Helpers\Languages;
// or with the alias
use Languages;
Or specify the FQN when using it:
\App\Helpers\Languages::myFunction();
// or with the alias
\Languages::myFunction();
You can't really avoid this. What you could do, so you don't have to worry about namespaces: use helper functions without a class. Just like Laravel's helper functions. (route(), 'trans()', etc)

Write a user defined class in laravel?

I have class in libraries/myclass.php and a function named myFunction. Also I try to call that function in my controller with the following code
$myclasobj=new libraries\Myclass();
$returnvalue=$myclasobj->myFunction($para);
results that class not found. I dont want it as a helper class and auto load this class. I just want to use as a simple class.I am using laravel 4.How can I obtain this?
Update
Thanks all of you for your great help.
As per #carousel,#Ohgodwhy I make it by namespacing (Actually before I don't know about it).
I make a directory under libraries named mylib and move my class (myclass.php) to it and after that I add namespace mylib; to the top of myclass.php.
And after that I add use mylib\Myclass; to my controller.
Finally I add these lines to composer.json
,
"psr-0": {
"mylib": "app/libraries"
},
After these things my class is working.Thanks to all for helping me
Every new class, in order to be used in Laravel, has to be linked to Application. It can be done in more then one way:
Through class map
With namespacing
By its path
In that sense there is no simple classes. All classes can become a part of Laravel Application flow, if they are referenced correctly with composer.
UPDATE TO MY ANSWER:
Here is a link to best resource that explaines facades.
Assuming that the file hasn't been loaded yet, the proper way to add your libraries/ directory to the classloader would be to modify your composer.json to add the directory to the autoloader.
autoload: {
classmap: [
"...",
"libraries/"
]
}
After that, you'll need to rebuild the autoloader, so in the home directory, go ahead and run this in your terminal:
$ php artisan dump-autoload -o
Also ensure that your class is actually contained inside a namespace, because using
new libraries\myClass();
Does not load "myClass" from the "libraries" folder. It would be helpful if you could add it to the original question.
Try doing this, it should solve your problem:
ClassLoader::addDirectories(array(
app_path().'/commands',
app_path().'/controllers',
app_path().'/models',
app_path().'/database/seeds',
app_path().'/classes', //we added this
));

Categories