Laravel - Multi Site/Project - php

I'm currently looking for a framework to support my own new framework. Laravel seems to be my best choice.
I have a very specific structure in mind. My project will have a base design with common models, views and controllers, as well as some sub projects with there specific views. The goal is to provide a platform for owners of the same business, where we provide a unique website. In many cases only the design varies, whilst the structure and components stay the same. My idea was to create a maintainable structure on laravel wich every sites pulls its models, controllers and views from and if there is a specific need an additional view can be created.
Has somebody had experience with a simular project in the past?
I see some major obstacles:
Creating sub projects
Using multi database connections
Using models and views from the main project
project setup

Laravel is very flexible and highly configurable, you should have no problem doing things like that at all. As for the database, for example, you can create two connections: main, a fixed connection to your main database tables, and project for the current project tables, here's what it should look like:
'main' => [
'driver' => 'pgsql',
'host' => env('DB_HOST', 'localhost'),
'port' => env('DB_PORT', '5432'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
'schema' => 'public',
'sslmode' => 'prefer',
],
'project' => [
'driver' => 'pgsql',
'host' => env('DB_HOST', 'localhost'),
'port' => env('DB_PORT', '5432'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
'schema' => 'public',
'sslmode' => 'prefer',
],
And you should be able to:
Configure model connection:
<?php
namespace App;
class Posts extends Model
{
protected $connection = 'project';
}
Query connections directly:
DB::connection('project')->table('users')->where('activated', true)->get();
Configure the database in run time:
config([
'database.connections.project.database' => 'project1db',
'database.connections.project.user' => $user,
'database.connections.project.password' => $password,
]);
As for the views, you can tell Laravel to find views wherever you need by simply doing:
View::addLocation('/path/to/project1/');

Related

Enable MARS in Laravel

For my Laravel application, I want to use MARS to connect to our SQL server. However, the documentation makes no note of this, nor is there any info on how to pass extra config parameters to the connection.
I'm on Laravel v7.30.
The database works fine apart for the few cases where I need to run several queries on one connection. Right now, those throw a "Protocol error in TDS stream" error. I'm fairly certain this is due to MARS not being activated. If, however, this could have a different reason I'm of course open to suggestions!
My config/database.php entry for SQL Server looks like this:
'sqlsrv' => [
'driver' => 'sqlsrv',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', 'localhost'),
'port' => env('DB_PORT', '1433'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
'prefix_indexes' => true,
'appname' => env('DB_APPNAME', 'MyAppName-' . env('APP_ENV')),
],
Apart from that, the database connection is working fine and queries perform as expected.

Laravel : How to set database connection pool?

I need to connect many databases dynamically in laravel app.
How to set database connection pool?
for example,there are many second-class domain name,like this:
chicago.example.com
newyork.example.com
losangeles.example.com
...
They have separate database:
chicago
newyork
losangeles
...
I connect these databases dynamically like this:
public function store(Request $request)
{
//post request from http://chicago.example.com/articles
$server_name_arr=explode('.',$_SERVER['SERVER_NAME']); //the result is ['chicago','example','com']
$db=array_slice($server_name_arr,-3,1)[0]; //the result is 'chicago'
Config::set('database.connections.mysql.database', $db);
DB::reconnect('mysql');
//...
}
For performance,I want to set database connection pool,how to do it in laravel?
If you have quite many different instances of your code and is difficult to manage the configuration (env file), you can modify your code, adding a condition to modify env file and cache the configuration if needed. This if you just need an admin functionality, it will not work if you have one instance, please look the code below.
If you have one instance and one DB server, then perhaps you can use table prefix to distinguish your tables, I mean to copy all your tables with a different prefix depending your subdomain.
But if you really need database coonection pool, there are some solutions for Laravel at Github like this , but I have never tried one.
public function store(Request $request)
{
//post request from http://chicago.example.com/articles
$server_name_arr=explode('.',$_SERVER['SERVER_NAME']); //the result is ['chicago','example','com']
$db=array_slice($server_name_arr,-3,1)[0]; //the result is 'chicago'
$current_db = DB::connection()->getDatabaseName();
if($db != $current_db){
$path = base_path('.env');
file_put_contents($path, str_replace('DB_DATABASE=' . current_db,
'DB_DATABASE=' . $db, file_get_contents($path)));
Artisan::call('config:cache');
}
//...
}
You can define multiple Mysql connections like this in 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', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
],
'mysql2' => [
'driver' => env('DB_CONNECTION_SECOND'),
'host' => env('DB_HOST_SECOND'),
'port' => env('DB_PORT_SECOND'),
'database' => env('DB_DATABASE_SECOND'),
'username' => env('DB_USERNAME_SECOND'),
'password' => env('DB_PASSWORD_SECOND'),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
],
Define variables for same in .env file. Now create model with properties as below.
protected $connection = 'mysql2';
protected $table = 'tablename';
Model will refer to that particular table of remote database.

Multiple databases in Laravel PHP [duplicate]

This question already has answers here:
How to use multiple databases in Laravel
(7 answers)
Closed 5 years ago.
We are building a multi-tenant application. Through the admin interface, we will add new tenant as and when required. This application needs to work with 1+n database.
1 Main DB with about 5 tables.
n DBs for each tenant that we create. The tenant specific database may reside on the separate db server altogether.
Question:
What is the best way to achieve this ?
Where do we store the the db connection information for each tenant ?
Sometime, we may have to fire join queries on tables in tenant and main db.
How would this work?
Thanks in advance for reading and any possible solution please.
Google is your friend, so is the documentation:
https://laravel.com/docs/5.4/database#using-multiple-database-connections
config/database.php
And add a new connection for each database-connection you want to use.
To switch connections:
$users = DB::connection('foo')->select(...);
We can set the DB connection in config/database.php in connections part:
'connections' => [
//Our primary DB
'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' => false,
'engine' => null,
],
//Secondary DB
'mysql2' => [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB2_DATABASE', 'secondary'),
'username' => env('DB2_USERNAME', 'forge'),
'password' => env('DB2_PASSWORD', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
'engine' => null,
],
],
And for Model we can add
class User2 extends Model
{
protected $connection = 'mysql2';
}
And in migration we can use connection method.
Schema::connection('mysql2')->create('table')
And if you use Eloquent ORM we can use setConnection('mysql2') on it.
$user = new User2;
$user->setConnection('mysql2');
This answer based on this question
In my case a wont use multi-tenant
store child db configurations in main database
set child db params in middleware
use $connection = 'child' in needed models
join is not possible, because may be different servers, but huge part of relations is work propertly (not whereExists, withCount.. etc)
Hope it`s help

How to make schema of postgres sql dynamic in laravel?

I need to make schema of postgres dynamic in laravel. The database config is below
'pgsql' => [
'driver' => 'pgsql',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'stoddart'),
'username' => env('DB_USERNAME', 'postgres'),
'password' => env('DB_PASSWORD', '123456'),
'charset' => 'utf8',
'port' => env('DB_PORT', '7373'),
'prefix' => '',
'schema' => 'cp_bn',
],
Here you can see i have specified schema, but i want it to be Dynamic. The schema name will come from client side.
I am currently doing like following
$connection =DB::connection()->getPdo();
$connection->prepare("Set search_path to {$schema}")->execute();
But in this case i have to execute this whenever the connection to the database is made. I need to save it globally for all connection once it is set.

Using multiple databases for different endpoints

I have API written in lumen(laravel). I am using Eloquent for my models.
What I need to do is to use different databases based on url (endpoint).
For example I have http://apiprovider.com/api/v1/ as base API url and it connects to the api_v1 database, but I need to use another database if v2 is used http://apiprovider.com/api/v2 for instance api_v2 database.
All classes and laravel application should be the same, only different database according to version.
Database settings is stored in .env file.
Please suggest the right way to implement this ? Or at least possible ways.
Thanks.
It's just an idea, i haven't tried it but a simple way would be switching between the two databases from a middleware.
For example you could define the two connections available in database.php :
'connections' => [
'mysql1' => [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
'mysql2' => [
'driver' => 'mysql',
'host' => env('DB_HOST_2', 'localhost'),
'database' => env('DB_DATABASE_2', 'forge'),
'username' => env('DB_USERNAME_2', 'forge'),
'password' => env('DB_PASSWORD_2', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
]
Then create a middleware and switch the DB in the handle method
public function handle($request, Closure $next)
{
//check the request URL and decide what DB to use
//set the DB for this request
Config::set('database.default', $dbname );
}
I think that Config::set('database.default', $dbname); will work only for the current request, but it would do what you need

Categories