Laravel migrate command always tries to create a migations table - laravel

I have the following code from an Artisan command that creates a new database:
public static function run($command)
{
$command->newLine();
$command->warn('Creating main database');
DB::disconnect('mysql');
// config(['database.connections.mysql.database' => '']);
DB::reconnect('mysql');
DB::statement('CREATE DATABASE IF NOT EXISTS `db`;');
DB::disconnect('mysql');
config(['database.connections.mysql.database' => 'manager']);
DB::reconnect('mysql');
$command->info('Database created');
$command->warn('Running migrations');
$command->call('migrate', [
'--path' => 'vendor/company/database/database/manager'
]);
$command->info('All migrations have been executed');
$command->warn('Inserting default record');
DB::table('customers')
->insert([
'name' => 'Customer',
'email' => 'customer#example.com.br',
'phone' => '55999999999',
'db_password' => Crypt::encryptString('pass'),
'modules' => 'basic,banners,dispatches,conversations',
'created_at' => now(),
'updated_at' => now(),
]);
$command->info('Record successfully inserted');
$command->info('Main database sucessfully created');
$command->newLine();
}
It works perfectly, but if I uncomment the line that is commented out, it starts showing an error that the migrations table already exists. If this line is commented out, it just tells you that there are no migrations to run.
I know it's something specific to me, but I'd like to understand why this single database name change is causing this error.

Related

Query parameter binding issue with illuminate/database and illuminate/queue

I'm using Illuminate\Queue outside of a Laravel app inside an add-on for a CMS. So the only instances of Laravel or Illuminate are these packages that I've required:
"illuminate/queue": "^8.83",
"illuminate/bus": "^8.83",
"illuminate/contracts": "^8.83"
I'm first trying to use the Database for the queue as the default driver since the CMS is database driven, then provide options to SQS etc. I've setup everything so the migrations create my queue tables and everything seems to be wired together when I make the following call to push something to the queue.
/** #var \Illuminate\Queue\QueueManager $queue */
$queue->push('test', ['foo' => 'bar']);
Then it ends in the following error. The parameter bindings are not working or something. It's leaving the ? in the values list.
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '"exp_dgq_jobs" ("queue", "attempts", "reserved_at", "available_at", "created_at"' at line 1 (SQL: insert into "exp_dgq_jobs" ("queue", "attempts", "reserved_at", "available_at", "created_at", "payload") values (default, 0, ?, 1674567590, 1674567590, {"uuid":"6bf7a17e-dda3-4fed-903a-8714e5a2d146","displayName":"test","job":"test","maxTries":null,"maxExceptions":null,"failOnTimeout":false,"backoff":null,"timeout":null,"data":{"foo":"bar"}}))
I've step debugged the whole request and it feels like a bug, but then again this is really the first time I've used Laravel or one of it's packages, so maybe I'm missing something? This function explicitly sets reserved_at to null, and the Connection->prepareBindings() method doesn't do anything with the ?, it just leaves it as that value, so the query fails.
protected function buildDatabaseRecord($queue, $payload, $availableAt, $attempts = 0)
{
return ['queue' => $queue, 'attempts' => $attempts, 'reserved_at' => null, 'available_at' => $availableAt, 'created_at' => $this->currentTime(), 'payload' => $payload];
}
What am I missing? Everything just looks right to me an I'm kind of at a loss. I'm making this with PHP 7.4 in mind (for the time being). Maybe I'll try 8.1 to see if that changes anything with the Illuminate packages. Using MySQL 8 too.
Update: potentially relevant screenshot just before the error.
Update 2: I tried PHP 8.1 and latest Laravel 9 packages, didn't make a difference.
For more clarity on how I"m creating my QueueManager:
<?php $queue = new Queue;
$queue->addConnection([
'driver' => 'database',
'table' => ee('db')->dbprefix . 'dgq_jobs',
'queue' => 'default',
'retry_after' => 90,
'after_commit' => false,
]);
$databaseConfig = $provider->make('DatabaseConfig');
$queue->addConnector('database', function () use ($databaseConfig) {
$pdo = new PDO(
sprintf('mysql:host=%s; dbname=%s', $databaseConfig['host'], $databaseConfig['database']),
$databaseConfig['username'],
$databaseConfig['password']
);
$connection = new Connection($pdo);
$connectionResolver = new ConnectionResolver(['default' => $connection]);
$connectionResolver->setDefaultConnection('default');
return new DatabaseConnector($connectionResolver);
});
return $queue->getQueueManager();
I was able to reproduce the error you were seeing. I haven't looked too deeply but I think it may be due to the PDO object not setting up the connection exactly as the Illuminate Queue library expects.
This modification to using the Illuminate\Database library to create the connection solved the issue in my test environment:
$database = new \Illuminate\Database\Capsule\Manager;
$queue = new \Illuminate\Queue\Capsule\Manager;
$database->addConnection([
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'db_name',
'username' => 'username',
'password' => '',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
]);
$queue->addConnector('database', function () use ($database) {
$connection = $database->getConnection();
$connectionResolver = new \Illuminate\Database\ConnectionResolver(['default' => $connection]);
$connectionResolver->setDefaultConnection('default');
return new \Illuminate\Queue\Connectors\DatabaseConnector($connectionResolver);
});
$queue->addConnection([
'driver' => 'database',
'table' => 'jobs_table',
'queue' => 'default',
'retry_after' => 90,
'after_commit' => false,
]);
$queue->getQueueManager()->push('SendEmail', ['message' => 'test']);

Laravel Excel Not Importing Data To Database [duplicate]

This question already has answers here:
Laravel 5.4 field doesn't have a default value
(10 answers)
Closed last year.
This post was edited and submitted for review last year and failed to reopen the post:
Original close reason(s) were not resolved
When I am importing data from excel after getting the file and on the step of saving data to db it showing field doesn't have value from excel file. Where as all the fields are filled with data.
i am using laravel excel
LeadImport Code
return new lead([
'name' => $row[0],
'leadid' => $row[1],
'number' => $row[2],
'city' => $row[3],
'state' => $row[4],
'address' => $row[5],
'pincode' => $row[6],
'type' => $row[7],
]);
Controller Code
Excel::import(new LeadsImport, $request->file('file'));
Error
SQLSTATE[HY000]: General error: 1364 Field 'leadid' doesn't have a default value (SQL: insert into `leads` (`updated_at`, `created_at`) values (2022-01-14 19:24:21, 2022-01-14 19:24:21))
The leadid don't have any assigned value and it doesn't have any default value assigned. What is $row[1] returning? I assume row[1]'s value is null, that's why you actually get this error. dd() it and tell us what it returns.
in your excel file you must have cells:
name, leadid, number, city, state, address, pincode, type
and in LeadImport just:
return new lead([
'name' => $row['name'],
'leadid' => $row['leadid'],
'number' => $row['number'],
'city' => $row['city'],
'state' => $row['state'],
'address' => $row['address'],
'pincode' => $row['pincode'],
'type' => $row['type'],
]);

Laravel Insert Seed if data doesn't already exist

Is there any way to run a laravel seed to only insert the records if they do not exist already?
My current laravel seeder looks like this
DB::table('users')->insert([
//Global Admin
[
'member_id' => 11111111,
'firstname' => 'Joe',
'lastname' => 'Bloggs'
],
[
'member_id' => 22222222,
'firstname' => 'Jim',
'lastname' => 'Bloggs'
],
]);
Pretty standard!
would I have to wrap each and every insert in a try catch? like this
try {
DB::table('users')->insert(['member_id' => 11111111, 'firstname' => 'Joe', 'lastname' => 'Bloggs']);
} catch(Exception $e){
//Die silently
}
try {
DB::table('users')->insert(['member_id' => 22222222, 'firstname' => 'Jim', 'lastname' => 'Bloggs']);
} catch(Exception $e){
//Die silently
}
Later on I might want to add extra rows to the same seeder without having to write a new one, and re run php artisan db:seed to only add my new rows.
Is this possible?
You can achieve this by Eloquent firstOrCreate.
The firstOrCreate method will attempt to locate a database record
using the given column / value pairs. If the model can not be found in
the database, a record will be inserted with the attributes from the
first parameter, along with those in the optional second parameter.
So, if you identify the user by member_id, you can do something like this:
User::firstOrCreate(
['member_id' => 11111111],
[
'firstname' => 'anakin',
'lastname' => 'skywalker',
'password' => Hash::make('4nak1n')
]
);
If you want to locate the record by 'member_id', 'firstname' and 'lastname' fields, something like this:
User::firstOrCreate(
[
'member_id' => 11111111,
'firstname' => 'anakin',
'lastname' => 'skywalker'
],
[
'password' => Hash::make('4nak1n'),
]
);
As stokoe0990 stated, it is not advisable to run seeders in production. The Laravel Seeder was written as way to generate test data. Per the documentation "Laravel includes a simple method of seeding your database with test data using seed classes".
That said, The only way you can satisfy your question is to build the logic into your seed:
$users = array(
['member_id' => 11111111,'firstname' => 'Joe','lastname' => 'Bloggs'],
['member_id' => 22222222,'firstname' => 'Jim','lastname' => 'Bloggs']
);
foreach ($users as $user) {
if (\App\User::find($user['id'])) {
DB::table('users')->insert($user);
}
}
Seeding is only supposed to be used for testing, anyways.
Why don't you just execute php artisan migrate:fresh --seed?
This will refresh your database (deletes the tables) then runs all your migrations again and finally seeds the database again.
You should never be using seeders in production.
Just add the new data to your seeder, run migrate:fresh and re-seed :)
You can achieve that by using Eloquent updateOrInsert() method:
DB::table('users')->updateOrInsert('your_data');
Read more about it here.
The best I recommend is to truncate (or delete all) the data in the table anytime you migrate. Try something like this:
//data in the table
DB::table('users')->delete(); //or use model like this: User::truncate();
DB::table('users')->insert([
//Global Admin
[
'member_id' => 11111111,
'firstname' => 'Joe',
'lastname' => 'Bloggs'
],
[
'member_id' => 22222222,
'firstname' => 'Jim',
'lastname' => 'Bloggs'
],
]);
Then there will be no duplications when you run php artisan db:seed

[cakePHP3]how to debug a failed save

This is my code , I have problems with making a simple save. The message is :( when i trying to save
$user = $this->Users->newEntity();
if($this->request->is('post'))
{
$user = $this->Users->patchEntity($user, $this->request->data);
if($this->Users->save($user))
{
$this->Flash->success(':)');
return $this->redirect(['controller' => 'Users', 'action' => 'index']);
}
else
{
$this->Flash->error(':(');
}
debug($this->request->data);
}
$this->set(compact('user'));
this is my table , I made a migration. All fields can be null
$table = $this->table('users');
$table->addColumn('first_name','string',array('limit'=>100))
->addColumn('last_name','string',array('limit'=>100))
->addColumn('email','string',array('limit'=>100))
->addColumn('password','string')
->addColumn('role','enum',array('values'=>'admin,user'))
->addColumn('active','boolean')
->addColumn('created','datetime')
->addColumn('modified','datetime')
->create();
this is my request data
[
'first_name' => 'wewe',
'last_name' => 'wewe',
'email' => 'wewe#wee.com',
'password' => 'wewewe',
'role' => 'admin',
'active' => '1'
]
I hope that you help me , I am very frustrated
EDIT: if i use print_r ($user->errors()); i get this...
Array ( [firts_name] => Array ( [_required] => This field is required ) )
Your error is in the name of your data, the request data is
'first_name' => 'wewe'"
your column name is "firts_name", its a typing error.

Will Model::updateOrCreate() update a soft-deleted model if the criteria matches?

Let's say I have a model that was soft-deleted and have the following scenario:
// EXISTING soft-deleted Model's properties
$model = [
'id' => 50,
'app_id' => 132435,
'name' => 'Joe Original',
'deleted_at' => '2015-01-01 00:00:00'
];
// Some new properties
$properties = [
'app_id' => 132435,
'name' => 'Joe Updated',
];
Model::updateOrCreate(
['app_id' => $properties['app_id']],
$properties
);
Is Joe Original now Joe Updated?
OR is there a deleted record and a new Joe Updated record?
$variable = YourModel::withTrashed()->updateOrCreate(
['whereAttributes' => $attributes1, 'anotherWhereAttributes' => $attributes2],
[
'createAttributes' => $attributes1,
'createAttributes' => $attributes2,
'createAttributes' => $attributes3,
'deleted_at' => null,
]
);
create a new OR update an exsiting that was soft deleted AND reset the softDelete to NULL
updateOrCreate will look for model with deleted_at equal to NULL so it won't find a soft-deleted model. However, because it won't find it will try to create a new one resulting in duplicates, which is probably not what you need.
BTW, you have an error in your code. Model::updateOrCreate takes array as first argument.
RoleUser::onlyTrashed()->updateOrCreate(
[
'role_id' => $roleId,
'user_id' => $user->id
],
[
'deleted_at' => NULL,
'updated_at' => new \DateTime()
])->restore();
Like this you create a new OR update an exsiting that was soft deleted AND reset the softDelete to NULL
Model::withTrashed()->updateOrCreate([
'foo' => $foo,
'bar' => $bar
], [
'baz' => $baz,
'deleted_at' => NULL
]);
Works as expected (Laravel 5.7) - updates an existing record and "undeletes" it.
I tested the solution by #mathieu-dierckxwith Laravel 5.3 and MySql
If the model to update has no changes (i.e. you are trying to update with the same old values) the updateOrCreate method returns null and the restore() gives a Illegal offset type in isset or empty
I got it working by adding withTrashed so that it will include soft-deleted items when it tries to update or create. Make sure deleted_at is in the fillable array of your model.
$model = UserRole::withTrashed()->updateOrCreate([
'creator_id' => $creator->id,
'user_id' => $user->id,
'role_id' => $role->id,
],[
'deleted_at' => NULL
])->fresh();
try this logic..
foreach ($harga as $key => $value) {
$flight = salesprice::updateOrCreate(
['customerID' => $value['customerID'],'productID' => $value['productID'], 'productCode' => $value['productCode']],
['price' => $value['price']]
);
}
it work for me

Resources