Can't use dependency injection in Laravel 6 - laravel

I am using laravel 6. I have a service provider class called DriveServiceProvider. This class has all the dependencies that are needed to connect with google drive.The following is my Service Provider
<?php
use Hypweb\Flysystem\GoogleDrive\GoogleDriveAdapter;
use League\Flysystem\Filesystem;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Storage;
class DriveServiceProvider extends ServiceProvider
{
public function register(){
}
public function boot()
{
Storage::extend('google',function( $app,$config){
$client=new \Google_Client();
$client->setClientId($config['clientId']);
$client->setClientSecret($config['clientSecret']);
$client->refreshToken($config['refreshToken']);
$service=new \Google_Service_Drive($client);
$adapter=new GoogleDriveAdapter($service,$config['folderId']);
return new FileSystem($adapter);
});
}
}
I want to pass this service provider to a controller, the following is my controller
<?php
namespace App\Http\Controllers\Cloud;
use App\Http\Controllers\Controller;
use App\Providers\DriveServiceProvider;
use Hypweb\Flysystem\GoogleDrive\GoogleDriveAdapter;
use Illuminate\Support\Facades\Cache;
use League\Flysystem\Filesystem;
class uploadFileController extends Controller{
public $filesystem;
//Attempting Dependency Injection
public function __construct(DriveServiceProvider $filesystem) {
$this->filesystem=$filesystem;
}
public function createFolder(){
$directoryName='Demo';
$this->filesystem->createDir($directoryName);
//return $$filesystem->folder_id;
}
public function deleteFolder($id){
$this->filesystem->delete();
}
}
When i run the script , it's throwing the fllowing error
Illuminate\Contracts\Container\BindingResolutionException
Unresolvable dependency resolving [Parameter #0 [ <required> $app ]] in class
Illuminate\Support\ServiceProvider
What's wrong with my code ? any help is appreciated.

There is an easier approach to do Google Drive implementation in Laravel install.
composer require nao-pon/flysystem-google-drive
In filesystems.php include your google config.
'google' => [
'driver' => 'google',
'clientId' => env('GOOGLE_DRIVE_CLIENT_ID'),
'clientSecret' => env('GOOGLE_DRIVE_CLIENT_SECRET'),
'refreshToken' => env('GOOGLE_DRIVE_REFRESH_TOKEN'),
'folderId' => env('GOOGLE_DRIVE_FOLDER_ID'),
],
Now you should be able to get your files like so.
Storage::disk('google')->get('yourfile');
This is inspired by this following tutorial.

Related

Lumen - Using factory() function in tests make error - Undefined Function

I'm using Lumen 8.3 ,wanted to use factory() function in my tests, it gives me
Undefined Function ,there is nothing useful in the Docs of Lumen
Am i missing something here?
class ProductTest extends TestCase
{
public function test_if_can_send_products_list(){
$products = factory('App/Products',5)->make();
$this->json('post','/payouts',$products)
->seeJson([
'created' => true,
]);
}
}
->
Error: Call to undefined function factory()
It's better to use direct class like that:
$products = factory(Products::class, 5)->create();
don't forget to add Products model usage (namespace).
Edit
You should create Factory:
<?php
namespace Database\Factories;
use App\Products;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
class ProductFactory extends Factory
{
protected $model = Products::class;
public function definition(): array
{
return [
'name' => $this->faker->unique()->userName()
];
}
}
And add HasFactory Trait to your model:
use Illuminate\Database\Eloquent\Factories\HasFactory;
class Products extends Model {
use HasFactory;
}
you can also use it like this
Products::factory()->count(5)->make();
I just uncommented these lines in app.php file
$app->withFacades();
$app->withEloquent();
Apparently Laravel 8 removed the 'factory' helper, and it seems Lumen followed that path without updating documentation;
#Faesal Answer is the correct way to do it these days;
remember to add use HasFactory; to your Model.

Unable to locate factory in Laravel 7

I am making a unit test for PHPunit. The code is:
<?php
namespace Tests\Unit;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use PHPUnit\Framework\TestCase;
class ThreadTest extends TestCase
{
use DatabaseMigrations;
public function test_a_thread_has_replies()
{
$thread = factory('App\Thread')->create();
$this->assertInstanceOf('Illuminate\Database\Eloquent\Collection', $thread->replies);
}
}
When I run PHPUnit i get the error:
InvalidArgumentException: Unable to locate factory for [App\Thread].
I have a threadfactory:
<?php
/** #var \Illuminate\Database\Eloquent\Factory $factory */
use App\Thread;
use Faker\Generator as Faker;
$factory->define(Thread::class, function (Faker $faker) {
return [
'user_id' => factory(App\User::class),
'title' => $faker->sentence,
'body' => $faker->paragraph
];
});
If I use the factory in Tinker it works fine.
I have similar testfunctions and factories for other classes and these work fine.
Most likely I am making a very stupid error, but I cannot find it.
Any suggestions?
Kind regards,
HUbert
You are extending the php unit testcase class. Which does not load your Laravel application. You should extends the use Tests\TestCase provided by Laravel.
Using php artisan make:test UserTest on the CLI will create a test with the correct template fitting for testing a Laravel application.
What worked for me was to use
$factory->define(App\Model::class, function (Faker $faker) {
//return code here
}
Instead of just using the Model name without placing APP\ in front of the model name
$factory->define(Model::class, function (Faker $faker) {
//return code here
}

How to share one method to all controllers in Laravel?

How to share one method to all controllers with different DI, view and parameters? I need something like this:
public function method(Model $model)
{
$baseData = [
'model' => $model,
'route' => route('$route', [$param => $model]),
];
return view($view);
}
All controllers extend App\Http\Controllers\Controller so you can just place it there
<?php
namespace App\Http\Controllers;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
public function method(Model $model, $route, $param, $view)
{
// Declared but not used
$baseData = [
'model' => $model,
'route' => route($route, [$param => $model]),
];
return view($view);
}
}
And use it with $this->method()
For example in HomeController
<?php
namespace App\Http\Controllers;
use App\User;
class HomeController extends Controller
{
/**
* Show the application dashboard.
*
* #return \Illuminate\Contracts\Support\Renderable
*/
public function index()
{
$user = User::first();
return $this->method($user, 'home', 'user', 'welcome');
}
}
Now accessing domain.tld/home will return the welcome view
If you want to share function to all controller best way will make service in service folder of app.
step to make service:-
1.create service using artisan command
php artisan make:service service_name and define function that to share to all controller in your project.
after making service your have to register this service with provider.make a provider using artisan command.
php artisan make provider:provider_name and you will see 2 function register and boot
register function is used to register your created service and boot for call already register service
register service like this
public function register()
{
$this->app->bind('App\Services\servicename', function( $app ){
return new serviceclassname;
});
}
3.Go config folder ,open app.php where you will get providers array. In this provider you have to define you provider like App\Providers\providerclassname::class,
call this service in controllers like use App\Services\serviceclassname;
public function functionname(serviceclassname serviceobject)
{
serviceobject->functionname();
}

Laravel - Custome Auth Throttlelogins

I have created a custom authentication and everything is working fine.
Now I am trying to add the Throttlelogins to prevent multiple incorrect login attempts. But The ThrottleLogins doesn't seem to load.
Q: What am I missing here? or am I doing something wrong?
The exception:
Method
App\Http\Controllers\Auth\CustomersLoginController::hasTooManyLoginAttempts
does not exist.
<?php
namespace App\Http\Controllers\Auth;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Validation\ValidationException;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Auth;
class CustomersLoginController extends Controller
{
public function __construct()
{
$this->middleware('guest:customers');
}
public function ShowLoginForm()
{
return view('auth.customer-login');
}
public function login(Request $request)
{
$v = $request->validate([
'email' => 'required|email',
'password' => 'required',
]);
if ($this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
if(Auth::guard('customers')->attempt(['email'=>$request->email,'password'=>$request->password],$request->remember)){
return redirect()->intended(route('customerdashboard'));
};
return $this->sendFailedLoginResponse($request);
}
protected function sendFailedLoginResponse(Request $request)
{
throw ValidationException::withMessages([
$this->username() => [trans('auth.failed')],
]);
}
public function username()
{
return 'email';
}
}
Error Message
Can someone please explain what am I mssing?
The error says you are missing a function: hasTooManyLoginAttempts
In the function login you can see it's trying to call the function but it does not exist in your class. This is where it goes wrong.
update
In the AuthenticateUsers class, which you tried to copy, it's using ThrottlesLogins trait, which you are missing in your controller.
Update your controller like so:
class CustomersLoginController extends Controller
{
use ThrottlesLogins;
Another update
You tried to import the Trait which Laravel uses in their own Login. However this will not work here's why:
When you define a class, it can only have access to other classes within its namespaces. Your controller for instance is defined within the following namespace.
namespace App\Http\Controllers\Auth;
So to use other classes, you need to import them from their own namespaces so you can access them. e.g.:
use Illuminate\Foundation\Auth\ThrottlesLogins;
Now that you have imported the ThrottlesLogins, which is actually a trait, now inside the class you use it to expose all of the methods inside.

Laravel use custom class

I created a new class under /app/UserRepositories/UserRepository.php.
Now i want to use it in my AuthenticateUser.php under /app.
I tried to import it like that use App\Repositories\UserRepository;
but I get still the same error: Class does not exist
UserRepository.php
<?php use App\Repositories;
use App\User;
class UserRepository {
public function updateOrCreate($userData)
{
return User::firstOrCreate([
'username' => $userData->username,
'email' => $userData->email,
'avatar' => $userData->avatar
]);
}
}
At the beginning of your file /app/UserRepositories/UserRepository.php, you will need to namespace it using:
namespace App\UserRepositories;
Then you can import it to be used anywhere by:
use App\UserRepositories\UserRepository;

Resources