I had a problem importing libraries into the Laravel project. I want to use the image_QRCode-0.1.3 library coded in php used in Project Laravel.
https://pear.php.net/package/Image_QRCode/download
but when I use the require command in class QRCodeController
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
require_once "../../../Library/Image_QRCode-0.1.3/Image_QRCode-0.1.3/Image/QRCode.php";
class QRCodeController extends Controller {
public function genQRCode()
{
$QR = new \Image_QRCode();
$option = array(
'module_size' => 4,
'image_type' => 'png',
'output_type' => 'display',
'error_correct' => 'H',
);
$qrcode = $QR->makeCode(htmlspecialchars("https://blog.shnr.net/?p=526", ENT_QUOTES), $option);
}
}
The program did not run and reported an error.
Please help me, thanks you so much !
To use external classes or any other PHP library into your Laravel project, you have to do the following steps:
1. Create a folder somewhere in your Laravel app that will contain the PHP files you're going to use:
For example you have a custom class, create a folder in the directory app/libraries. Inside app/libraries, paste the PHP files you'll be using (the library files you've downloaded).
2. In your composer.json file, add the folder/directory into your autoload classmap:
"autoload": {
"classmap": [
"app/commands",
"app/controllers",
"app/models",
"app/libraries", <------------------ YOUR CUSTOM DIRECTORY
"app/database/migrations",
"app/database/seeds",
]
}
3. Once you're done, just run composer dump-autoload and you should be able to call your class as follows:
Assuming your class name is SomeClass.php and it's inside the app/libraries directory and you're properly namespaced the class you've just copied over, you can now use SomeClass.php anywhere you need it.
$class = new \some_class_namespace\SomeClass();
You can also give it an alias in your config/app.php file:
/*
|--------------------------------------------------------------------------
| Class Aliases
|--------------------------------------------------------------------------
|
| This array of class aliases will be registered when this application
| is started. However, feel free to register as many as you wish as
| the aliases are "lazy" loaded so they don't hinder performance.
|
*/
'aliases' => [
....
'SomeAlias' => 'app\libraries\SomeClass',
....
],
After then you can instantiate the class from anywhere in your application just like any other classes:
$class = new SomeAlias();
Related
I apologize if this is duplicate; please guide me to the right directions.
I know we can create class aliases in Laravel from /config/app.php. However trying to create namespace aliases using the same method fails.
/*
|--------------------------------------------------------------------------
| Class Aliases
|--------------------------------------------------------------------------
|
| This array of class aliases will be registered when this application
| is started. However, feel free to register as many as you wish as
| the aliases are "lazy" loaded so they don't hinder performance.
|
*/
'aliases' => [
...
/*
* My custom namespace aliases
*/
'MyNamespace' => 'App\Models\MyNamespace',
],
Testing this in thinker returns the following results:
>> new \MyNamespace\MyClass();
PHP Fatal error: Class 'MyNamespace/MyClass' not found in Psy Shell code on line 1
Do you know a way to create namespace alias in Laravel?
Make your code PSR-4 compatible and put it in composer.json
"autoload": {
"psr-4": {
"MyNamespace\\": "src/MyNameSpace",
}
},
Then run composer dumpautoload. So long as you stick to the convention of subfolders being namespaces, your classes will autoload.
src/MyNamespace/SomeClass.php would have namespace MyNamespace; and class SomeClass.
src/MyNamespace/Something/SomethingElse.php would have namespace MyNamespace\Something; and class SomethingElse.
I am trying to create a hook extension for Contao.
But Contao doesn't seem to be able to load my class from the namespace, which handles the hook.
This is my file structure:
I have tried changing names and added ".php" to the class, looked up tutorials, but I can't find what I am doing wrong. I am fairly inexperienced in this topic, so I might be missing something obvious.
autoload.php
ClassLoader::addNamespaces(array
(
'Memberlevels',
));
gister PSR-0 namespace
*/
if (class_exists('NamespaceClassLoader')) {
NamespaceClassLoader::add('Memberlevels', 'system/modules/memberlevels/classes');
}
if (class_exists('NamespaceClassLoader')) {
NamespaceClassLoader::addClassMap(array
(
'Memberlevels' => 'system/modules/memberlevels/classes/myClass.php'
));
}
/*
* Register the templates
*/
TemplateLoader::addFiles([
'cookiebar' => 'system/modules/memberlevels/templates',
]);
config.php
$GLOBALS['TL_HOOKS']['outputBackendTemplate'][] = array('Memberlevels\myClass', 'myOutputBackendTemplate');
I get the error message:
Attempted to load class "myClass" from namespace "Memberlevels". Did you forget a "use" statement for another namespace?
You are still using the old Contao 3 way of loading classes. In Contao 4, you should use the autoloading feature of composer. The default composer.json of the most recent Contao versions already include autoloading directives for the src/ folder of your Contao installation:
"autoload": {
"psr-4": {
"App\\": "src/"
}
},
Using that, this is how you create & register a hook in a Contao 4.4 compatible way:
// src/EventListener/OutputBackendTemplateListener.php
namespace App\EventListener;
class OutputBackendTemplateListener
{
public function onOutputBackendTemplate(string $buffer, string $template): string
{
// Do something
return $buffer;
}
}
// app/Resources/contao/config/config.php
$GLOBALS['TL_HOOKS']['outputBackendTemplate'][] = [\App\EventListener\OutputBackendTemplateListener::class, 'onOutputBackendTemplate'];
Starting with Contao 4.8 you can also use annotations to register a hook, eliminating the need to register the hook in app/Resources/contao/config/config.php.
I have made the below composer view for my app. I've placed it in separate file at app/composers.php.
<?php
// namespace App\Modules\Manager\Composer;
// use Illuminate\Support\Facades\View as View ;
/*
|--------------------------------------------------------------------------
| Composers
|--------------------------------------------------------------------------
|
|
*/
View::composer('tshop.includes.header', function($view)
{
$categories = Categories::getWithChilds();
$view->withCategories( $categories);
});
My composer.php file is
"autoload": {
"classmap": [
"app/commands",
"app/controllers",
"app/models",
"app/database/migrations",
"app/database/seeds",
"app/tests/TestCase.php"
],
"files": [
"app/composers.php"
]
},
Unfortunately I get this error
Fatal error: Class 'View' not found in C:\xampp\htdocs\eshop\app\composers.php on line 15
Update
I also tried this. I wrote inside app/start/global.php
require app_path().'/composers.php';
and
use Illuminate\Support\Facades\View as View ;
at app/composers.php, getting this error
Fatal error: Call to a member function composer() on a non-object in
C:\xampp\htdocs\eshop\vendor\laravel\framework\src\Illuminate\Support\Facades\Facade.php
on line 211
I don't think your app/composers.php should be autoloaded within composer. Composer's responsibility is to resolve packages and install them for you, which has nothing to do with your application logic, let alone your application's views.
At the point of running composer, it would not have any knowledge of your Laravel app. That means your Laravel facades like View, Input, DB, Auth, etc. are not loaded yet. Thus your code throws Call to a member function composer() on a non-object.
Approach 1:
Laravel does not strictly specify where you put your laravel view composers, so requiring it by adding:
require app_path() . '/composers.php';
at the bottom of app/start/global.php like edi9999 said would be fine.
Don't forget to remove in this case:
"files": [
"app/composers.php"
]
Approach 2: there is a way to autoload your view composers in composer.json!
From example in Laravel docs on view composers, you can do something like...
app/viewcomposers/HeaderViewComposer.php:
class HeaderViewComposer
{
public function compose($view)
{
$categories = Categories::getWithChilds();
$view->withCategories( $categories);
}
}
composer.json:
"classmap": [
...
"app/viewcomposers"
]
app/composers.php:
View::composer('tshop.includes.header', 'HeaderViewComposer');
bottom of app/start/global.php:
require app_path() . '/composers.php';
Unfortunately you still need to add the line above to app/start/global.php so Laravel knows what view composers are defined.
Approach 3: Do autoload class in composer.json + register a custom ServiceProvider
Learning from Using View Composers in Laravel 4 by Philip Brown, we could also add our own custom service provider and not having to edit our app/start/global.php file.
app/viewcomposers/HeaderViewComposer.php:
<?php namespace App\Modules\Manager\Composer;
class HeaderViewComposer
{
public function compose($view)
{
$categories = Categories::getWithChilds();
$view->withCategories( $categories);
}
}
composer.json:
"classmap": [
...
"app/viewcomposers"
]
app/viewcomposers/ViewComposerServiceProvider.php:
<?php namespace App\Modules\Manager\Composer;
use Illuminate\Support\ServiceProvider;
class ViewComposerServiceProvider extends ServiceProvider {
public function register()
{
$this->app->view->composer('tshop.includes.header', 'App\Modules\Manager\Composer\HeaderViewComposer');
}
}
app/config/app.php:
'providers' => array(
...
'App\Modules\Manager\Composer\ViewComposerServiceProvider',
),
As #TheShiftExchange found out, one problem is that you used the "files" options.
As you can see in composer's code, the autoload section corresponds to this:
class ComposerAutoloaderInitf8489489s7f894ds98f47d
{
....
....
public static function getLoader()
{
....
....
$includeFiles = require __DIR__ . '/autoload_files.php';
foreach ($includeFiles as $file) {
composerRequiref4s65f4556sd4f564fsdfd($file);
}
return $loader;
}
}
function composerRequire5894s89f4sd98498489f7b37d($file)
{
require $file;
}
So the files array you specify is required during composer's autoload process, way before the View Facade is loaded.
The providers to the facades are loaded in vendor/laravel/framework/illuminate/foundation/start.php
/*
|--------------------------------------------------------------------------
| Register The Core Service Providers
|--------------------------------------------------------------------------
|
| The Illuminate core service providers register all of the core pieces
| of the Illuminate framework including session, caching, encryption
| and more. It's simply a convenient wrapper for the registration.
|
*/
$providers = $config['providers'];
$app->getProviderRepository()->load($app, $providers);
Actually, the problem with classmaps is an other one: It is that they is no class in your file, so the file will never be loaded so it doesn't do anything.
To make it work, you should add into app/start/global.php at the end of the file:
Instead of
require app_path() . '/filters.php';
Write
require app_path() . '/composers.php';
require app_path() . '/filters.php';
That's the best way I can think of to include files at each load of your application that are not classes.
Okay so I have an project folder inside my Laravel app. named TLGD (the name if my site). Inside i created a form validation helper which is being used to take away unnecessary code form the controller.
here is the folder structure:
TGLD\Validation\Forms
and inside here I have my form helper classes
now in the controller just to test it out I was calling the classes by the use methd from php like so:
use TGLD\Validation\Forms\Login;
login being the class for the login validation
now thus works great so I tried to autoload the TGLD folder so I don't need to add the use line in every controller. Here is my composer.json file
"autoload": {
"classmap": [
"app/commands",
"app/controllers",
"app/models",
"app/database/migrations",
"app/database/seeds",
"app/tests/TestCase.php"
],
"psr-4": {
"TGLD\\": "app/TGLD"
}
},
but when I autoload it it gives me the error that my login class doesn't exist which means the autoloader is not working. Is there a syntax error or am I missing something? I ran
composer dump-autoload -o
well any advice is helpful thank you in advance
What you want to do cannot be done.
You have to use the complete namespace somewhere to identify the class you want to use. You have several options to do this
Using the fully qualified name of the class with namespace like this: new \TGLD\Validation\Forms\Login().
Using a use clause that imports the named class into the current namespace for this file with use TGLD\Validation\Forms\Login; ... new Login();
Using a part of the namespace in the use, and use the rest in the class name: use TGLD\Validation\Forms; ... new Forms\Login();
After you have chosen the class name in one way or the other, PHP knows which class it needs, and then triggers the autoloading if the class is still unknown to PHP.
So you cannot affect the naming of classes with autoloading.
I'm trying to write my own validation class in Laravel 4. To do this, I created a new directory called app/validators. I then added this directory to the composer.json classmap and ran composer update, like so:
"classmap": [
"app/commands",
"app/controllers",
"app/models",
"app/validators", <- added here
"app/database/migrations",
"app/database/seeds",
"app/tests/TestCase.php"
]
My validation class looks like this:
class LinkValidation extends Illuminate\Validation\Validator {
{
public function validateHost($field, $value, $params)
{
return $value == 'test';
}
}
and in my controller, I'm trying to extend the validator like so:
Validator::extend('awesome', 'LinkValidation#supportedHost');
However, I'm getting this error when loading a page:
{
"error":{
"type":"ReflectionException",
"message":"Class LinkValidation does not exist",
"file":"C:\\xampp\\htdocs\\laravel\\vendor\\laravel\\framework\\src\\Illuminate\\Container\\Container.php",
"line":301
}
}
Any ideas why Laravel won't load the class? I thought it'd do it automatically if added to composer's classmap.
Not sure why it isn't working, but I think you should try adding it in app/start/global.php.
/*
|--------------------------------------------------------------------------
| Register The Laravel Class Loader
|--------------------------------------------------------------------------
|
| In addition to using Composer, you may use the Laravel class loader to
| load your controllers and models. This is useful for keeping all of
| your classes in the "global" namespace without Composer updating.
|
*/
ClassLoader::addDirectories(array(
app_path().'/commands',
app_path().'/controllers',
app_path().'/models',
app_path().'/database/seeds',
app_path().'/validators',
));
Always do composer dumpautoload after create new class object.