I use in my Laravel application `MongoDB as a database driver using composer package:
https://github.com/jenssegers/laravel-mongodb
By default, Laravel models extend Illuminate\Database\Eloquent\Model class.
But when I use MongoDB then my models must extend the Jenssegers\Mongodb\Eloquent\Model` class instead of default Laravel class.
How I can now replace Laravel Sanctum default extending model class Laravel\Sanctum\PersonalAccessToken to Jenssegers\Mongodb\Eloquent\Model.
Example
<?php
namespace Laravel\Sanctum;
// use Illuminate\Database\Eloquent\Model; // Replace this class
use Jenssegers\Mongodb\Eloquent\Model; // To this class
use Laravel\Sanctum\Contracts\HasAbilities;
class PersonalAccessToken extends Model implements HasAbilities
{
// sanctum model
}
Now I can do this inside the vendor folder but I think it's the incorrect way. How to solve this problem correctly?
What you need to do is create a custom PersonalAccessToken (you can just copy the original one "Laravel\Sanctum\PersonalAccessToken.php")
then just change
use Illuminate\Database\Eloquent\Model
for
use Jenssegers\Mongodb\Eloquent\Model
and finally in \Providers\AuthServiceProvider
you must add in the boot function
public function boot()
{
$this->registerPolicies();
Sanctum::usePersonalAccessTokenModel(PersonalAccessToken::class);
}
in my search I found this package:
Laravel-Sanctum-Mongo
It can serve you, basically it is just installing
Or
Step 1:
Copy this Model \Laravel\Sanctum\PersonalAccessToken and paste in your custom model \App\Models\Sanctum\PersonalAccessToken
Step 2:
Find the use Illuminate\Database\Eloquent\Model; and replace with use Jenssegers\Mongodb\Eloquent\Model;
Step 3:
In the App\Providers\AppServiceProvider add this:
// Loader Alias
$loader = AliasLoader::getInstance();
// SANCTUM CUSTOM PERSONAL-ACCESS-TOKEN
$loader->alias(\Laravel\Sanctum\PersonalAccessToken::class, \App\Models\Sanctum\PersonalAccessToken::class);
and Ready, work for me
I had also to add in the vendor folder NewAccessToken file this:
use App\Models\Sanctum\PersonalAccessToken;
As per this issue sanctum only support extending the default model and are probably not going to consider adding an interface.
But we can trick autoloader into loading our class instead of the default one.
Here is how to do it:
Step 1: Copy the /vendor/laravel/sanctum/src/PersonalAccessToken.php file to /app/overrides/PersonalAccessToken.php
Step 2: Edit the /app/overrides/PersonalAccessToken.php and replace use Illuminate\Database\Eloquent\Model; with use Jenssegers\Mongodb\Eloquent\Model;
Step 3: Edit your composer.json file and edit the autoload section to look like the following:
"autoload": {
"exclude-from-classmap": ["vendor\\laravel\\sanctum\\src\\PersonalAccessToken.php"],
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/",
"Laravel\\Sanctum\\": "app/overrides/"
}
},
Step 4: run composer dump-autoload
This fixed my issue in the windows machine but the solution might not work for different OS because I've not tried them all. (Please comment your os name if this worked in your os)
Credits to https://github.com/laravel/sanctum/issues/263
Related
so when using the new model factories class introduced in laravel 8.x, ive this weird issue saying that laravel cannot find the factory that corresponds to the model. i get this error
PHP Error: Class 'Database/Factories/BusinessUserFactory' not found in .....
tho ive followed the laravel docs, ive no idea whats going on
Here is the BusinessUser class
<?php
namespace App;
use Database\Factories\BusinessUserFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class BusinessUser extends Model
{
use HasFactory;
}
and the factory
<?php
namespace Database\Factories;
use App\BusinessUser;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
class BusinessUserFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* #var string
*/
protected $model = BusinessUser::class;
/**
* Define the model's default state.
*
* #return array
*/
public function definition()
{
return [
'name' => "dsfsf"
];
}
}
any ideas or leads is greatly appreciated.
If you upgraded to 8 from a previous version you are probably missing the autoload directive for the Database\Factories namespace in composer.json:
"autoload": {
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/"
}
},
You can also remove the classmap part, since it is no longer needed.
Run composer dump after making these changes.
Laravel 8.x Docs - Upgrade Guide - Database - Seeder and Factory Namespace
Apparently you have to respect the folder structure as well. For example, if you have the User Model in the following path: app\Models\Users\User, then the respective factory should be located in database\factories\Users\UserFactory.
I'm in the process of migrating from laravel 7 to 8.
After banging my head against the wall for a while and looking at the source code, I saw that you can optionally override what factory class gets called for a model using the newFactory method on the model.
I also then noticed that it IS in the documentation (https://laravel.com/docs/8.x/database-testing#creating-models) - I just didn't understand what it meant the first time I read it. Now I do.
I solved this by the following:
<?php
namespace My\Fancy\Models;
use Database\Factories\SomeFancyFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class SomeClass extends Model
{
use HasFactory;
/** #return SomeFancyFactory */
protected static function newFactory()
{
return SomeFancyFactory::new();
}
}
After this change, my tests passed as expected.
You need to ensure that the namespace is the same: as shown below: otherwise this will screw you up big time. The name of the factory is the name of the model + Factory
e.g. app\models\User- will match to database/factories/UserFactory
finally ensure you run: composer dumpautoload
In my own case, it happened in a Laravel 8 project ie it wasn't a project I upgraded from Laravel 7. And I noticed this after doing composer update recently.
1: When creating the model, create the factory alongside
php artisan make:model BusinessUser -f // -f creates the factory
2: For your older models comment out use HasFactory; or just create the factory
php artisan make:factory BusinessUserFactory -m
Let's say your model Example is under the App\Example\Models namespace. If you want ALL of your factories under database\factories, then you could define the namespace for your all of factories in your AppServiceProvider:
// ...
use Illuminate\Database\Eloquent\Factories\Factory;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
Factory::guessFactoryNamesUsing(function (string $modelName) {
return 'Database\\Factories\\'.class_basename($modelName).'Factory';
});
}
}
And then in your factory, located in database/factories/ExampleFactory.php:
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
class ExampleFactory extends Factory
{
// ...
}
...as per this twitter comment (I can't take credit for this solution but sharing the fix!):
https://twitter.com/ejunker/status/1306007589940068352/photo/1
I was having this same issue, but for a different reason. If you're using factories in the setUp function of a test, make sure:
You're extending Tests\TestCase (instead of PHPUnit\Framework\TestCase)
The first line of your setUp function should be parent::setUp(); (I was missing this)
Add this to AppServiceProvider::boot() to prevent namespace of model guessing.
Factory::guessFactoryNamesUsing(function (string $modelName) {
return 'Database\\Factories\\' . Arr::last(explode('\\', $modelName)) . 'Factory';
});
It seems like a laravel core issue ! it was caused by the modelName() method located in Illuminate\Database\Eloquent\Factories\Factory.php
Issue was fixed 10 days ago by laravel maintainers in this commit
Fix commit and this release 8.82.0
You can fix the issue by upgrading your laravel version to 8.82.0
Hope this saves you some time. cheers !
May be everything is perfect just run composer dump-autoload. It happened to me.
my problem was related with composer.lock file that was installing laravel v7, solved it with this command
composer update
Use this package if you are upgrading from laravel 7 to 8
composer require laravel/legacy-factories
Today I have got below issue after upgrading my project from Laravel 7 to Laravel 8 and updating it online on server.
Trait 'Illuminate\Database\Eloquent\Factories\HasFactory' not found
Even I have updated composer.json with autoload directive given in answer by #lagbox but it did not resolved the issue for me.
Finally I have updated complete vendors folder online that have resolved my issue.
I am just start working with Laravel, want to create a custom class and want to call this class in every controller. For this, I create a Customer class in app/Library/ folder.
When I tried to autoload this library via composer, json it's giving an error:
Could not scan for classes inside "App/Library/Customer" which does not appear to be a file nor a folder.
How can we use autoload class in controllers?
Customer.php
<?php
namespace App\Library;
use App\Model\User;
class Customer
{
public function login($user_name,$password){
$data = User::where('email', $user_name)
->where('password', $password)
->first();
return $data->id';
}
}
Autoload section of Composer.json
{
"autoload": {
"classmap": [
"database",
"app/Library/Customer"
],
"psr-4": {
"App\\": "app/"
},
"files" : [
"app/Helper/helper.php"
]
}
}
I think you're not understanding what the composer autoload is there for. You use this to include libraries and their dependencies, not really for classes you've created in your app.
What you're better off doing is when you create the controller add in the class you want to use eg:
<?php
use App\Library\Customer;
You will need to put this in every controller.
You should remove it from the classmap group and just add the proper namespace and class. You can see all the psr-4 standards here: http://www.php-fig.org/psr/psr-4/
Lets say you have a folder structure like this:
app
-> Library
-> Customer.php // namespace App\Library; class Customer{}
-> Model
-> User.php // namespace App\Model; class User{}
And all the files should autoload as long as you use the proper namespace and class names.
By the way you should use the Auth facade instead: https://laravel.com/docs/5.4/authentication
There is no need to classmap as already psr-4 autoloading is in place. You've to understand how it works. then you can simply import your classes using use keyword, like this
<?php
use App\Library\Customer;
For more information read PSR-4: Autoloader and take this Tutorial
I'm new on laravel and need some help.
Actualy i use 5.3 laravel version.
I need to use, in laravel, external company framework (call it F for semplicity).
This framework is some like process manager. Actualy, for integrate it with laravel i put it in laravel/public folder, this way i can use laravel and F's pages in same domain. In laravel i need to access to some F functionality wich is all collect in class FFramework\Facade\FInterface;
Then i want to acces to this class from laravel controller FController.
But when i run code i get Class Not Found Exception.
This is folder structure:
laravel
app
http
controllers
FController.php
public
css
js
index.php
fframework
facade
FInterface.php
index.php
This is code example:
FController.php
<?php
namespace App\Http\Controllers;
use FFramework\facade\FInterface;
class FController extends Controller {
public function getSimpleDAta() {
$f = new FInterface();
return $f->getSimpleData();
}
}
FInterface.php
<?php
namespace FFramework\facade;
use some\internal\function;
class FInterface {
public function getSimpleDAta() {
$simpleData = ...omg so much computation :) ...
return $simpleData;
}
}
Exception that i get:
Class 'FFramework\facade\FInterface' not found
Additional Information
I use standard LAMP configuration
PHP version is last 5.6 stable version
Question
How can i use FInterface from Laravel controller leaving FFramework in public folder?
You need to update the autoload section of your composer.json file to tell your project where to look for files in the FFramework namespace.
"autoload": {
"classmap": [
"database"
],
"psr-4": {
"App\\": "app/"
"FFramework\\": "public/fframework"
}
},
So I've been trying to create a custom class file for all my custom classes and append them in there, I'm using namespaces in order to accomplish using them in my controller however the controller is not recognizing the class
Ok:
Here is my custom class file placed in my project as app/Library/robloxClasses.php
namespace App\Library;
class RobloxMaths{
public function sortArrayOfArray(&$array, $subfield)
{
$sortarray = array();
foreach ($array as $key => $row)
{
$sortarray[$key] = $row[$subfield];
}
array_multisort($sortarray, SORT_DESC, $array);
}
}
Library is a folder i made to store all my custom class files in there
Here is how my controller ApiController uses the file using it's namespace
<?php
namespace App\Http\Controllers;
use App\Library\RobloxMaths;
use Illuminate\Http\Request;
class ApiController extends Controller
{
protected $RobloxClass;
public function __construct(){
$this->$RobloxClass= new RobloxMaths;
}
}
?>
The problem is, it keeps returning:
Class 'App\Library\RobloxMaths' not found
And I honestly do not know what's wrong, please help!
NOTE: I have tried composer update, and it fixes it temporarily but after a day or two or after me installing new dependencies it notifies me that the Class 'App\Library\RobloxMaths' not found thing happened
help please
Ensure that you have correctly setup the psr-4 autoload root in your composer.json file and that your file/directory names match perfectly including capitalisation, then run composer dump-autoload.
Example:
"autoload": {
"psr-4": {
"App\\": "app/"
}
}
This will assign the root namespace App to the app folder.
If you are using an IDE, there is a large chance that your use and namespace statements where auto-generated with the lowercase app to match the directory name. As all the names tie up correctly in the IDE there are no errors, but when it comes to running the PHP script the autoloader is not doing require|require_once on your files and therefore your classes are not available.
Option 1 (Do this)
Ensure that your namespaces have consistent capitalisation that matches the composer.json entry.
Option 2 (Written for completion)
Ensure that you add a new entry for this root namespace to your composer.json file. For the example above this would be:
"autoload": {
"psr-4": {
"App\\": "app/",
"app\\": "app/"
}
}
It's an old question, but I had the same problem with laravel 9,
The problem is that I've used php short tag <? instead of <?php at the custom class file.
it's silly but this was the solution for me.
I am starting out with Laravel 5 and as first order of business I want to move all my models into a folder called Models.
But how can I access those without specifying the namespace like in the following?:
...
class UserRolesTableSeeder extends Seeder {
public function run()
{
DB::table('user_roles')->delete();
App\Models\UserRoles::create(['name' => 'CREATE_USER']);
}
}
Go into your composer.json and add at the end of "autoload": "classmap" this line "app/models". This way you are telling laravel to autoload those clases. After that, run a composer update and it should work.
You can also create a service provider to access models without namespaces.
To create a service provider, here is what you have to do :
1) Create a file in your models directory and name it ModelsServiceProvider.php
2) Inside of it write this code
<?php
namespace App\Models;
use Illuminate\Support\ServiceProvider;
class ModelsServiceProvider extends ServiceProvider {
public function register()
{
$this->app->booting(function()
{
$loader = \Illuminate\Foundation\AliasLoader::getInstance();
$loader->alias('UserRoles', 'App\Models\UserRoles');
});
}
3) Go into app/config/app.php and under providers array add this line 'App\Models\ModelsServiceProvider'
You can also add directly your aliases for classes under the aliases array inside app/config/app.php.
Alternatively, you can just load your models into the global namespace like you were doing before! It's a bit scary to go against the docs but so far we haven't had any issues with it.
To make sure your models are still loaded, you just need to add the reference to your composer.json:
(assumes your namespace is App\Models)
"autoload": {
"classmap": [
...
"app/Models/"
],
...
"": [
"app/Models/"
]
be sure to run composer dump-autoload