ErrorException running php artisan vendor:publish with Elqouent-Sluggable - laravel-5

I'm using Laravel 5 and attempting to install Eloquent-Sluggable. I have followed all the steps in the installation instructions:
composer require cviebrock/eloquent-sluggable
composer update
Add Cviebrock\EloquentSluggable\SluggableServiceProvider::class to the Providers in config/app.php
php artisan vendor:publish
The last step resulted in this error message:
[ErrorException] Argument 2 passed to
Cviebrock\EloquentSluggable\SluggableTableCommand::__construct() must be an instance of Illuminate\Foundation\Composer, instance of
Illuminate\Support\Composer given, called in
C:\wamp\www\blog\vendor\cvi
ebrock\eloquent-sluggable\src\SluggableServiceProvider.php on line 92 and defined
What caused the error to occur?

It happened to me too. This is because the SluggableTableCommand requires Composer instance in its constructor but accidentally different type of instance is passed.
This might not be the smartest way to fix this but if you are in rush you can just remove the Composer declaration before $composer in the SluggableTableCommand constructor. The file that you need to edit is vendor/cviebrock/eloquent-sluggable/src/SluggableTableCommand.php on line 44
This should work:
/**
* Create a new migration sluggable instance.
*
* #param SluggableMigrationCreator $creator
* #param Composer $composer
*/
public function __construct(
SluggableMigrationCreator $creator,
$composer
) {
parent::__construct();
$this->creator = $creator;
$this->composer = $composer;
}

I had the same error using Laravel 5.2.29 when I tried to create migration via console command
php artisan sluggable:table posts slug
What solved the issue was creation usual Laravel migration, but I had commented 'Cviebrock\EloquentSluggable\SluggableServiceProvider::class' row in config/app.php file before.
php artisan make:migration add_slug_to_posts_table
with the next code in migration file
public function up(){
Schema::table('posts', function(Blueprint $table){
$table->string('slug')->nullable();
});
}
public function down(){
Schema::table('posts', function(Blueprint $table){
$table->dropColumn('slug');
});
}
and ran the migration
php artisan migrate

Related

Laravel: how to simplify artisan commands?

I want to simplify the following artisan commands because I have several databases and the migrations for each database are stored in a separate folder.
php artisan make:migration {{name}} --path=/database/migrations/{{folder}}
php artisan migrate:rollback --path=/database/migrations/{{folder}}
to
php artisan make:migration {{name}} {{folder}}
php artisan migrate:rollback {{folder}}
Is this possible and if so how can I implement it?
Since this is not an option in the Laravel commands, a way to implement this yourself is by writing you own commands that call other artisan commands.
To do so, in your terminal write, for example, php artisan make:command MigrateWithPath to create a new command at app/Console/Commands/MigrateWithPath.php. Then, you can call the vanilla implementation Laravel provides at (vendor\laravel\framework\src) \Illuminate\Database\Console\Migrations\MigrateMakeCommand but then in a way that you specify.
Be sure though that the name of your new command needs to be different from the Laravel one, to prevent recursions. Therefore, I have prefixed the name with app: to be like app:make:migration, but feel free to use something else.
Take a look at the following suggestion:
class MigrateWithPath extends BaseCommand
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'app:make:migration {name : The name of the migration}
{folder? : The location where the migration file should be created}';
/**
* Execute the console command.
*
* #return int
*/
public function handle()
{
$this->call('make:migration', [
'name' => $this->argument('name'),
'--path' => '/database/migrations/' . $this->argument('folder'),
]);
return 0;
}
Then do the same for the rollback command.

Why does php artisan migrate fresh --seed is not working properly

Hi developers i have question regarding on php artisan migrate:refresh --seed VS php artisan db:seed I just wanted to ask because I have problem on php artisan migrate:refresh --seed, however when I use the php artisan db::seed it works properly
Now the data that I Created on my seeder is not seeding to the tables. I don't know why where the problem came from
Seeding: VehicleModelsSeeder
Seeded: VehicleModelsSeeder (0 seconds)
Here is my vehicle model seeder class
<?php
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use App\Vehicle;
use App\VehicleModel;
class VehicleModelsSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
//
$vehicles = Vehicle::all();
foreach($vehicles as $vehicles_data) {
VehicleModel::forceCreate([
'name' => Str::random(5),
'vehicle_id' => $vehicles_data->id
]);
}
}
}
By default, the db:seed command runs the Database\Seeders\DatabaseSeeder class.
There is two solutions:
1. You need to call your additional seeder(s) in the default seeder's run method.
database/seeders/DatabaseSeeder.php
public function run()
{
$this->call([
VehicleModelsSeeder::class
]);
}
Then:
php artisan migrate:refresh --seed
2. You can specify which seeder you want to run with the --class flag, but in this case you need to run the refresh and the migrate commands separately:
php artisan migrate:refresh
php artisan db:seed --class:VehicleModelsSeeder
More info: Laravel database seeding documentation

Laravel & PostGres - Migration down() will not drop table (TimeScaleDB Extension)

Here is what create_facts_table looks like:
class CreateFactsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::connection('pgsql')->create('facts', function (Blueprint $table) {
$table->bigInteger('entry_id');
$table->string('tag');
$table->timestampTz('time');
$table->double('sensor_value');
$table->index(['entry_id', 'tag', 'time']);
$table->unique(['entry_id', 'tag', 'time']);
});
DB::connection('pgsql')->statement('SELECT create_hypertable(\'facts\', \'time\');');
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
// Tried both, neither would delete the table
Schema::connection('pgsql')->dropIfExists('facts');
//DB::connection('pgsql')->statement('DROP TABLE facts;');
}
}
I don't get any error from down(). I am able to login as the DB user specified in my .env file and run DROP TABLE facts.
When I run php artisan migration:fresh up() fails to create the table and throws a duplicate table error:
Duplicate table: 7 ERROR: relation "facts" already exists
After manually deleting the table, I can then run php artisan migration:fresh. I must specify connection('pgsql') as I'm using multiple databases. Semi-unrelated, but I'm using TimeScaleDB extension (hence create_hypertable())
I dug a bit deeper on this recently. I hadn't directly mentioned I was using the TimeScaleDB extension ('SELECT create_hypertable(\'facts\', \'time\');').
I updated the title of the question incase someone lands here from Google in the future.
Here is what I have learned:
When php artisan migration:fresh is run, it attempts to drop all tables in batch and does not use the down() method. TimeScaleDB hypertables cannot be deleted in batch.
The solution is to use php artisan migration:refresh instead which will run the defined drop() operations for each table.
Source: https://stackoverflow.com/a/69105447/5449796

Can we create a migration for the data, not just structure of the tables

I love laravel because of the ability to create migrations.
From what I understood, laravel gives us the capability to create a migration where we can repeat the same process without having to create tables and structures manually.
My Question:
Similarly,
1) If I want that my data (inputs to the table) is also stored in some way, so that whenever i change the data in the database, that can also be reverted back or the whole process can also be recreated.
2) If 1 is not possible then can we have a way to save the methods for the "initial" seeding of the database. (so when we "factory" reset the whole thing, it can also automatically populate the content of the database, not just the structure of the database)
Any references for the same please?
I hope I was able to make myself clear!
You're correct in assuming Laravel is incredible! So with respect to your first question.
1) If I want that my data (inputs to the table) are also stored in some way, so that whenever i change the data in the database, that can also be reverted back or the whole process can also be recreated.
If you you want to recreate the data you will need to create a table seeder. To do this, simply create a seeder and a factory with artisan.
php artisan make:seeder UsersTableSeeder
After making your seeder you can run it this with command:
composer dump-autoload && php artisan db:seed
If you wanted to create Controllers, Seeders and Factories at the same time when you make a model type this artisan command.
php artisan make:model User -fa
You can see more on the Laravel documentation for creating seeders and factories here.
Instead of messing with your migration files, I would create seeders. Here is a couple examples.
Exhibit 1 - Example of a an Article Factory (database/factories/ArticleFactory.php)
<?php
use Faker\Generator as Faker;
$factory->define(App\Article::class, function (Faker $faker) {
return [
'title' => $faker->text(50),
'slug' => $faker->unique()->slug,
'body' => $faker->text(200),
'user_id' => rand(1,10),
];
});
Exhibit 2 - Example of an Article Seeder (database/seeds/ArticleTableSeeder.php)
<?php
use Illuminate\Database\Seeder;
class ArticlesTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
factory(App\Article::class, 10)->create();
}
}
Exhibit 3 - Example of an Article Migration (database/migrations/2018_05_13_create_articles_table.php)
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateArticlesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('articles', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->text('body');
$table->string('slug');
$table->integer('media_id')->nullable();
$table->integer('user_id')->nullable(); // Owner of Article
$table->timestamps();
$table->softDeletes();
$table->index('slug');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('articles');
}
}
Exhibit 4 - DatabaseTableSeeder.php
<?php
use Illuminate\Database\Seeder;
use Illuminate\Database\Eloquent\Model;
use Faker\Factory as Faker;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*
* #return void
*/
public function run()
{
// Disable all mass assignment restrictions
Model::unguard();
// Seeds the Articles
$this->call(ArticlesTableSeeder::class);
Then to do a complete factory reset, all you need to do is type the following artisan command:
php artisan migrate:db --fresh
php artisan db:seed
Answer 1) Yes you can manually automatically insert your data into your tables each time you run your migrations.
Answer 2) Question one is possible
Example:
public function up()
{
// Create the table
Schema::create('users', function($table){
$table->increments('id');
$table->string('email', 255);
$table->string('password', 64);
$table->boolean('verified');
$table->string('token', 255);
$table->timestamps();
});
// Insert some stuff
DB::table('users')->insert(
array(
'email' => 'name#domain.com',
'verified' => true
)
);
}
Although you can do data migrations by both using a migration file or a seeder file (as explained in the above answers), from experience I strongly recommend that you put such migration code inside a seeder file, not a migration file.
The reason being is that it's very difficult to run a single file migration. Migrations are designed to run all at once, or to run migrations in step by step sequence since the last migration was done, migrations are not designed to be cherry picked individually, see migration help:
php artisan migrate --help
Usage:
migrate [options]
Options:
--database[=DATABASE] The database connection to use.
--force Force the operation to run when in production.
--path[=PATH] The path of migrations files to be executed.
--pretend Dump the SQL queries that would be run.
--seed Indicates if the seed task should be re-run.
--step Force the migrations to be run so they can be rolled back individually.
-h, --help Display this help message
-q, --quiet Do not output any message
-V, --version Display this application version
--ansi Force ANSI output
--no-ansi Disable ANSI output
-n, --no-interaction Do not ask any interactive question
--env[=ENV] The environment the command should run under
-v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
Help:
Run the database migrations
you will notice that there is no option available to run a handpicked migration, something that you may want to do some day with your data migration (example: suppose you simply want to take data from one legacy table to another table, think of it as moving data from a transactional database to an analytics database using a nightly cron job or something).
This option is however available in a seeder:
php artisan db:seed --help
Usage:
db:seed [options]
Options:
--class[=CLASS] The class name of the root seeder [default:
which makes it much more flexible than a migration (not to mention that seeding data is all about data, which is more appropriate for your task)

Errors in migration when installing the Laravel Voyager package

i have i brand new installation of Laravel 5.5, but when i try to install the Voyager admin panel i have this error :
[Illuminate\Database\QueryException]
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 1000 bytes (SQL: alter table `translations` add unique `translati
ons_table_name_column_name_foreign_key_locale_unique`(`table_name`, `column_name`, `foreign_key`, `locale`))
Config
PHP version : 7.0.10
MYSQL version : 5.7.14
CODE UPDATE
I think i have found the concerned code :
Schema::create('translations', function (Blueprint $table) {
$table->increments('id');
$table->string('table_name');
$table->string('column_name');
$table->integer('foreign_key')->unsigned();
$table->string('locale');
$table->text('value');
$table->unique(['table_name', 'column_name', 'foreign_key', 'locale']); // SOURCE OF THE ERROR ?
});
You need to Update the "config/database.php" for 'mysql'.
'engine' => null
To
'engine' => 'InnoDB ROW_FORMAT=DYNAMIC',
also Update the "app/Providers/AppServiceProvider.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()
{
// Specified key was too long error, Laravel News post:
Schema::defaultStringLength(191);
}
/**
* Register any application services.
*
* #return void
*/
public function register()
{
//
}
}
and run these commands in your project folder.
php artisan cache:clear
php artisan config:clear
php artisan voyager:install --with-dummy
The total length of your index is too long.
The column on which the unique index is added shouldn't be such long like VARCHAR columns, because the index will be very bulky and inefficient.
This is a known issue.
If you do not use the muli-language features from Voyager simply uncomment the line in *******************_create_translations_table
// $table->unique(['table_name', 'column_name', 'foreign_key', 'locale']);
or try to update your MySql Database to 7.x

Resources