How to Use Laravel With Your Current Legacy Application
Reading time: Takes 3 minutes
I have researched the topic a few times and never really found a good way to achieve having a Laravel application running alongside an existing legacy application.
The benefits for doing it this kind of side-loading way would be so that a section at a time can be ported across instead of actively maintaining two different projects and trying to keep the logic in sync with each other.
This guide assumes that there is no existing single entry point/front controller and no routing, e.g. that the url mysite.com/path/to/my/script/index.php
is how the current site behaves.
composer global require laravel/installer
laravel new [directory name]
It might be easier to use a different directory from the project you want to use Laravel with and copy the files and directories over one at a time.
Create an .env
file from the .env.example
.
Create an app key:
php artisan key:generate
Add the database connections that you need, e.g.:
DB_CONNECTION=db
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=my_main_app_db
DB_USERNAME=root
DB_PASSWORD=
SECONDARY_DB_CONNECTION=secondary_db
SECONDARY_DB_DRIVER=mysql
SECONDARY_DB_HOST=localhost
SECONDARY_DB_PORT=3306
SECONDARY_DB_DATABASE=my_secondary_app_db
SECONDARY_DB_USERNAME=root
SECONDARY_DB_PASSWORD=
If you only have one database then this will be even easier.
Then ensure that these are also in config/database.php
:
'db' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'my_main_app_db'),
'username' => env('DB_USERNAME', ''),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'latin1',
'collation' => 'latin1_swedish_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'),
]) : [],
],
'secondary_db' => [
'driver' => 'mysql',
'url' => env('SECONDARY_DATABASE_URL'),
'host' => env('SECONDARY_DB_HOST', '127.0.0.1'),
'port' => env('SECONDARY_DB_PORT', '3306'),
'database' => env('SECONDARY_DB_DATABASE', 'my_secondary_app_db'),
'username' => env('SECONDARY_DB_USERNAME', ''),
'password' => env('SECONDARY_DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'latin1',
'collation' => 'latin1_swedish_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'),
]) : [],
],
and set the default database connection:
'default' => env('DB_CONNECTION', 'my_main_app_db'),
Be careful of the charset and collations above, if you don't use those then change them to what you currently use, e.g. utf8mb4
and utf8mb4_unicode_ci
.
If composer and npm are already being used within the project, you will also need to consolidate composer.json and package.json in order to get the Laravel dependencies installed along with the currenty dependencies of the project.
Create or update .htaccess
in your project vhost entry point:
Options +FollowSymLinks
RewriteEngine on
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Send Requests To Front Controller...
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ laravel.php [L]
Create laravel.php
in the same directory as the .htaccess
file above and insert the following:
<?php
require_once __DIR__ . '/../public/index.php';
Add the following to routes.web.php
/* Fallback route */
Route::any( "/{path?}", [RouteController::class, 'oldRoute'])->where('path', '.*');
Create a RouteController
- php artisan make:controller RouteController
Open it app and add the oldRoute
method:
/**
* Include file at the given path
*
* @param String $path
* @return Response
*/
public function oldRoute($path)
{
ob_start();
if (file_exists(base_path('entrypoint-directory/' . $path))) {
include base_path(sprintf('entrypoint-directory/%s', $path));
} elseif (file_exists(base_path('public/' . $path))) {
$publicPath = base_path(sprintf('public/%s', $path));
header(sprintf('Content-Type: %s', mime_content_type($publicPath)));
readfile($publicPath);
} else {
abort(404, 'Page not found');
}
return response(ob_get_clean());
}
Update Http/Middleware/Authenticate.php
to point to the login url of the application, e.g.
// return route('login');
return 'login.php';
Make the custom auth middleware:
php artisan make:middleware CustomAuth
Set the contents of the handle
method to:
$user = User::getLoggedInUser();
// Login the user manually using Laravel's Auth Facade
// don't use `Auth::login($user, true);` unless `remember_token` is added to the users table.
Auth::login($user);
// set the user for the current request
$request->setUserResolver(function() use ($user) {
return $user;
});
return $next($request);
Open app/Http/Kernel.php
and change the auth
array entry so that it reads:
'auth' => \App\Http\Middleware\CustomAuth::class,
// 'auth' => \App\Http\Middleware\Authenticate::class,
Add a getLoggedInUser
method to the User
class:
public static function getLoggedInUser()
{
if (!isset($_SESSION['user']['id'])) {
return null;
}
// check if we want to impersonate someone
if (isset($_SESSION['impersonate'])) {
$user = self::find($_SESSION['impersonate']);
} else {
$user = self::find($_SESSION['user']['id']);
}
if (empty($user)) {
self::logout();
return null;
}
return $user;
}
Also, make sure the User
class is using the correct database connection if you have more than one database. This needs to be correct for each of your models if that is the case.
protected $connection = 'db';
That's it! Your legacy app should continue to operate as normal and now any new Laravel based routes should work alongside the existing application.