Composer load class without Namespace - php

Amazon's MWS PHP client library is just a zip file without any namespace, Is there a way to use this library with Laravel application or with any application which uses composer for its dependency management.

Sure, just create your own library directory in your Laravel app. I usually keep mine just inside app directory and call it Libraries. Dump the source files inside a folder such as AmazonMWS.
.config.inc.php comes with an autoloader but it won't be used. Instead you could probably just open your composer.json in your Laravel project and tell it to autoload your new Library directory targeting the config. Ex:
"autoload-dev": {
"classmap": [
"app/Libraries/AmazonMWS/Client.php"
]
}
Make sure config.inc.php is accessible at the AmazonMWS root.
Then run composer dump-autoload to regenerate the autoloaders. If done properly then you should be able to instantiate any of the MWS classes without a namespace.
In your Controller, include the following use:
use \MarketplaceWebServiceProducts_Client;
Now you can call your service as expected:
$config = [...];
$service = new MarketplaceWebServiceProducts_Client(
AWS_ACCESS_KEY_ID,
AWS_SECRET_ACCESS_KEY,
APPLICATION_NAME,
APPLICATION_VERSION,
$config);
Or just omit use \MarketplaceWebServiceProducts_Client; and instantiate directly with namespace prefix, your choice.

Related

how to add a PHP library to TYPO3 extension without namespace?

I'm tyring to implement a custom TYPO3 extension to execute some php code. With my main class "hello world!" ist already working and i understand the use of namespaces.
But now I found a php Library that suits my needs. I pasted the lib folder in the "Classes" folder of my extension. But now I'm getting class not found errors because none of the lib classes have a namespace.
Unfortunately I couldn't find any tutorial/doc on how to add a library to a typo3 extension while dynamically adding a namespace to every class. I tried to override every class with a namespace but somehow this cant be the solution
here is a sample of my Main class that is working but as soon as I try to call "ServiceMailman" i get namespace error, well, because they have none
namespace Htwg\GiMailman;
require_once 'Service/ServiceMailman.php';
class GiMailman{
public function getMailinglists() {
$mm = new ServiceMailman('http://localhost', '', '');
}
}
I'm looking for a way to add a php library to the "Classes" folder without adding a namespace to every library class.
Update:
I installed the library on an externel path and added it to the composer.json in the classmap entry:
"autoload": {
"psr-4": {
"Htwg\\GiMailman\\": "Classes/"
},
"classmap": ["/opt/lampp/lib/php/Services"]
}
and it shows up in the autoload_classmap.php:
// autoload_classmap.php #generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
...
'Services_Mailman' => $baseDir . '/../../../../lib/php/Services/Mailman.php',
'Services_Mailman_Exception' => $baseDir . '/../../../../lib/php/Services/Mailman/Exception.php',
);
But when i try to class the class in my Main php class it still can't be found:
namespace Htwg\GiMailman;
//require_once 'Services/Mailman.php';
class GiMailman{
public function getMailinglists() {
$mm = new \Service_Mailman('http://localhost:8001/3.1', '', 'password');
return "getMailinglists";
}
}
Any PHP classes that do not use namespaces are in the top level namespace. So you can use them like:
$mm = new \ServiceMailman('http://localhost', '', '');
You should not add external libraries to you Classes directory. Classes in this directory are autoloaded with the correct namespace for your extension (Vendor/ExtensionName). As external libraries have a different, or in your case no, namespace, this will cause problems. Usually we put external libraries in Resources/Private/Php/LibraryName. You will then need to require or include the library.
If you're using composer it is however better not to include external libraries inside your extension, but let composer worry about it if possible. That way you don't have to worry about autoloading (so you don't need to require or include any files manually) and any dependencies for the external library are also automatically resolved. Either require the library in your global composer.json or, if you install the extension that requires it through composer, add it to the composer.json of the extension.
If you're running composer there are two ways:
The library is available on https://packagist.org/ => Require it in your composer.json file
The library needs to be copied into e.g. Library/ServiceMailman/. After that you set it into your composer.json in the autoload section "classmap", if no namespaces exists for this library. More: https://getcomposer.org/doc/04-schema.md#classmap (If the library has namespaces, it should be in autoload section "psr-4")
If you're not running composer and want to include it in your TYPO3 extension easily, there is a good tutorial: https://insight.helhum.io/post/148112375750/how-to-use-php-libraries-in-legacy-extensions

What steps it takes to add GitHub repo to Laravel application?

I would like to use following GitHub repo in my Laravel application:
https://github.com/khanamiryan/php-qrcode-detector-decoder
It doesn't have composer set up nor it can be found from Packagist. I tried to use regular php_require but it tells me "Class 'App\Http\Controllers\QrReader' not found".
Using php_require feels wrong anyways. What is the correct way to handle situation like this?
Create a new directory in your app root
mkdir third-party
cd third-party
Clone the repo
git clone https://github.com/khanamiryan/php-qrcode-detector-decoder
Edit your composer.json file and add it to the classmap:
"classmap": [
"database",
"third-party/php-qrcode-detector-decoder"
],
Update class maps:
composer dumpautoload
And you should see in your vendor/composer/autoload_classmap.php
'Zxing\\Binarizer' => $baseDir . '/third-party/php-qrcode-detector-decoder/lib/Binarizer.php',
'Zxing\\BinaryBitmap' => $baseDir . '/third-party/php-qrcode-detector-decoder/lib/BinaryBitmap.php',
...
Then you just have to use it:
use Zxing\Reader;
I think the major class is QrReader(). You can use this class as controller class but you need to extend the controller class and fix imports. You can import this class as third party class on your laravel controller too.
Do you need to use QrReader() class?
Then just put all the library files App\Libraries and the main class in App\classes. Or you can do in our own way too. But follow the following
1) Manage namespaces
2) import the class to your controller by using
use App\classes\QrReader
Finally, you will have access to all the methods defined in the imported class. But in you main class you need to correct the path and dependencies of libraries files.
You can try this tutorial too:
How to use external classes
You can read the discussion here (Nice)
Best way to import third party classes
Because this github project does not have a composer.json file, I don't think you can use it with composer.
However, you could branch the repo, make your own copy, and add a composer file to it. Then you'd be able to add it to your main project's composer.json file:
{
"repositories": [
{
"type": "git",
"url": "https://github.com/your-git-account/php-qrcode-detector-decoder"
}
],
"require": {
"your-git-account/php-qrcode-detector-decoder": "dev-master"
}
Hope this helps!
(Source https://getcomposer.org/doc/05-repositories.md#loading-a-package-from-a-vcs-repository)

Including my class in a Laravel 5 Project

I made a class in php with some helper methods that parse HTML files.
I'd like to use this class in my Laravel project, but I'm new to Laravel and it's not clear how to add a simple class to a Laravel 5 project.
Is this possible? Or do I need to go to all the trouble of creating a composer package for my class, hosting it somewhere, and then require it in my composer.json file. That seems like a lot of work for including a simple PHP class, and I'm hoping there's an easier way.
As it stands right now there's not a great/easy way to do this in Laravel 5 (possibly by design). The two approaches you can take are
Create a new class in the App namespace
By default Laravel 5.0 looks for App\ prefixed classes in the app/ folder, so something like this should work
#File: app/Helpers/Myclass.php
<?php
namespace App\Helpers;
class Myclass
{
}
and then create your class with
$object = new App\Helpers\Myclass;
This approach, however, relies on you creating classes in the App\ namespace, and there's some ambiguity around if the App\ namespace is owned by Laravel, or is owned by the developer of the application.
Create your own Namespace and Register as PSR-4 autoloader
A better, but more complicated, approach would be to create classes in your own namespace, and then tell Laravel about this namespace by registering a new PSR autoloader.
First, you'd create the class definition
#File: application-lib/Myclass.php
<?php
namespace Pulsestorm;
class Myclass
{
}
Notice we've created a new folder off the root folder to hold our classes named application-lib. You could name this folder anything you like, because in the next step, you're going to add a section to your composer.json file's autoloader section
#File: composer.json
"autoload": {
"classmap": [
"database"
],
"psr-4": {
"App\\": "app/",
"Pulsestorm\\": "application-lib/"
}
},
The section we've added is this
"Pulsestorm\\": "application-lib/"
The key to the object (Pulsestorm\) is your namespace. The value (application-lib) is the folder where composer should look for class definition files with the specified namespace.
Once you've added this to composer.json, you'll need to tell Composer to regenerate it's autoload cache files with the dumpautoload command
$ composer dumpautoload
Generating autoload files
After doing the above, you should be able to instantiate your class with
$object = new Pulsestorm\Myclass;
The "real" right way to do this would be to create a generic composer package for your helper class, and then require that composer package into your laravel project. That may, however, be more work than you care to take on for a simple library helper.
If your class is generic enough to use it in other projects, the best way is to release it as a package.
Here's how you create packages with Laravel 5: http://laravel.com/docs/5.0/packages

How to use composer with my Yii application

I have developed web app using Yii 1.1.3, and I am very much new with Core php, can anyone give me some detail that how I can use composer with Yii app.
I have used Bootstrap, RESTFull Yii, yii-user and some other extensions.
Your help will be appreciated.
I am assuming that you know how to create your composer.json and so on?
If so then you use Composer with Yii as you would with any other application.
You just have to modify Yii's classMap to make sure it picks up the loaded composer requirements.
Edit your index.php (and probably also your yiic.php in the protected folder if you have one) and load the Composer autoloader and pass the map onto Yii:
$loader = require(__DIR__ . '/../vendor/autoload.php');
Yii::$classMap = $loader->getClassMap();
It is possible you have to modify the include path of course (my example assumes you have a public_html-folder.
If you also want to add your application classes to the map, so that you don't have to add aliases all the time:
"autoload": {
"classmap": [
"protected/"
],
Don't forget to run composer dump-autoload after you add classes then or it won't find them.

Initializing PHP classes in the Web server/browser context

I am writing a script that talks to a database, and transforms the content and puts it into an XML file.
I am trying to utilize best practices, and as part of library re-use, I have found the following classes to be beneficial:
Symfony components:
Yaml : for parsing and loading database info.,
DI Container : for injecting dependencies
Others:
PHPExcel, the amazing excel library
Doctrine DBAL to get an easy PDO wrapper
Mockery for obtaining easy mocks during testing
My core business class, ExcelExporter, will need all these files functioning harmoniously with each other. I also need a place where I can initialize by own class, and inject these dependencies in.
I am confused as to where to do this. If I were building a web page, I'd say I'd put the initialization & configuration process inside index.php and finally call ExcelExporter to do its thing when a user loads index.php in the browser. Is there a better way for this bootstrapping process? What's the most common approach?
You should totaly use Composer for this task.
It will handle vendors and autoloading for you.
Here is a quick setup:
curl -s https://getcomposer.org/installer | php
php composer.phar init
php composer.phar require symfony/dom-crawler:dev-master doctrine/dbal:2.4.x-dev
php composer.phar install
You will have a vendor directory with your dependencies. Then the bootstrap file is simply initializing what you have to do. Autoloading is handled by Composer:
// Then add this on top of your bootstrap file
require 'vendor/autoload.php';
I assume you are not using any framework. Only using symphony components. If you were using a framework it would have been done by the framework. But for vanila framework you need
A single entry point for the application (say index.php)
A bootstrap.php file that loads initial classes and external resources. Many framework uses this bootstrap files. Just look at the file structure you'll find them. The name might not be bootstrap.php.
Once your application is loaded use a autoloader to load on-demand classes. This autoloader should be initialized on bootstrap.
function my_autoloader($class) {
include 'classes/' . $class . '.class.php';
}
spl_autoload_register('my_autoloader');
Based on Damien's answer, I found that Composer offers the easiest method to do this.
Now, my ExportExcel class lives in the src/ directory. The structure of my directory is:
src/
vendor/
index.php
bootstrap.php
composer.json
Within composer.json, I also asked it to load my classes for me:
{
"name": "adityamenon/excel_export",
"description": "Export data into a custom excel sheet format",
"require": {
"symfony/dependency-injection": "2.2.x-dev",
"symfony/yaml": "2.1.x-dev",
"doctrine/dbal": "2.4.x-dev",
"mockery/mockery": "dev-master",
"CodePlex/PHPExcel": "1.7.8"
},
"autoload": {
"psr-0": {"ExportExcel": "src/"}
},
"authors": [
{
"name": "aditya menon",
"email": "adityamenon90#gmail.com"
}
]
}
I just need to run $ composer install for all the dependencies to appear magically within vendor/.
PSR-0 is easy to follow. I just made a file called ExportExcel.php with a namespaced class inside called ExportExcel:
namespace ExportExcel;
class ExportExcel {
public function __construct(\ExportExcel\DbConvenience $db_convenience)
{
$this->DbConvenience = $db_convenience;
}
public function writeExcelFile()
{
// ...do stuff here
}
}
Finally, here's bootstrap.php, which takes care of autoloading stuff I need as well as injecting dependencies:
<?php
// composer autoloads dependencies
// also configured to load from src/
$loader = require('vendor/autoload.php');
// load configuration (only db right now)
use Symfony\Component\Yaml\Yaml;
$yaml_config = Yaml::parse('config.yml');
// load the database
$db_config = new Doctrine\DBAL\Configuration();
$conn = Doctrine\DBAL\DriverManager::getConnection($yaml_config, $db_config);
// load the convenience classes
$DbConvenience = new ExportExcel\DbConvenience($conn);
// use the dependency injector to load the exporter with DB
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
$sc = new ContainerBuilder();
$sc->setParameter('dbconvenience.class', 'ExportExcel\DbConvenience');
$sc->setParameter('exportexcel.class', 'ExportExcel\ExportExcel');
$sc
->register('dbconvenience', '%dbconvenience.class%')
->addArgument($conn);
$sc
->register('exportexcel', '%exportexcel.class%')
->addArgument(new Reference('dbconvenience'));
// here's the most important class of 'em all
$ExportExcel = $sc->get('exportexcel');
Finally in index.php, the first line is require('bootstrap.php');, and off I go. I can make calls to functions inside ExportExcel with $ExportExcel->doStuff();
Please feel free to add comments and shorten/improve this answer. Solving this puzzle was a bit hard and took a bit of reading around but everything is so clear in hindsight.

Categories