laravel 5.7 nested sets - laravel

I tried to seed nested set with array with Laravel 5.7 and https://github.com/lazychaser/laravel-nestedset package but always getting :
Array to string conversion error when function gets to main node children.
I am testing on example provided on github and cannot make it create tree with nested nodes from array when seeding.
$node = Category::create([
'name' => 'Foo',
'children' => [
[
'name' => 'Bar',
'children' => [
[ 'name' => 'Baz' ],
],
],
],
]);
Can anyone suggest how can I seed the database table or some other package like baum which is working with laravel 5.7 ?
Thank you !

I succeed to make this work, so for laravel 5.7 here are the steps :
create new laravel project, set db params in .env : composer create-project laravel/laravel nestedset
from nested set run : composer require kalnoy/nestedset
run : php artisan make:model NestedSetModel -m
change app/NestedSetModel.php code to:
namespace App;
use Kalnoy\Nestedset\NodeTrait;
use Illuminate\Database\Eloquent\Model;
class NestedSetModel extends Model
{
use NodeTrait;
}
change database/migrations/xxxx_xx_xx_xxxxxx_create_nested_set_models_table.php to:
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateNestedSetModelsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('nested_set_models', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->nestedSet();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('nested_set_models');
}
}
run : php artisan make:seeder NestedSetTableSeeder
change database/seeds/NestedSetTableSeeder.php to
<?php
use Illuminate\Database\Seeder;
class NestedSetTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
$node = App\NestedSetModel::create([
'name' => 'Foo',
'children' => [
[
'name' => 'Bar',
'children' => [
['name' => 'Baz'],
],
],
],
]);
}
}
run : php artisan migrate
run : php artisan db:seed
You should be able to see new table in your database properly seeded.
1 Foo 1 6 2018-12-03 16:54:20 2018-12-03 16:54:20
2 Bar 2 5 1 2018-12-03 16:54:20 2018-12-03 16:54:20
3 Baz 3 4 2 2018-12-03 16:54:20 2018-12-03 16:54:20

Related

How do I insert data in Laravel database from controller?

this is my first post in this forum and also I'm a very new user with Laravel.
I'm trying to do a very simple thing like creating an array and visualize the data inside in my database. The code works but I cant see the data in the database table. It might look easy but for some reason I've been a whole day with this thing so I'll appreciate a lot any help I can receive. This is how the code looks right now:
Controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Client;
use App\Http\Controllers\Controller;
class ClientController extends Controller
{
public function index()
{
DB::table('clients')->insert(
array(
'id' => 1,
'name' => 'Josh',
'age' => 45,
'gender' => 'M',
'nationality' => 'UK',
'job' => 'a',
)
);
}
}
Model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Client extends Model
{
use HasFactory;
protected $fillable = [
'name', 'age', 'gender', 'nationality', 'job',
];
}
Migration:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateClientsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('clients', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->integer('age');
$table->string('gender');
$table->string('nationality');
$table->string('job');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('clients');
}
}
First of all in your migration change this line:
$table->bigIncrements('id');
with
$table->id();
Once you have migrated it with:
php artisan migrate:fresh (empty database and recreate it)
Insert a record with:
public function index()
{
Client::create([
'name' => 'Josh',
'age' => 45,
'gender' => 'M',
'nationality' => 'UK',
'job' => 'a',
]);
}
There is no need to populate the id. Laravel (MySQL) will do it for you.
Maybe you do not need "," at the end of the array
protected $fillable = [
'name', 'age', 'gender', 'nationality', 'job',
];

Empty table after seeding in laravel8?

I just started working with Laravel and i'm trying to seed my DB. I have a many to many relationship between the users and shops table.
When i'm running php artisan DB:seed the seeder for shops isn't running. And if i run php artisan db:seed --class=ShopsTableSeeder i'm getting an Error SQLSTATE[HY000]: General error: 1364 Field 'user_id' doesn't have a default value
The factory file :
<?php
/** #var \Illuminate\Database\Eloquent\Factory $factory */
use App\Models\Shop;
$factory->define(Shop::class, function () {
$faker = Faker\Factory::create('fr_FR');
return [
'title' => $faker->text($maxNbChars = 20),
'description' => $faker->text(250),
...
'phone' => $faker->phoneNumber,
'active_until' => $faker->dateTimeBetween('+0 days', '+2 years'),
];
});
And the seeding file :
<?php
namespace Database\Seeders;
use App\Models\Shop;
use App\Models\User;
use Illuminate\Database\Seeder;
class ShopsTableSeeder extends Seeder
{
public function run()
{
factory(Shop::class, 10)->create();
foreach (Shop::all() as $shop){
$users = User::inRandomOrder()->take(rand(1,3))->pluck('id');
$shop->users()->attach($users);
}
}
}
how can i set the column user_id in the factory to connect a shop to user ?

Getting class does not exist error when running database seeder

I am creating a seeder in laravel 6.1 but I keep getting this error
Illuminate\Contracts\Container\BindingResolutionException : Target class [AdminsTableSeeder] does not exist.
I tried running composer dump-autoload and composer dumpautoload, it doesn't work for me.
here is my AdminsTableSeeder.php
use App\Models\Admin;
use Faker\Factory as Faker;
use Illuminate\Database\Seeder;
class AdminsTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
$faker = Faker::create();
Admin::create([
'name' => $faker->name,
'email' => 'admin#admin.com',
'password' => bcrypt('password'),
]);
}
}
and here is my DatabaseSeeder.php
<?php
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*
* #return void
*/
public function run()
{
$this->call(AdminsTableSeeder::class);
}
}
Make sure your AdminsTableSeeder.php file is in the same directory where you have your DatabaseSeeder.php file.
Run
composer dump-autoload
then try
php artisan db:seed
Optional.
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*
* #return void
*/
public function run(){
$this->call('AdminsTableSeeder');
}
}
try with $this->call('AdminsTableSeeder'); like this.
In your case, move all seeder files from previous database/seeds directory to database/seeders folder & then run composer dump-autoload.
Remember, from laravel 8 seeders and factories are namespaced
To accommodate for these changes,
[1] - Add Database\Seeders namespace to your seeder classes.
namespace Database\Seeders;
[2] - Move all seeder files to database/seeders folder.
[3] - If you import any seeders classes in DatabaseSeeder file then remove all of them. (simply remove all lines that started with use Database\Seeders\... from DatabaseSeeder.php)
[4] - Finally run dump-autoload.
composer dump-autoload
You can now try a fresh migration with seed,
php artisan migrate:fresh --seed
For my case(I use Laravel 8), I solved my problem by modifying the RouteServiceProvider.php file in App/Providers/ path. I uncommented code on line 29.
protected $namespace = 'App\\Http\\Controllers';
It worked for me.
run
composer dump-autoload
then try
php artisan db:seed
For Laravel 8:
I have the same issue and I found a solution in Laravel doc and it's worked for me.
https://laravel.com/docs/8.x/upgrade#seeder-factory-namespaces
Update Composer:
"autoload": {
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/"
}
}
Run:
composer dumpautoload
php artisan db:seed --force
Concerning my case, I used the latest Laravel 8 which is the latest version, I solved my problem by changing the RouteServiceProvider.php file in App/Providers/ path by uncommenting the code on line 29.
protected $namespace = 'App\Http\Controllers';
For Laravel ^7.0
If your using Laravel Eloquent
Example:
<?php
use App\Models\User;
use Illuminate\Database\Seeder;
class UsersTableSeeder extends Seeder
{
public function run()
{
$users = [
[
'id' => 1,
'name' => 'Admin',
'email' => 'admin#admin.com',
'password' => bcrypt('password'),
'remember_token' => null,
],
];
User::insert($users);
}
}
If your using Laravel Query Builder
Example:
<?php
//Do not use -> namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class UsersTableSeeder extends Seeder
{
public function run()
{
DB::table('users')->insert([
'name' => 'Admin',
'email' => 'admin#admin.com',
'password' => bcrypt('password'),
'remember_token' => null,
]);
}
}
In your DatabaseSeeder.php
<?php
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
public function run()
{
$this->call([
UsersTableSeeder::class,
]);
}
}
Seems like the controller name is case-sensitive in Laravel 8. So my suggestion is to double-check the controller name.
For instance:
in web.php avoid calling
UserAPIController
as
UserApiController
(API as api)
It may fix this error.
In your DatabaseSeeder.php, you can add the nameSpace for AdminsTableSeeder like -
use App\Models\Admin\AdminsTableSeeder;
Closing the current running serve before doing db:seeds

How can test a function that gets data from DB in a Laravel 5 package?

I'm working on a Laravel 5 package, and writing tests I'm trying to test a function that gets datas from DB.
public function getPhotoDatasFromDb()
{
$ret = GalleryImage::get()->keyBy('file_name');
return $ret;
}
The returned values should be in this format:
Collection {#416 ▼
#items: array:2 [▼
"IMG_1979.jpg" => GalleryImage {#423 ▼}
"alt_text" => "example alt text"
"description" => "lorem ipsum"
"IMG_1980.jpg" => GalleryImage {#424 ▶}
]
}
I had already experiences with testing database testing in other Laravel applications.
My question is: since I'm writing a package, and in the dev environment I don't have an instance of the DB I'm wondering what is the best approach to test it?
If can help to have a wider picture, the database table gets created in the application trough this migration:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateGalleryImagesTable extends Migration
{
public function up()
{
Schema::create('gallery_images', function (Blueprint $table) {
$table->increments('id');
$table->string('file_name')->unique();
$table->text('description')->nullable();
$table->string('alt')->nullable();
$table->string('video_link')->nullable();
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('gallery_images');
}
}
And this is the model associated
<?php
namespace DavideCasiraghi\ResponsiveGallery;
use Illuminate\Database\Eloquent\Model;
class GalleryImage extends Model
{
protected $fillable = [
'file_name', 'description', 'alt', 'video_link',
];
}
I found the solution myself.
I post it in case it can be helpful for somebody else.
This is my test:
/** #test */
public function it_gets_photos_from_db()
{
$gallery = new ResponsiveGalleryFactory();
$dbImageDatas = $gallery->getPhotoDatasFromDb();
$this->assertStringContainsString($dbImageDatas['DSC_9470.jpg']->description, 'Photo description');
}
To make it work I had to configure the DB in the beginning of the testing class:
/**
* Create the tables this model needs for testing.
*/
public static function setUpBeforeClass() : void
{
$capsule = new Capsule;
$capsule->addConnection([
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => '',
]);
$capsule->setAsGlobal();
$capsule->bootEloquent();
Capsule::schema()->create('gallery_images', function (Blueprint $table) {
$table->increments('id');
$table->string('file_name')->unique();
$table->text('description')->nullable();
$table->string('alt')->nullable();
$table->string('video_link')->nullable();
$table->timestamps();
});
Model::unguard();
GalleryImage::create([
'file_name' => 'DSC_9470.jpg',
'description' => 'Photo description',
'alt_text' => 'Photo alt text',
'video_link' => 'https://www.youtube.com/fsda234',
]);
}

MorphMap is not working in Laravel 5.6

I am using Polymorphic relationship in my models and with polymorphic relations I want to use Moprph map. To implement the concept of morph map I wrote my own service provider and registered it in app.php. Everything is working fine except Morph map. Morphmap is not working even with AppServiceProvider. Please have a look on my code
Service Provider
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Database\Eloquent\Relations\Relation;
class MorphServiceProvider extends ServiceProvider
{
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
Relation::morphMap([
'First' => FirstModel::class,
'Second' => SecondModel::class,
'Third' => ThirdModel::class
]);
}
/**
* Register services.
*
* #return void
*/
public function register()
{
//
}
}
I ran into this situation too. Finally I solved this problem by running artisan command:
php artisan cache:clear
The Reason Why MorphMap is not working
The new custom service is not loaded. Check bootstrap/cache/services.php to see if the new ServiceProvider is in the array of providers
<?php return array (
'providers' =>
array (
0 => 'Illuminate\\Auth\\AuthServiceProvider',
1 => 'Illuminate\\Broadcasting\\BroadcastServiceProvider',
2 => 'Illuminate\\Bus\\BusServiceProvider',
3 => 'Illuminate\\Cache\\CacheServiceProvider',
4 => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
5 => 'Illuminate\\Cookie\\CookieServiceProvider',
6 => 'Illuminate\\Database\\DatabaseServiceProvider',
7 => 'Illuminate\\Encryption\\EncryptionServiceProvider',
8 => 'Illuminate\\Filesystem\\FilesystemServiceProvider',
//...
By default this file should update automatically after the app.php has been altered.
In my situation, I accidentally ran the command php artisan config:cache before. This prevent the services.php from updating. Further Reference:
Laravel Doc: Configuration
Why caching config would prevent services.php from updating
check bootstrap/cache/config.php, look inside what's in there. providers is part of application config
check Illuminate\Foundation\Http\Kernel
protected $bootstrappers = [
\Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
\Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
\Illuminate\Foundation\Bootstrap\HandleExceptions::class,
\Illuminate\Foundation\Bootstrap\RegisterFacades::class,
\Illuminate\Foundation\Bootstrap\RegisterProviders::class,
\Illuminate\Foundation\Bootstrap\BootProviders::class,
];
check Illuminate\Foundation\Bootstrap\LoadConfiguration
check Illuminate\Foundation\Application, registerConfiguredProviders
Finally, I have to say that I am quite new to laravel. If I made some mistakes, let me know. Thank you.

Resources