Loading a composer class in laravel - php

I'm in the process of trying to make a laravel compatible composer/packagist package. I'm using Laravel 5.5.
I've created a package : floor9design/machine-identifier. Composer downloads this to vendors/floor9design fine, but despite reading/googling how to do this, I'm unsure of how to include this in my laravel projects.
PHP Storm is correctly picking up the class, auto-completing as expecting.
I have not modified any files so far. If I add the following to a controller:
use Floor9design\MachineIdentifier\MachineIdentifier;
(alongside some class usage on the page).
PHP storm autocompletes this (as it does with other classes validly called).
When I try to load this, the following error comes:
Class 'Floor9design\MachineIdentifier\MachineIdentifier' not found
I've had a look round plenty of tutorials, and this final step seems to be missing from a lot of information.
I realise there are three approaches:
Firstly:
Direct include_once, which while working, is not the normal approach
Secondly:
Pre-laravel 5.5 approach (add something to app.php)
Thirdly
Laravel 5.5 approach and up, autodetection of something.
I've deliberately said something as the documentation seems to speak about ServiceProviders, and I simply don't get how they work.
Let me rephrase this into a question and a follow up question:
Question: apart from include_once, how do I load the MachineIdentifer class from floor9design/machine-identifier in Laravel.
Question 2: If the answer is via a service provider, can you simply explain how they relate to one another.
Thanks
Answer (as accepted below)
On the composer repo I was incorrectly specifying the PSR4 namespace, which is now corrected to:
"autoload": {
"psr-4": {
"Floor9design\\MachineIdentifier\\": "src"
}
}
The previous namespace had a -, which is an illegal character. Many thanks to lawrence-cherone.

Your PSR4 is wrong in the package
floor9design\\machine-identifier\\": "src"
Will cause the composer/autoload_psr4.php to map to:
'floor9design\\machine-identifier\\' => array($vendorDir . '/floor9design/machine-identifier/src'),
Which is not a valid class namespace.
You should change the PSR4 to match your class namespace:
Floor9design\\MachineIdentifier\\": "src"
Once you fix that you will be able to use it like normal from anywhere in your project.

Related

Laravel "Unable to locate a class or view for component" in production environment

I develop on a Mac locally. Latest version of Big Sur.
Today I went to deploy my app to production via an Ubuntu server through Forge, and got greeted with an error I've never seen before, and can't find an answer to online. I can see MANY people complaining about it, but all anyone has said on other answers is link to issues that don't have solutions or even explanations really, so that's why I'm asking a new question.
The exact error is this;
Unable to locate a class or view for component [layouts.base]. (View: /home/forge/default/releases/20201204084441/resources/views/layouts/app.blade.php)
In my app I have;
app\View\Components\Layouts\App.php
which looks like this;
<?php
namespace App\View\Components\Layouts;
use Illuminate\View\Component;
class App extends Component
{
public function render()
{
return view('layouts.app');
}
}
Then I also have;
resources\views\layouts\app.blade.php
<x-layouts.base>
<!-- contents -->
</x-layouts.base>
(Also pretty much the same for base)
Works flawlessly on Mac. As soon as I deploy it on Ubuntu, I get the error above that it is "unable to locate a class or view" with those names.
Can someone please instruct me on how I can go about fixing this, since so far I have absolutely no idea and despite knowing that case sensitivity is probably the issue as per the other questions about this, I cannot find any actual solution or way to resolve this.
I had the same problem. Thanks to your question, I could find out how to solve it :D
In my case, I had created a component inside another folder, for better organization sake:
$ php artisan make:component Tutorial/channelName/Alert
So it created the view component inside the following directory:
views/components/tutorial/channel-name/alert.blade.php
Now, to call your component you do it this way:
<x-tutorial.channelName.alert />
That's pretty much it.
I was facing the same issue and I fixed it by cross-checking my folder name.
Please note that the folder name should be components and not component.
Refer the screenshot for a better idea.
Example:
In case you are following the convention, one more thing is that if you have a file at
views/components/admin/side-menu/side.blade.php
You can call your Component as:
<x-admin.side-menu.side></x-admin.side-menu.side>
Explained:
The x- used in the blade syntax basically tells that you are selecting folder or file from the Components folder.
The . (dot) used is for every directory you dig to the blade file you want to use.
Well, I had the same problem but I realized that the error was the class name of the component. I didn't capitalize the class name and when I did capitalize the class name I stopped getting that error and my project worked well.
Please try capitalizing the class name that matches the component in the error message.
In my Case, I didn't provide the namespace in the Component, it solved after providing namespace.
when I was a beginner I got the same error But in my case, there is all ok but there is a small syntax error <x- card /> there is a gap between card and dash which is not correct so there should be no space between dash and card <x-card /> so try once maybe this is your problem.
I had the same problem - solution
was to change:
<x-forms.inputradio>
to:
<x-forms.inputRadio>
just letter size..
The issue for the mentioned problem is case sensitive,
for local looks like its case insensitive reasons its works for local perfect but breaks on serve.
if you have create new component inside any new folder
i.e
$ php artisan make:component Widgets/CustomAlert
it will create two files, class and blade file for the component.
class file
app\Views\Components\\CustomAlert.php
blade file
resources\views\components\widgets.custom-alert.blade.php
you can render component with either class or with blade file.
for class make sure folder, class name in case sensitive
ie.
<x-Widgets.CustomAlert />
to render blade file it should be
<x-widgets.custom-alert />
Note
if you have manually relocate the file, make sure your namespace in class file, filename and the component call syntax should be match(with case sensitive)
examples are just for reference try to compare syntax and names with your files,folder.
I hope it will help :)
In my case, I had created a class AppLogo and I had the blade generated as app-logo.blade.php.
However, in my view files, I referenced the component as x-applogo and this worked locally, but in production (a live hosting server), I got this error.
SOLUTION:
I changed all occurrences of x-applogo in my blade/view files to x-app-logo.
This worked both in development and in production.
Hope this helps someone out there.
This happens at server. try not to make components inside folder..
i had the same issue at server but did not get any solution,
the only solution worked is to keep your components outside any sub folder

Laravel cannot find a Controller Method (does not exist)

I'm trying to implement a new method in a BoController called "deleteBooking", the method is defined:
public function deleteBooking($id){
$booking = Reservation::find($id);
if($booking && $booking->delete()){
try {
$email = Mail::to($booking->user_email)->send(new Cancel($booking));
} catch(\Exception $e){
Log::error($e->getMessage());
}
return redirect('admin/manager/home')->with('message','Réservation annulée!');
}
return redirect('admin/manager/home')->with('message','Réservation non annulée!');
}
But laravel at the endpoint says:
(1/1) BadMethodCallException
Method [deleteBooking] does not exist.
Other methods from the same class are linked to endpoints too, and work well.
Do you have any ideas please? Thank you.
I got it fixed, I've found another file called BoController, in another folder somehow and it was conflicting with the App\Http\Controllers one.
Thank you.
It's most likely that you have declared that function for some other request type other than the one you're trying to make. For example you put Route::post('some-method', 'BoController#deleteBooking'); but you need to put either Route::get(...) or Route::put(...) or Route::delete(...).
If it isn't that problem, then you probably misspelled it.
I have faced similar issue. Then I have figured out a issue pointed in composer install log, with following instance of log line:
Class App\Http\Controllers\BlogController located in ./app/Http/Controllers/BlogControllerOld.php does not comply with psr-4 autoloading standard. Skipping.
Based on that I have found that one of the file renamed with Old suffix was creating conflict with the main file. So here I have to chhoseone of the following solutions:
To delete the file created for backup.
Or just rename the class in duplicated file to BlogControllerOld.
So its a good idea to check for issues with composer install
It will highlight the conflicts that can be fixed using one of the method above.
Once fixed using specified methods above issue composer install to apply the fix and regenerate autoloader.

Drupal 7 xautoload composer

So I have the Paypal REST API installed ( https://github.com/paypal/rest-api-sdk-php ) with Composer in my_drupal_module/lib/Drupal/ and now I want to use the namespaces in a function in my module. I understood that I need something like xautoload ( https://drupal.org/project/xautoload ) to do that so I tried something like:
$payer = new \Drupal\vendor\PayPal\Api\Payer;
with and without the first slash, and with and without parentheses at the end but it didn't work. I added:
require DIR . '/lib/Drupal/vendor/autoload.php';
but still nothing so I commented it. Meanwhile I found this: https://drupal.org/node/1976206 that explains this issue but it is unclear to me what exactly to write in hook_xautoload() or direct registration for the setup that I have. Can someone please help?
Nevermind. I solved it. Thanks to proloy03 who gave me the idea: https://drupal.org/node/2096621
You don't need xautoload to load the classes and namespace just implement hook_init to require it like so:
function my_module_init() {
require __DIR__ . '/vendor/autoload.php';
}
and then in your function write:
$payer = new PayPal\Api\Payer();
and it all works.
With xautload you can do something like this...
In mymodule.module
function mymodule_libraries_info() {
'paypal' => array(
'name' => 'PayPal SDK',
'xautoload' => function($adapter) {
$adapter->composerJson('composer.json');
}
}
Declaring this allow you to use the namespace. Like
use PayPal\Api\Amount;
Check xautoload.api.php
Your assumption that you need XAutoload to use the Paypal API installed by Composer is wrong.
The only thing you need to make any code installed by Composer available is to include the Composer autoloader in your code execution path when you need any of the provided classes. The easiest form of this is to simply require the Composer autoloader in the very first index.php (or whatever Drupal uses) file that answers every request (possibly instantiating more Drupal classes, modules and stuff).
Once the code execution comes to your own code, the autoloading allows your code to include all the classes you included with Composer.
How to use the code? Don't invent your own namespace for the existing code, it will not work. "\Drupal\vendor\PayPal\Api\Payer" sounds pretty wrong to me, I suspect the correct namespace is "\PayPal\Api\Payer". And yes, that file does indeed exist. So you have to use that.
If it still does not work, complaining the class could not be loaded, then the Composer autoloader file is not included in your scripts code path.

Developing/using a custom Resource Plugin in Zend Framework

We have used Zend_Log, which is configured in application.ini differently for different circumstances. We initialize it/get it in the bootstrap and store it in the registry:
$r = $this->getPluginResource('log');
$logger = $r->getLog();
But we've subclassed Zend_Log (say, Our_Log) to add customized features, and want to get it the same way. So then we have to make a new Resource Plugin. That seems quite easy - just copy Application/Resource/Log.php, rename the file to Ourlog.php, rename the class to class Zend_Application_Resource_Ourlog. For now, let's not worry about "Our_Log", the class -- just use the new Resource Plugin to get a Zend_Log, to reduce the variables.
So then, our new code in the bootstrap is:
$r = $this->getPluginResource('ourlog');
$logger = $r->getLog();
but of course this doesn't work, error applying method to non-object "r". According to the documentation,
"As long as you register the prefix path for this resource plugin, you
can then use it in your application."
but how do you register a prefix path? That would have been helpful. But that shouldn't matter, I used the same prefix path as the default, and I know the file is being read because I "require" it.
Anyway, any guidance on what simple step I'm missing would be greatly appreciated.
Thanks for the pointers -- so close, so close (I think). I thought I was getting it...
Okay, so I renamed the class Xyz_Resource_Xyzlog, I put it in library/Xyz/Resource/Xyzlog.php
Then, because I don't love ini files, in the bootstrap I put:
$loader=$this->getPluginLoader();
$loader->addPrefixPath('Xyz_Resource','Xyz/Resource/');
$r = $this->getPluginResource('xyzlog');
if (!is_object($r)) die ('Not an object!!');
Sudden Death. So, okay, do the ini:
pluginPaths.Xyz_Resource='Xyz/Resource/'
The same. No help. I believed that the basepaths of the plugin paths would include the PHP "include" paths. Am I mistaken in that? Any other ideas? I'll happily write up what finally works for me to help some other poor soul in this circumstance. Something to do with Name Spaces, maybe?
Plugin classes are resolved using the plugin loader, which works slightly differently to the autoloader; so just requiring the class in doesn't help you here. Instead, add this to your application.ini:
pluginPaths.Application_Resource = "Application/Resource"
you should then be able to use the class as normal. Since your path above will be checked before the default Zend one, you can also name your class 'Log' and still extend the Logger resource to override the standard functionality.

What are the possible reasons for App::import() not working?

I'm trying to implement a simple way to manage static pages in CakePhp, as described in this article.
The problem I'm facing is that App::import() doesn't seem to import the required class in the routes.php file.
The code is the following:
App::import('Model','StaticPage');
$page = new StaticPage();
$slugs = $page->find('list', array(
'fields' => array('StaticPage.slug'),
'order' => 'StaticPage.slug DESC'
));
I'm getting the error: Fatal error: Class 'StaticPage' not found in ...
This class is present in the models folder (models/StaticPage.php).
I just started CakePhp a few weeks ago and I guess I'm missing a simple thing here...
I'm using CakePhp 1.3 and Php 5.2.42.
I think the reason it doesn't work is because you don't follow CakePHP's naming conventions for file names: file names are lowercase and underscored. So renaming your file to static_page.php should fix the problem.
Having taken a quick look at the article you reference, your snippet doesn't match up. You're importing the ClassRegistry class (which doesn't need to be imported) and then trying to instantiate a StaticPage. I'd recommend removing the AppImport reference all together and using ClassRegistry:
$page = ClassRegistry::init( 'StaticPage' );
You don't need the AppImport line because ClassRegistry::init() both loads the model and instantiates the object.
The other (potential) problem I see is that your model file name doesn't follow convention. It should be models/static_page.php. Cake's inflection may not be handling the deviation from the norm.
Like the error says: You are missing the Class StaticPage. Are you sure that you have this file? If you do, sure that it's in right place, has the right filename so the autoloader can find it?.

Categories