Laravel 5.1 issue implementing global scope - php

So I am trying to create a global scope in laravel 5.1 but just keep on getting the following error Trait 'Eloquent\Scopes\DependentTypeTrait' not found.
Here is my code:
App\Models\Eloquent\Scopes\DependentTypeTrait.php:
<?php namespace App\Models\Eloquent\Scopes;
trait DependentTypeTrait {
/**
* Boot the Active Events trait for a model.
*
* #return void
*/
public static function bootDependentTypeTrait()
{
static::addGlobalScope(new DependentTypeScope);
}
}
App\Models\Eloquent\Scopes\DependentTypeScope.php:
<?php namespace App\Models\Eloquent\Scopes;
use Illuminate\Database\Eloquent\ScopeInterface;
use Illuminate\Database\Eloquent\Builder;
class DependentTypeScope implements ScopeInterface
{
public function apply(Builder $builder)
{
$builder->where('vip_type_id', 2);
}
public function remove(Builder $builder)
{
$query = $builder->getQuery();
// here you remove the where close to allow developer load
// without your global scope condition
foreach ((array) $query->wheres as $key => $where) {
if ($where['column'] == 'vip_type_id') {
unset($query->wheres[$key]);
$query->wheres = array_values($query->wheres);
}
}
}
}
App\Models\Dependent.php:
<?php namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Eloquent\Scopes\DependentTypeTrait;
class Dependent extends Model
{
use DependentTypeTrait;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = '<my table name>';
/**
* The actual primary key for the model.
*
* #var string
*/
protected $primaryKey = '<my primary key>';
}
I feel like I have the namespacing correct but its still saying it can't find the attribute....any ideas?

I think you have the use namespace wrong when trying to import your DependentTypeTrait:
<?php namespace App\Models\Eloquent\Scopes;
trait DependentTypeTrait { //...
And then you use it in App\Models\Dependent:
use Eloquent\Scopes\DependentTypeTrait;
Those namespaces don't match. Try this instead:
use App\Models\Eloquent\Scopes\DependentTypeTrait;
Or you can modify your composer.json to change how the Eloquent namespace is autoloaded:
"autoload": {
"psr-4": {
"Eloquent\\": "app/Models/Eloquent"
}
},
And don't forget to dump your autoloader: $ composer dump-autoload
Though specifically because you're using the name Eloquent which is ubiquitous in Laravel, I wouldn't go this route myself even if you would save yourself some typing. Laravel itself uses the namespace Illuminate\Database\Eloquent so you're probably safe from conflicts for now, but the possibility exists if Taylor changes things around or you use a third party library that stomps on it.

Related

Laravel, Call to undefined function Database\Seeders\factory()

I get the title error when I run command:
php artisan db:seed
My screenshot:
I have no idea where this problem comes from. I was searching for code examples and solution but I haven't found anything :(
ArticlesTableSeeder.php
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
// use Laracasts\TestDummy\Factory as TestDummy;
class ArticlesTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
factory(App\Models\Article::class, 30)->create();
}
}
ArticleFactory.php
<?php
namespace Database\Factories;
use App\Models\Model;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
class ModelFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* #var string
*/
protected $model = App\Models\Article::class;
/**
* Define the model's default state.
*
* #return array
*/
public function definition()
{
return [
'title' => $faker->text(50),
'body' => $faker->text(200)
];
}
}
DatabaseSeeder.php
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*
* #return void
*/
public function run()
{
$this->call(ArticlesTableSeeder::class);
}
}
Thank you in advance for your help!
In laravel 8 the default route namespace was removed.
Try to change:
ArticlesTableSeeder.php:
factory(App\Models\Article::class, 30)->create();
to:
\App\Models\Article::factory()->count(30)->create();
ArticleFactory.php:
protected $model = App\Models\Article::class;
to:
protected $model = \App\Models\Article::class;
and you will probably have to change:
'title' => $faker->text(50),
'body' => $faker->text(200)
to:
'title' => $this->faker->text(50),
'body' => $this->faker->text(200)
All suggestions that were mentioned here are correct.
Sometimes running composer require laravel/legacy-factories might fix your problem if you're using Laravel 8.
Also, in case you get an error that says Class 'Database\Factories\ArticleFactory' not found
then make sure you have class ArticleFactory extends Factory and not ModalFactory.
And make sure you're using HasFactory in the Article Model like here.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Article extends Model
{
use HasFactory;
}
For more info: Laravel 8 Modal Factories
Try to change
factory(App\Models\Article::class, 30)->create();
to
App\Models\Article::factory()->count(30)->create();
ArticlesTableSeeder.php
<?php
namespace Database\Seeders;
use App\Models\Article;
use Illuminate\Database\Seeder;
class ArticlesTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
Article::factory()->times(30)->create();
}
}
ArticleFactory.php
<?php
namespace Database\Factories;
use App\Models\Article;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
class ArticleFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* #var string
*/
protected $model = Article::class;
/**
* Define the model's default state.
*
* #return array
*/
public function definition()
{
return [
'title' => $this->faker->text(50),
'body' => $this->faker->text(200)
];
}
}
If you are using version 8 of laravel, look at the upgrade guide.
"Laravel's model factories feature has been totally rewritten to support classes and is not compatible with Laravel 7.x style factories. However, to ease the upgrade process, a new laravel/legacy-factories package has been created to continue using your existing factories with Laravel 8.x. You may install this package via Composer:
composer require laravel/legacy-factories"
https://laravel.com/docs/8.x/upgrade#seeder-factory-namespaces
change
‍factory(App\Models\Article::class, 30)->create(); ‍
to
\App\Models\Article::factory(30)->create();
I'm facing the same issue when I realized my model was not using the HasFactory trait.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
use HasFactory;
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'categories';
}
So make sure this trait is being used by your model.
If you are using version 8 of laravel you can directory use:
use App\Models\Article;
Article::factory()->count(30)->create();
composer require laravel/legacy-factories
php artisan db:seed

Using Laravel with microservices: Is it possible to use eloquent without a database?

We're using a microservice architecture. There are 2 sets of data for the laravel service:
The database that houses the admins.
And all the other data that admins can access, which comes via GRPC
calls to other services.
I want something like eloquent (maybe API Resource?) for structuring data/relationships, but instead of making Database-queries to load data, it needs to make GRPC calls to other services. I was thinking of making a custom class that extends off of eloquent and overloading the protected functions that make calls to the database, but that sounds like a recipe for a bad time. If anybody has experience doing what I'm describing, what direction did you go? What worked? what didn't?
So, I ended up not using eloquent at all. I continued using the protoc set up as the documentation explains. But I used Route-binding to enable type-hinting in controllers:
<?php
namespace App\Providers;
use OurNamespace\GrpcClient;
use Illuminate\Support\Facades\Route;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use OurNamespace\Customer;
use OurNamespace\CustomerIdInput;
class RouteServiceProvider extends ServiceProvider
{
/**
* This namespace is applied to your controller routes.
*
* In addition, it is set as the URL generator's root namespace.
*
* #var string
*/
protected $namespace = 'App\Http\Controllers';
/**
* Define your route model bindings, pattern filters, etc.
*
* #return void
*/
public function boot()
{
//
parent::boot();
Route::bind('customer', function ($customerId) {
$grpcClient = app(GrpcClient::class);
$customerIdInput = new CustomerIdInput();
$customerIdInput->setCustomerId($customerId);
list($customer, $status) = $grpcClient->GetCustomerDetails($customerIdInput)->wait();
if ($status->code != 0) {
error_log('ERROR - ' . print_r($status, 1));
return redirect()->back()->withErrors(['There was an error retrieving that customer', $status->details]);
}
return $customer;
});
The GrpcClient is coming from the AppServiceProvider. This way if we want to make a query we don't have to manually instantiate it.
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use OurNamespace\GrpcClient;
use Grpc\ChannelCredentials;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->app->singleton('OurNamespace\GrpcClient', function ($app) {
return new GrpcClient(env('GRPC_HOST'), [
'credentials' => ChannelCredentials::createInsecure(),
]);
});

Laravel 5.7: target is not instantiable while building

I know there are so many answer, but I cannot really solve this.
I did follow this answer (How to make a REST API first web application in Laravel) to create a Repository/Gateway Pattern on Laravel 5.7
I have also the "project" on github, if someone really kindly want test/clone/see : https://github.com/sineverba/domotic-panel/tree/development (development branch)
App\Interfaces\LanInterface
<?php
/**
* Interface for LAN models operation.
*/
namespace App\Interfaces;
interface LanInterface
{
public function getAll();
}
App\Providers\ServiceProvider
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Schema;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
/**
* Solve the "Key too long" issue
*
* #see https://laravel-news.com/laravel-5-4-key-too-long-error
*/
Schema::defaultStringLength(191);
}
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->app->register(RepositoryServiceProvider::class);
}
}
App\Providers\RepositoryServiceProvider
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class RepositoryServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind(
'app\Interfaces\LanInterface', // Interface
'app\Repositories\LanRepository' // Eloquent
);
}
}
App\Gateways\LanGateway
<?php
/**
* The gateway talks with Repository
*/
namespace App\Gateways;
use App\Interfaces\LanInterface;
class LanGateway
{
protected $lan_interface;
public function __construct(LanInterface $lan_interface) {
$this->lan_interface = $lan_interface;
}
public function getAll()
{
return $this->lan_interface->getAll();
}
}
App\Repositories\LanRepository
<?php
/**
* Repository for LAN object.
* PRG paradigma, instead of "User"-like class Model
*/
namespace App\Repositories;
use App\Interfaces\LanInterface;
use Illuminate\Database\Eloquent\Model;
class LanRepository extends Model implements LanInterface
{
protected $table = "lans";
public function getAll()
{
return 'bla';
}
}
I did add also App\Providers\RepositoryServiceProvider::class, in providers section of config\app.php
This is finally the controller (I know that it is not complete):
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Gateways\LanGateway;
class LanController extends Controller
{
private $lan_gateway;
/**
* Use the middleware
*
* #return void
*/
public function __construct(LanGateway $lan_gateway)
{
$this->middleware('auth');
$this->lan_gateway = $lan_gateway;
}
/**
* Display a listing of the resource.
*
* #return \Illuminate\Contracts\Support\Renderable
*/
public function index()
{
$this->lan_gateway->getAll();
return view('v110.pages.lan');
}
}
And the error that I get is
Target [App\Interfaces\LanInterface] is not instantiable while building [App\Http\Controllers\LanController, App\Gateways\LanGateway].
I did try:
php artisan config:clear
php artisan clear-compiled
I think #nakov might be right about it being case-sensitive. I don't believe PHP itself cares about upper/lowercase namespaces, but the composer autoloader and the Laravel container use key->value array keys, which do have case-sensitive keys, to bind and retrieve classes from the container.
To ensure the names always match, try using the special ::class constant instead, like this:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Repositories\LanRepository;
use App\Interfaces\LanInterface;
class RepositoryServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind(
LanInterface::class,
LanRepository::class
);
}
}
In my case i forgot to enlist the provider to confit/app.php that's why the error.
Clear the old boostrap/cache/compiled.php:
php artisan clear-compiled
Recreate boostrap/cache/compiled.php:
php artisan optimize

Laravel 5 SQLSTATE[42S02]: Base table or view not found

I'm studing about Repository Design Pattern in Laravel and I'm using https://github.com/andersao/l5-repository to do it.
I think i install success in my project . But when i run code with repository i have some problem
SQLSTATE[42S02]: Base table or view not found: 1146 Table
'test.nhanviens' doesn't exist (SQL: select * from nhanviens)
Table in my database is Nhanvien not Nhanviens
Here in my code
NhanvienRepository.php
<?php
namespace App\Repositories;
use Prettus\Repository\Contracts\RepositoryInterface;
/**
* Interface NhanvienRepository
* #package namespace App\Repositories;
*/
interface NhanvienRepository extends RepositoryInterface
{
//
}
NhanvienRepositoryEloquent.php
<?php
namespace App\Repositories;
use Prettus\Repository\Eloquent\BaseRepository;
use Prettus\Repository\Criteria\RequestCriteria;
use App\Repositories\NhanvienRepository;
use App\Entities\Nhanvien;
use App\Validators\NhanvienValidator;
/**
* Class NhanvienRepositoryEloquent
* #package namespace App\Repositories;
*/
class NhanvienRepositoryEloquent extends BaseRepository implements NhanvienRepository
{
/**
* Specify Model class name
*
* #return string
*/
public function model()
{
return Nhanvien::class;
}
/**
* Boot up the repository, pushing criteria
*/
public function boot()
{
$this->pushCriteria(app(RequestCriteria::class));
}
}
DataController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\nhanvien;
use App\Repositories\NhanvienRepository;
class DataController extends Controller
{
protected $repository;
public function __construct(NhanvienRepository $repository){
$this->repository = $repository;
}
public function DanhSach(){
var_dump($this->repository->all());
}
}
from App\Nhanvien.php Add this variable to the class:
protected $table = 'nhanvien';
Explanation: The "snake case", plural name of the class will be used as the table name unless another name is explicitly specified. So, in this case, Eloquent will assume the nhanvien model stores records in the nhanviens table.
As stated in the official Eloquent documentation you need to specifically set the table name in your Model definition. That is, in your App\Nhanvien.php file set the following:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Nhanvien extends Model
{
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'Nhanvien';
}
or use
protected $table = 'nhanvien';
instead if your table name is full lowercase.
Check your migration file, maybe you are using Schema::table, like this:
Schema::table('table_name', function ($table) {
// ... });
If you want to create a new table you must use Schema::create:
Schema::create('table_name', function ($table) {
// ... });
See the Laravel migration documentation for more information.
If you are using Schema::create then please provide the contents of your migration file.
In my case, I've got rid of similar error by executing the command
php artisan config:cache

Namespacing for seeders

I'm trying to see what I'm doing wrong for my seed file to not work with my namespacing properly and wanted to see if someone can spot what's not working in this code.
Error: PHP Fatal error: Class 'App\Models\Eloquent' not found in
/Users/me/Repositories/personal/project/app/models/Event.php
<?php
namespace App\Models;
class Event extends Eloquent {
protected $fillable = [];
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'events';
}
<?php
use App\Models\Event;
// Composer: "fzaninotto/faker": "v1.3.0"
use Faker\Factory as Faker;
class EventsTableSeeder extends Seeder {
public function run()
{
$faker = Faker::create();
foreach(range(1, 100) as $index)
{
Event::create([
]);
}
}
}
You need to point to Eloquent in the root namespace instead of Eloquent inside App\Models (which doesn't exist)
To do that either reference id with a backslash:
class Event extends \Eloquent {
or add a use statement:
use Eloquent
class Event extends Eloquent {

Categories