Laravel DB Config, Adding Periods to Prefix - php

In my Laravel 5 config/database.php file I have the following driver defined.
'Portal' => [
'driver' => 'sqlsrv',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_PORTAL', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'prefix' => 'Portal.dbo.',
],
When I add a period . in the prefix (currently set to Portal.dbo.), I get a white screen with no exception or stack trace information. I have enabled DB logging, but the page stops loading before any logging can take place. When I remove the . from the prefix, everything appends correctly to the query as it should.
I need to prefix my queries in such a way because I have more than one databases on the same SQL Server that I want to run Joins between. How can I use periods in my prefix without Laravel crashing?

Related

Laravel migration error - could not find driver - Illuminate\Database\QueryException

I'm trying to run a migration following this tutorial https://www.youtube.com/watch?v=074AQVmvvdg&list=PL4cUxeGkcC9hL6aCFKyagrT1RCfVN4w2Q&index=13
I think the tutorial might be out of date because when I enter php artisan migrate; I get this error:
Illuminate\Database\QueryException
could not find driver (SQL: select * from information_schema.tables where table_schema = pizzahouse and table_name = migrations and table_type = 'BASE TABLE')
at C:\Users\jonke\Documents\laravel\pizzahouse\vendor\laravel\framework\src\Illuminate\Database\Connection.php:703
699▕ // If an exception occurs when attempting to
run a query, we'll format the error
700▕ // message to include the bindings with SQL,
which will make this exception a
701▕ // lot more helpful to the developer instead
of just the database's errors.
702▕ catch (Exception $e) {
➜ 703▕ throw new QueryException(
704▕ $query, $this->prepareBindings($bindings), $e
705▕ );
706▕ }
707▕ }
1 C:\Users\jonke\Documents\laravel\pizzahouse\vendor\laravel\framework\src\Illuminate\Database\Connectors\Connector.php:70
PDOException::("could not find driver")
2 C:\Users\jonke\Documents\laravel\pizzahouse\vendor\laravel\framework\src\Illuminate\Database\Connectors\Connector.php:70
PDO::__construct()
I've read the comments on the video, where I found the solution to an earlier error. I've tried following suggestion on this page: https://github.com/laravel/framework/issues/24711 which seemed promising but no joy.
I found pages on this website describing the same error message with different causes. One looked promising but vscode didn't like the sudo apt-get bits. (I've lost the link, sorry).
This one had a similar title but was no good: Migration in Laravel 5.6 - could not find driver
I also tried following the official docs: https://laravel.com/docs/8.x/migrations
How am I able to create the DB in the command line in vscode but not run the migration? I don't get it! I've been clicking around in circles for a couple of days now, can someone help me please?
Thanks
Added JonKemm Solution
It was the c:\php7/php.ini - needed to modify a line - uncomment this line: extension=pdo_mysql Answer found here: https://stackoverflow.com/a/25137901/16714187
If any other case your problem not solve try further
You have to add driver connection reading code. You can find in
config->database.php
'mysql' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
If you didn't find this in b/w
'connections' => [
...
],
Above version copied from Laravel Framework 6.20.30
If you missing something from these code from older laravel version try to compare or add some codes.
If you didn't find mysql code there
Copy my code and paste into your file, If you find any error comment below.
It was the c:\php7/php.ini - needed to modify a line - uncomment this line:
extension=pdo_mysql
Answer found here: https://stackoverflow.com/a/25137901/16714187

Two tables for one model in Laravel / Default (undeletable) rows

I have two databases for my Laravel 8 project: DB_COMMON and DB_SYSTEM. The point is, that I want to separate sensitive data to avoid deleting, so I'll use one db_user (with all privileges) for DB_COMMON and another (without deleting or updating permissions) for DB_SYSTEM.It will be something like additional security layer.
And there are table/(-s), for exapmle, rbac_role. I want to store two roles as "system" (S_ADMIN and CUSTOMER) in DB_SYSTEM and allow user to create new roles in same table name (rbac_role), but in DB_COMMON. And usually I want to work with that roles in one place (one model).
Are there any way to do it?
Or, maybe, I can "push" this two roles in model? I mean merge rows from database table with my (maybe even hardcoded) rows in model?
First of all you have to create two separate connection in your config/database.php file.
mysql connection is default if you are using mysql database.
Copy that params and create new connection:
'connection2' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
...
],
Then you can specify any model to run on specific connection:
class RoleModel extends Model {
protected $connection = 'connection2';
...
}
When you call RoleModel it will connect to second database.
I don't fully get what you want, But if you want to select from rows from two database you can set connection dynamically and select rows from any table.
$first_rows = RoleModel::setConnection('mysql')->select('id', 'role')->get();
$second_rows = RoleModel::setConnection('connection2')->select('id', 'role')->get();
$combined_rows = $first_rows->merge($second_rows);
If you want to create new row in second connection depending whether same record exists in first connection:
if(RoleModel::setConnection('mysql')->where('role', 'somerole')->exists()){
RoleModel::setConnection('connection2')->create([
'role' => 'somerole'
]);
}
Hope this answer helps you

Does laravel automatically add group by's? Weird behaviour Laravel toSql vs query being run.

I have a very, VERY weird issue. Our team has ignored this for a while because it hasn't broken anything (I know, not a good attitude), but I really want to know what the hell is/could be going on. We are on Laravel 5.2.
We have built very long queries using the laravel eloquent query builder. For some reason, sometimes, when we do a toSql(), we'll get the query we meant to run. When pasting the query, I'll get an error like this one:
Error Code: 1055. Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'onion.distance' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
Weird part though, changing nothing about it, laravel will run the query just fine! Anyone have ANY idea why laravel would run the query fine, but the toSql out put trigger this error? And how could we avoid it (other than manually adding the Group By's).
Not pasting code unless requested (lots of moving parts to some of the queries).
Thank you to Marcin Nabialek, you were 100% right. Laravel was overriding the default mysql server configuration and setting strict mode to false. For anyone that was confused as I was:
database.php
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'port' => env('DB_PORT', '3306'),
'dump_command_timeout' => 60 * 15, // 5 minute timeout
'unix_socket' => env('UNIX_SOCKET', ''),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', 'mysqltest'),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
'engine' => null,
]
All I had to do was set strict to true
'strict' => true

In Laravel application, mysql import transforms timestamp null values to 0000-00-00 00:00:00

In Laravel application I have a MySQL timestamp field deleted_at which was created for softDeletes and the default value is NULL. If the value is not NULL the Eloquent will not retrive the data. When I import CSV file the NULL value from source file becomes 0000-00-00 00:00:00.
I read Mysql import transforms timestamp null values to 0000-00-00 00:00:00 and \N does not worked for me. I have many tables which I need to import periodically, so I really need to fix this. Please help.
You need to disable strict mode in MySQL. Particularly, the mode name is STRICT_TRANS_TABLES . Open /etc/mysql/my.cnf (or the same file in Windows) find and comment out STRICT_TRANS_TABLES there.
More information is here:
http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sql-mode-strict
I think you should see your config/database.php file. This file contains the variable from where you can set the strict mode - On / Off.
Laravel now gives you the power to enable / disable mysql modes. With this new feature, Laravel now has the ability to do three things: Disable "strict" mode, returning to the <= 5.6 behavior; enable "strict" mode, setting it to the 5.7 behavior; or customizing exactly which modes are enabled.
The code in your file goes like this...
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => true, // <----- This variable sets the strict mode.
'engine' => null,
],
set this value to false if you want to disable the strict mode else make it true to enable the strict mode.
Hope this help you to solve your problem.

Running migrations while changing database

I'm making a multi tenancy application. For reasons I've chosen to go with a database for each of the tenants, and then a "master" database which contains meta information about the different tenants, and such.
I've therefore grouped my migrations into two directories:
Master - which contains the migrations for the master database.
Tenants - contains the migrations for each tenant database.
Instead of having to specify the path to the migration folders and the database to run on, each time I migrate, I've created a console command instead. However this is where the issue occurs.
I handle tenants using the subdomain as an identifier for which database to load from, using a middleware like this:
public function handle($request, Closure $next)
{
$domains = explode('.', parse_url($request->url())['host']);
if (count($domains) < 3)
return app()->abort(403, "A valid subdomain is required");
\Config::set('database.connections.tenant.database', $domains[0]);
return $next($request);
}
This works fine for web.
However when I use Config::set() within my console command, it's being ignored, and Laravel is just using the one from my .env file.
database config file:
return [
'default' => env('DB_CONNECTION', 'tenant'),
'connections' => [
'tenant' => [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_TENANT_DATABASE'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', '')
],
'master' => [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_MASTER_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
],
]
];
(I've cleaned it up a bit, so only the essential is shown).
In my .env file I've then specified a default tenant database, which is used when I'm using the cli.
DB_HOST=127.0.0.1
DB_MASTER_DATABASE=master
DB_TENANT_DATABASE=company
DB_USERNAME=root
DB_PASSWORD=
Within my TenantMigrater I iterate through each tenant, and run migrate for each of them with a different connection and path.
foreach(Tenant::all() as $tenant)
{
$this->info("Running migrations for the tenant: {$tenant->name}");
\Config::set('database.connections.tenant.database', $tenant->database);
$this->call('migrate', [
'--database' => 'tenant',
'--path' => 'database/migrations/tenants/'
]);
}
Although I'm setting a new database for the tenant connection, it's still falling back to the one specified in the .env file.
I tried going through Laravel's migrater, and as far I could see, the name was being set in the config correctly, so I'm feeling a bit confused. Any ideas?
Edit:
I think I've gotten one step closer to the issue. It seems like, when running php artisan *, the cli starts a connection to the database under the name specified in the config/database.php file. When i then try to override this, the connection is already open to the connection (or so laravel thinks), and it just hand my command the same connection, without setting the new database, hence why it keeps using the same database. However, I have no idea as to how to force it to create a new connection each time I iterate through the tenant.
Running \DB::reconnect('tenant'); before each migration seemed to make it work. This is a bit counter intuitive I think though.

Categories