Error while applying a seeder in laravel - laravel-5

Here is my code that intends to seed the includes table:
<?php
use Illuminate\Database\Seeder;
use App\Include;
class IncludesTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
$faker = Faker\Factory::create();
for ($i=1; $i < 12; $i++) {
$include = [
'name' => $faker->words(2, true),
'price' => $faker->numberBetween(20000, 2000000),
'product_id' => $i,
];
Include::create($include);
}
}
}
But when I attempt to run the seeder via artisan I get this error:
[Symfony\Component\Debug\Exception\FatalThrowableError]
Parse error: syntax error, unexpected 'Include' (T_INCLUDE), expecting iden
tifier (T_STRING) or '{'
I can't figure out what is missing, anybody with an idea please!

PHP don't allow you to name a class Include, change the name of the model and it should work.
Please notice that if you change the name of the model you either need to change the name of table as well or use the protected var table to override the convention.
class NameOfClass
{
protected $table = "includes";
}

Related

laravel-8 user table seeder does not exist

I am trying to make a login from laravel 8 but at the begging I faced an error which I cannot find a solution. The UsersTablesSeeder is created but still the compiler cannot find it
Illuminate\Contracts\Container\BindingResolutionException
Target class [UsersTablesSeeder] does not exist.
at C:\xampp\htdocs\pary\vendor\laravel\framework\src\Illuminate\Container\Container.php:832
828▕
829▕ try {
830▕ $reflector = new ReflectionClass($concrete);
831▕ } catch (ReflectionException $e) {
➜ 832▕ throw new BindingResolutionException("Target class [$concrete] does not exist.", 0, $e);
833▕ }
834▕
835▕ // If the type is not instantiable, the developer is attempting to resolve
836▕ // an abstract type such as an Interface or Abstract Class and there is
1 C:\xampp\htdocs\pary\vendor\laravel\framework\src\Illuminate\Container\Container.php:830
ReflectionException::("Class "UsersTablesSeeder" does not exist")
2 C:\xampp\htdocs\pary\vendor\laravel\framework\src\Illuminate\Container\Container.php:830
ReflectionClass::__construct("UsersTablesSeeder")
the following code shows DatabaseSeeder.php
<?php
use Illuminate\Database\Seeder;
use Illuminate\Database\Eloquent\Model;
class DatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
Eloquent::unguard();
$this->call(UsersTablesSeeder::class);
}
}
this is my user table
<?php
use Illuminate\Database\Seeder;
use Illuminate\Database\Eloquent\Model;
use App\User;
class UsersTablesSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
User::create([
'name' => 'John Smith',
'email' => 'john_smith#gmail.com',
'password' => Hash::make('password'),
'remember_token' => str_random(10),
]);
}
}
I am following this link
Add namespace Database\Seeders; to your class. As said in laravel 8
Seeders and factories are now namespaced. To accommodate for these
changes, add the Database\Seeders namespace to your seeder classes. In
addition, the previous database/seeds directory should be renamed to
database/seeders:

How to change hard coded Eloquent $connection only in phpunit tests?

I have an Eloquent Model like this:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class SomeModel extends Model
{
protected $connection = 'global_connection';
......................
The problem is that this $connection has to be hard coded because I have a multi tenant web platform and all the tenants should read from this Database.
But when now in tests I am hitting the Controller route store() and I don't have access to the model!
I just do this:
public function store()
{
SomeModel::create($request->validated());
return response()->json(['msg' => 'Success']);
}
Which works great when using it as a user through browser...
But now I want to somehow force that model NOT to use that hard coded $connection and set it to Testing database connection...
And this is my Test
/** #test */
public function user_can_create_some_model(): void
{
$attributes = [
'name' => 'Some Name',
'title' => 'Some Title',
];
$response = $this->postJson($this->route, $attributes)->assertSuccessful();
}
Is there any way to achieve this with some Laravel magic maybe :)?
Because you asked for Laravel magic... Here it goes. Probably an overkill and over engineered way.
Let's first create an interface whose sole purpose is to define a function that returns a connection string.
app/Connection.php
namespace App;
interface Connection
{
public function getConnection();
}
Then let's create a concrete implementation that we can use in real world (production).
app/GlobalConnection.php
namespace App;
class GlobalConnection implements Connection
{
public function getConnection()
{
return 'global-connection';
}
}
And also another implementation we can use in our tests.
app/TestingConnection.php (you can also put this in your tests directory, but make sure to change the namespace to the appropriate one)
namespace App;
class TestingConnection implements Connection
{
public function getConnection()
{
return 'testing-connection';
}
}
Now let's go ahead and tell Laravel which concrete implementation we want to use by default. This can be done by going to the app/Providers/AppServiceProvider.php file and adding this bit in the register method.
app/Providers/AppServiceProvider.php
namespace App\Providers;
use App\Connection;
use App\GlobalConnection;
// ...
public function register()
{
// ...
$this->app->bind(Connection::class, GlobalConnection::class);
// ...
}
Let's use it in our model.
app/SomeModel.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class SomeModel extends Model
{
public function __construct(Connection $connection, $attributes = [])
{
parent::__construct($attributes);
$this->connection = $connection->getConnection();
}
// ...
}
Almost there. Now in our tests, we can replace the GlobalConnection implementation with the TestingConnection implementation. Here is how.
tests/Feature/ExampleTest.php
namespace Tests\Feature;
use Tests\TestCase;
use App\Connection;
use App\TestingConnection;
class ExampleTest extends TestCase
{
public function setUp(): void
{
parent::setUp();
$this->app->instance(Connection::class, TestingConnection::class);
}
/** #test */
public function your_test()
{
// $connection is 'testing-connection' in here
}
}
Code is untested, but should work. You can also create a facade to access the method statically then use Mockery to mock the method call and return a desired connection string while in testing.
Unfortunately for me, none of these answers didn't do the trick because of my specific DB setup for multi tenancy. I had a little help and this is the right solution for this problem:
Create a custom class ConnectionResolver somewhere under tests/ directory in laravel
<?php
namespace Tests;
use Illuminate\Database\ConnectionResolverInterface;
use Illuminate\Database\ConnectionResolver as IlluminateConnectionResolver;
class ConnectionResolver extends IlluminateConnectionResolver
{
protected $original;
protected $name;
public function __construct(ConnectionResolverInterface $original, string $name)
{
$this->original = $original;
$this->name = $name;
}
public function connection($name = null)
{
return $this->original->connection($this->name);
}
public function getDefaultConnection()
{
return $this->name;
}
}
In test use it like this
create a method called create() inside tests/TestCase.php
protected function create($attributes = [], $model = '', $route = '')
{
$this->withoutExceptionHandling();
$original = $model::getConnectionResolver();
$model::setConnectionResolver(new ConnectionResolver($original, 'testing'));
$response = $this->postJson($route, $attributes)->assertSuccessful();
$model = new $model;
$this->assertDatabaseHas('testing_db.'.$model->getTable(), $attributes);
$model::setConnectionResolver($original);
return $response;
}
and in actual test you can simply do this:
/** #test */
public function user_can_create_model(): void
{
$attributes = [
'name' => 'Test Name',
'title' => 'Test Title',
'description' => 'Test Description',
];
$model = Model::class;
$route = 'model_store_route';
$this->create($attributes, $model, $route);
}
Note: that test method can have only one line when using setUp() method and $this-> notation
And that's it. What this does is forcing the custom connection name (which should be written inside config/database.php) and the model during that call will work with that connection no matter what you specify inside the model, therefore it will store the data into DB which you have specified in $model::setConnectionResolver(new ConnectionResolver($original, 'HERE'));
This is tested for Laravel 8 & 9 and Super Simple.
Here is an example of switching the connection while testing.
In your model ->
class YourModel extends Model {
protected $connection = 'remote';
public function __construct(array $attributes = [])
{
if(config('app.env') === 'testing') {
$this->connection = 'sqlite';
}
parent::__construct($attributes);
}
}
In the Eloquent Model you have the following method.
/**
* Set the connection associated with the model.
*
* #param string|null $name
* #return $this
*/
public function setConnection($name)
{
$this->connection = $name;
return $this;
}
So you can just do
$user = new User();
$user->setConnection('connectionName')
One option would be to create a new environment file just for testing, that way you can overwrite the connection credentials only for your tests and you would not have to touch your models:
tests/CreatesApplication.php
public function createApplication()
{
$app = require __DIR__ . '/../bootstrap/app.php';
$app->loadEnvironmentFrom('.env.testing'); // add this
$app->make(Kernel::class)->bootstrap();
return $app;
}
Copy your .env file to .env.testing and change your database credentials for the connection global_connection to your test database credentials.
I am not sure how you configured your connection but it probably looks something like the following.
database.php
'global_connection' => [
'database' => env('DB_GLOBAL_DATABASE', ''),
'username' => env('DB_GLOBAL_USERNAME', ''),
'password' => env('DB_GLOBAL_PASSWORD', ''),
],
.env.testing:
DB_GLOBAL_DATABASE=database
DB_GLOBAL_USERNAME=username
DB_GLOBAL_PASSWORD=secret
Now you can use the global_connection connection but it will use your test database.
Additionally you could then remove all environment values from the phpunit.xml file and move them into the .env.testing file so you have all environment values for your tests in one place.
If you don't want to create a new environment file you could of course just update the values in your phpunit.xml file:
<php>
<server name="DB_GLOBAL_DATABASE" value="database"/>
<server name="DB_GLOBAL_USERNAME" value="username"/>
<server name="DB_GLOBAL_PASSWORD" value="password"/>
</php>
The most "magical" thing I suggest you could do is focus exclusively on the test and try to not modify the model at all:
/** #test */
public function user_can_create_some_model(): void
{
config([ "database.connections.global_connection" => [
'driver' => 'mysql', 'host' => x // basically override everything that is in config/database.php
]);
$attributes = [
'name' => 'Some Name',
'title' => 'Some Title',
];
$response = $this->postJson($this->route, $attributes)->assertSuccessful();
}
Hopefully when the configuration needs to be read the new one will be used.
If your global_connection configuration is read from the .env file you can also override the env variables in your test runner configuration (e.g. phpunit.xml)

Laravel seed issue, laravel is looking for plural table name

i've just started learning Laravel and I have problem generating seed for my test table.
Console error says:
"Base table or view not found: 1146 Table 'laravel.testms' doesn't exists..."
My table is called "testm" - I have no idea why it looks for testms
TestmFactory.php
use Faker\Generator as Faker;
$factory->define(App\Testm::class, function (Faker $faker) {
return [
'test' => $faker->paragraph
];
});
TestmTableSeeder.php
use Illuminate\Database\Seeder;
class TestmTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
factory(App\Testm::class, 5)->create();
}
}
DatabaseSeeder.php
public function run()
{
$this->call(LinksTableSeeder::class);
$this->call(TestmTableSeeder::class);
}
app/Testm.php
class Testm extends Model
{
// Below line fixed my code :-)
protected $table = 'testm';
protected $fillable = [
'test'
];
}
From Laravels documentation:
By convention, the "snake case", plural name of the class will be used as the table name unless another name is explicitly specified.
And in order to explicitly define the table name in the model, Testm.php in your case, you would want to add the following code to the class:
protected $table = 'testm';
Hope this helps!
Try adding this to your model
protected $table = 'testm';

SQLSTATE[42S02]: Base table or view not found: 1146 Table 'db.store' doesn't exist

When I try to save data from laravel form to a database table I am getting the following exception:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'db.store' doesn't exist (SQL: select count(*) as aggregate from store where name = samplename)
the table store exists but still I am getting the error
this is my contoller that is processing the form:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\storestore;
use App\Http\Requests\storeFormRequest;
class AddstoreController extends Controller
{
//
public function create()
{
//
}
public function store( storeFormRequest $request)
{
$store = new Store;
$store->name = Input::get('name');
$store->description = Input::get('description');
$store->store_vendor_id = Input::get('owner');
$store->contact_email = Input::get('contact_email');
$store->postal_address = Input::get('postal_address');
$store->city = Input::get('city');
$store->zip = Input::get('zip');
$store->phone = Input::get('phone');
$store->business_logo = Input::get('logo');
$store->save();
return \Redirect::route('add_store_success')
->with('message', 'Thanks for joining us!');
}
}
This is my Store model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Store extends Model
{
//
protected $table = 'stores';
protected $fillable = ['name', 'description', 'vendor_id',
'contact_email','postal_address','city','zip','phone',
'meta_description','business_logo'];
}
StoreRequest file:
<?php
namespace App\Http\Requests;
use App\Http\Requests\Request;
use App\StoreController;
class StoreFormRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
//
'name' => 'required|unique:dstore',
'vendor_id' => 'required',
'contact_email' => 'required|email|max:100|unique:dstore',
'business_logo' => 'required',
];
//validate
if ($validation->fails())
{
return redirect()->back()->withErrors($v->errors());
}
}
}
These are the get and post routes:
Route::get('/store_form', ['as' => 'add_store_form', 'uses' => 'StoreController#create']);
Route::post('/store_form',['as' => 'dstore', 'uses' => 'StoreController#store']);
Both routes are listed when I run php artisan route:list command
I have tried to goggle for solution but the one I landed on pointed out to missing tables as a course, but in my case the store table is existing but still I am getting the error.
Any help please!
Look at your Store model class:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Store extends Model
{
//
protected $table = 'stores';
protected $fillable = ['name', 'description', 'vendor_id',
'contact_email','postal_address','city','zip','phone',
'meta_description','business_logo'];
}
As you see property $table is set to stores so I assume table name in your database is stores and not store.
You should probably change in your StoreFormRequest content or rules method to use in unique rule valid table name, for example:
public function rules()
{
return [
//
'name' => 'required|unique:stores',
'vendor_id' => 'required',
'contact_email' => 'required|email|max:100|unique:stores',
'business_logo' => 'required',
];
//validate
if ($validation->fails())
{
return redirect()->back()->withErrors($v->errors());
}
}

Laravel 4 DatabaseSeed.php throws class not found

I have tried so much to get this database seed to work but I still get Class 'Account' not found even though I have namespaced where I should.
There error is thrown when running php artisan db:seed on $accountOut = Account::create(array( where Account is what is throwing the error. Am stating the using incorrectly? If I were to remove all the namespacing I have no issues at all.
My Account.php file:
<?php namespace App\Models;
class Account extends \Eloquent {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'account';
/**public function user()
{
return $this-belongsTo('User');
}*/
}
My seed file:
<?php
use App\Models;
class TransactionSeeder extends Seeder {
public function run()
{
DB::table('transaction')->delete();
DB::table('account')->delete();
$accountOut = Account::create(array(
'name' => 'Checking',
'origin' => 'Bank'
));
$accountIn = Account::create(array(
'name' => 'Stuff',
'origin' => 'Expense'
));
$adminUser = Sentry::getUserProvider()->findByLogin('admin#admin.com');
Transaction::create(array(
'account_id_in' => $accountIn->id,
'account_id_out' => $accountOut->id,
'amount' => 300.00
));
}
}
I feel really stupid but instead of calling out use App\Models you would call out use App\Models\Account and it works as it should.
Then remember to run php composer.phar dump-autoload
I've had similar issues and prefixing my classes with the namespace operator solved them.
Try \Account

Resources