Laravel Vue Socialite Setup
March 1, 2025 Β· AI Conversations
—
## **1. Install Laravel Socialite**
Run the following command in your Laravel project:
composer require laravel/socialite
—
## **2. Configure Socialite in `config/services.php`**
Add the Google and GitHub credentials:
return [
'github' => [
'client_id' => env('GITHUB_CLIENT_ID'),
'client_secret' => env('GITHUB_CLIENT_SECRET'),
'redirect' => env('GITHUB_REDIRECT_URI'),
],
'google' => [
'client_id' => env('GOOGLE_CLIENT_ID'),
'client_secret' => env('GOOGLE_CLIENT_SECRET'),
'redirect' => env('GOOGLE_REDIRECT_URI'),
],
];
—
## **3. Set Up Environment Variables in `.env`**
Get API credentials from:
– Google: [Google Developer Console](https://console.developers.google.com/)
– GitHub: [GitHub OAuth Apps](https://github.com/settings/developers)
Then, add them to your `.env` file:
GITHUB_CLIENT_ID=your_github_client_id
GITHUB_CLIENT_SECRET=your_github_client_secret
GITHUB_REDIRECT_URI=http://yourdomain.com/auth/github/callback
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
GOOGLE_REDIRECT_URI=http://yourdomain.com/auth/google/callback
—
## **4. Create Socialite Controller**
Run:
php artisan make:controller SocialAuthController
Then, update `app/Http/Controllers/SocialAuthController.php`:
namespace AppHttpControllers;
use LaravelSocialiteFacadesSocialite;
use AppModelsUser;
use IlluminateSupportFacadesAuth;
use IlluminateHttpRequest;
use InertiaInertia;
class SocialAuthController extends Controller
{
// Redirect to provider (Google/GitHub)
public function redirect($provider)
{
return Socialite::driver($provider)->redirect();
}
// Handle provider callback
public function callback($provider)
{
try {
$socialUser = Socialite::driver($provider)->user();
$user = User::where('email', $socialUser->getEmail())->first();
if (!$user) {
$user = User::create([
'name' => $socialUser->getName(),
'email' => $socialUser->getEmail(),
'provider' => $provider,
'provider_id' => $socialUser->getId(),
'password' => bcrypt(str()->random(16)), // Dummy password
]);
}
Auth::login($user);
return redirect()->route('dashboard');
} catch (Exception $e) {
return redirect()->route('login')->withErrors(['msg' => 'Authentication failed']);
}
}
// Logout
public function logout(Request $request)
{
Auth::logout();
return redirect('/');
}
}
—
## **5. Define Routes in `routes/web.php`**
use AppHttpControllersSocialAuthController;
Route::get('/auth/{provider}/redirect', [SocialAuthController::class, 'redirect']);
Route::get('/auth/{provider}/callback', [SocialAuthController::class, 'callback']);
Route::post('/logout', [SocialAuthController::class, 'logout'])->name('logout');
—
## **6. Modify User Model (`app/Models/User.php`)**
Add `provider` and `provider_id` columns:
protected $fillable = [
'name', 'email', 'password', 'provider', 'provider_id'
];
Then, run:
php artisan make:migration add_provider_columns_to_users_table --table=users
Update the migration:
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->string('provider')->nullable();
$table->string('provider_id')->nullable();
});
}
Run:
php artisan migrate
—
## **7. Frontend (Vue.js)**
Modify your Vue login component (e.g., `Login.vue`):
<template>
<div>
<button @click="loginWith('google')">Login with Google</button>
<button @click="loginWith('github')">Login with GitHub</button>
</div>
</template>
<script>
export default {
methods: {
loginWith(provider) {
window.location.href = `/auth/${provider}/redirect`;
}
}
};
</script>
—
## **8. Protect Routes Using Middleware (`routes/web.php`)**
Route::middleware(['auth'])->group(function () {
Route::get('/dashboard', function () {
return Inertia::render('Dashboard');
})->name('dashboard');
});
—
## **9. Test the Authentication**
1. Start Laravel server:
php artisan serve
2. Try logging in via Google/GitHub.
—
### π Now your Laravel Vue Inertia app supports Google and GitHub authentication using Laravel Socialite! Let me know if you need help.
—
## **1. Create a Migration for Adding the Column**
Run the following command to generate a new migration file:
php artisan make:migration add_custom_column_to_users_table --table=users
This will create a migration file inside the `database/migrations` directory.
—
## **2. Modify the Migration File**
Open the newly created migration file and add the custom column inside the `up()` method.
For example, if you want to add a column named `role`:
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
return new class extends Migration {
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->string('role')->default('user')->after('email'); // Add role column
});
}
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('role');
});
}
};
πΉ **Explanation:**
– The `after('email')` places the new `role` column after the `email` column.
– The `default('user')` ensures a default value of `"user"`.
– The `down()` method ensures the column is removed when rolling back the migration.
—
## **3. Run the Migration**
Execute the migration command to apply the changes:
php artisan migrate
—
## **4. Update the User Model (`app/Models/User.php`)**
Add the new column to the `$fillable` array to allow mass assignment:
protected $fillable = [
'name', 'email', 'password', 'role', // Add 'role' here
];
—
## **5. (Optional) Set Default Role When Creating Users**
If you want to ensure that users always have a default role, you can modify the `UserFactory.php`:
Open `database/factories/UserFactory.php` and update it:
public function definition()
{
return [
'name' => $this->faker->name(),
'email' => $this->faker->unique()->safeEmail(),
'password' => bcrypt('password'),
'role' => 'user', // Set default role
];
}
—
## **6. Test the New Column**
Run the following command in Tinker (`php artisan tinker`) to create a new user and check if the `role` column is added:
User::create([
'name' => 'Test User',
'email' => 'test@example.com',
'password' => bcrypt('password'),
'role' => 'admin'
]);
Then, verify:
User::all();
—
### β Done! Now your `users` table has a `role` column. Let me know if you need any modifications. π
—
### **1. Create a Migration File**
Run the following Artisan command:
php artisan make:migration add_custom_column_to_users_table --table=users
This will generate a new migration file in `database/migrations/`.
—
### **2. Modify the Migration File**
Open the newly created migration file (located in `database/migrations/`) and update the `up()` and `down()` methods. For example, if you want to add a `phone_number` column:
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
return new class extends Migration {
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->string('phone_number')->nullable()->after('email');
});
}
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('phone_number');
});
}
};
—
### **3. Run the Migration**
Execute the migration with:
php artisan migrate
This will apply the changes and add the `phone_number` column to the `users` table.
—
### **4. Update the User Model (`app/Models/User.php`)**
Make sure to add the new column to the `$fillable` array:
protected $fillable = [
'name', 'email', 'password', 'provider', 'provider_id', 'phone_number'
];
—
### **5. Update Form and Controller (If Needed)**
If you're allowing users to update their phone number, modify the corresponding Vue component and Laravel controller.
For example, in a Vue form component:
<template>
<form @submit.prevent="updateProfile">
<input type="text" v-model="user.phone_number" placeholder="Enter phone number" />
<button type="submit">Save</button>
</form>
</template>
<script>
import { useForm } from '@inertiajs/vue3';
export default {
setup() {
const user = useForm({
phone_number: '',
});
const updateProfile = () => {
user.post('/profile/update');
};
return { user, updateProfile };
}
};
</script>
And in the controller (`ProfileController.php`):
use IlluminateHttpRequest;
use IlluminateSupportFacadesAuth;
public function update(Request $request)
{
$request->validate([
'phone_number' => 'nullable|string|max:15',
]);
Auth::user()->update([
'phone_number' => $request->phone_number,
]);
return redirect()->back()->with('success', 'Profile updated.');
}
—
### β
**Done!**
Now your `users` table has a custom `phone_number` column. Let me know if you need any modifications! π
—
### **1. Create a Migration**
Run the following Artisan command:
php artisan make:migration add_provider_columns_to_users_table --table=users
—
### **2. Modify the Migration File**
Open the newly created migration file in `database/migrations/` and update the `up()` and `down()` methods:
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
return new class extends Migration {
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->string('provider')->nullable()->after('email');
$table->string('provider_id')->nullable()->after('provider');
$table->string('mobile_no')->nullable()->after('provider_id');
});
}
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn(['provider', 'provider_id', 'mobile_no']);
});
}
};
—
### **3. Run the Migration**
Execute the following command to apply the migration:
php artisan migrate
—
### **4. Update the `User` Model (`app/Models/User.php`)**
Modify the `$fillable` array to include the new columns:
protected $fillable = [
'name', 'email', 'password', 'provider', 'provider_id', 'mobile_no'
];
—
### β
**Done!**
Now, your `users` table will include the `provider`, `provider_id`, and `mobile_no` columns. Let me know if you need further modifications! π
accounts.google.com/o/oauth2/auth?client_id=960061260872-95h3526oahbplrkc6pu7vk3jrgkfkfj1.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Fsyt.ddev.site%2Fgoogle-callback&scope=openid+profile+email&response_type=code&state=hOZVQlFJVZVkkBzxM8nIfCGgtcffoJvSfCxDjQUF:1
GET https://accounts.google.com/o/oauth2/auth?client_id=960061260872-95h3526oahbplrkc6pu7vk3jrgkfkfj1.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Fsyt.ddev.site%2Fgoogle-callback&scope=openid+profile+email&response_type=code&state=hOZVQlFJVZVkkBzxM8nIfCGgtcffoJvSfCxDjQUF net::ERR_FAILEDUnderstand this errorAI
chunk-PQI74GGM.js?v=a9a130a1:1596 Uncaught (in promise) AxiosErrorΒ {message: 'Network Error', name: 'AxiosError', code: 'ERR_NETWORK', config: {β¦}, request: XMLHttpRequest,Β β¦}
handleError @ chunk-PQI74GGM.js?v=a9a130a1:1596Understand this errorAI
login:1 Access to XMLHttpRequest at 'https://github.com/login/oauth/authorize?client_id=Ov23liAp5Lc6XG4i18MU&redirect_uri=https%3A%2F%2Fsyt.ddev.site%2Fgithub-callback&scope=user%3Aemail&response_type=code&state=tm6FhxMmkWQFhkEk88Gy8rfIWuSCqBg2FLix87Le' (redirected from 'https://syt.ddev.site/auth/github/redirect') from origin 'https://syt.ddev.site' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.Understand this errorAI
chunk-PQI74GGM.js?v=a9a130a1:1653
GET https://github.com/login/oauth/authorize?client_id=Ov23liAp5Lc6XG4i18MU&redirect_uri=https%3A%2F%2Fsyt.ddev.site%2Fgithub-callback&scope=user%3Aemail&response_type=code&state=tm6FhxMmkWQFhkEk88Gy8rfIWuSCqBg2FLix87Le net::ERR_FAILED
dispatchXhrRequest @ chunk-PQI74GGM.js?v=a9a130a1:1653
xhr @ chunk-PQI74GGM.js?v=a9a130a1:1533
dispatchRequest @ chunk-PQI74GGM.js?v=a9a130a1:2008
_request @ chunk-PQI74GGM.js?v=a9a130a1:2223
request @ chunk-PQI74GGM.js?v=a9a130a1:2120
wrap @ chunk-PQI74GGM.js?v=a9a130a1:8
visit @ @inertiajs_vue3.js?v=a9a130a1:4068
onClick @ @inertiajs_vue3.js?v=a9a130a1:4496
callWithErrorHandling @ chunk-U3LI7FBV.js?v=a9a130a1:2263
callWithAsyncErrorHandling @ chunk-U3LI7FBV.js?v=a9a130a1:2270
invoker @ chunk-U3LI7FBV.js?v=a9a130a1:11202Understand this errorAI
chunk-PQI74GGM.js?v=a9a130a1:1596 Uncaught (in promise) AxiosErrorΒ {message: 'Network Error', name: 'AxiosError', code: 'ERR_NETWORK', config: {β¦}, request: XMLHttpRequest,Β β¦}
### **Possible Causes & Fixes**
#### β
1. **Google & GitHub Don't Support CORS for OAuth Authorization**
Google and GitHub **donβt allow cross-origin requests** to their authentication URLs. Instead, authentication should be done **via a redirect**, not an AJAX request.
π **Fix:**
Ensure that the OAuth authentication flow is triggered using a standard **window redirect**, not an Axios/AJAX request.
Modify your Vue.js login button handler:
<template>
<button @click="loginWithGoogle">Login with Google</button>
<button @click="loginWithGitHub">Login with GitHub</button>
</template>
<script>
export default {
methods: {
loginWithGoogle() {
window.location.href = "/auth/google/redirect"; // Redirect instead of Axios
},
loginWithGitHub() {
window.location.href = "/auth/github/redirect";
}
}
};
</script>
—
#### β
2. **Ensure OAuth Routes Are Defined Correctly in Laravel**
In `routes/web.php`, ensure you have defined the OAuth routes correctly:
use LaravelSocialiteFacadesSocialite;
use IlluminateSupportFacadesRoute;
use AppHttpControllersAuthOAuthController;
Route::get('/auth/google/redirect', function () {
return Socialite::driver('google')->redirect();
});
Route::get('/google-callback', [OAuthController::class, 'handleGoogleCallback']);
Route::get('/auth/github/redirect', function () {
return Socialite::driver('github')->redirect();
});
Route::get('/github-callback', [OAuthController::class, 'handleGitHubCallback']);
—
#### β
3. **Allow CORS in Laravel**
You need to allow CORS in Laravel.
π **Step 1**: Install Laravel CORS package:
composer require fruitcake/laravel-cors
π **Step 2**: Publish the config file:
php artisan vendor:publish --tag="cors"
π **Step 3**: Open `config/cors.php` and set:
return [
'paths' => ['api/*', 'sanctum/csrf-cookie', 'auth/*', 'google-callback', 'github-callback'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,
];
π **Step 4**: Clear the cache:
php artisan config:clear
php artisan cache:clear
—
#### β
4. **Check Your OAuth Client Credentials**
Make sure you have set the correct **Google & GitHub OAuth credentials** in `.env`:
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
GOOGLE_REDIRECT_URI=https://syt.ddev.site/google-callback
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_CLIENT_SECRET=your-github-client-secret
GITHUB_REDIRECT_URI=https://syt.ddev.site/github-callback
Then, **restart the Laravel server**:
php artisan serve
—
#### β
5. **Ensure Your Google & GitHub OAuth Apps Have Correct Redirect URIs**
Go to your **Google Developer Console** and **GitHub Developer Settings**, and **whitelist** your redirect URLs:
– **Google**:
In the **Google Cloud Console**, set the **Authorized redirect URIs** to:
https://syt.ddev.site/google-callback
– **GitHub**:
In **GitHub Developer Settings**, set the **Authorization callback URL** to:
https://syt.ddev.site/github-callback
—
### **Final Steps**
β
Try logging in again using **window.location.href**, instead of Axios.
β
Make sure your Laravel routes, CORS settings, and OAuth credentials are correct.
β
If issues persist, check **Laravel logs** in `storage/logs/laravel.log`.
—
### **π Summary**
– **Don't use Axios for OAuth redirects** (use `window.location.href`).
– **Ensure correct OAuth routes** in Laravel.
– **Allow CORS in Laravel** using `fruitcake/laravel-cors`.
– **Verify OAuth credentials & redirect URIs** in Google/GitHub settings.
Let me know if you need more help! π
<script>
import Checkbox from '@/Components/Checkbox.vue';
import SiteLayout from '@/Layouts/SiteLayout.vue';
import InputError from '@/Components/InputError.vue';
import InputLabel from '@/Components/InputLabel.vue';
import PrimaryButton from '@/Components/PrimaryButton.vue';
import TextInput from '@/Components/TextInput.vue';
import { Head, Link, useForm } from '@inertiajs/vue3';
defineProps({
canResetPassword: {
type: Boolean,
},
status: {
type: String,
},
});
const form = useForm({
email: '',
password: '',
remember: false,
});
const submit = () => {
form.post(route('login'), {
onFinish: () => form.reset('password'),
});
};
</script>
{{ status }}
{{ $t('Please sign in') }}
Remember me
{{ $t('forgot_password','Forgot your password?') }}
{{ $t('register','Register') }}
{{ $t('login','Log in') }}
{{ $t('login_with_google','Login with Google') }}
{{ $t('login_with_github','Login with Github') }}
fix in above
1. **CORS issue with Google and GitHub OAuth redirects**
– The issue might be that your `route('auth.redirect', 'google')` and `route('auth.redirect', 'github')` are not properly configured in your backend.
– Ensure that your backend handles these redirects correctly without triggering CORS errors.
2. **Incorrect `$t` translation function usage**
– You're using `$t()` for translations but haven't imported or properly used it in “.
### **Fixed Code**
<script setup>
import { Head, Link, useForm } from '@inertiajs/vue3';
import { useI18n } from 'vue-i18n'; // Import Vue i18n for translations
import Checkbox from '@/Components/Checkbox.vue';
import SiteLayout from '@/Layouts/SiteLayout.vue';
import InputError from '@/Components/InputError.vue';
import InputLabel from '@/Components/InputLabel.vue';
import PrimaryButton from '@/Components/PrimaryButton.vue';
import TextInput from '@/Components/TextInput.vue';
const { t } = useI18n(); // Initialize i18n translations
defineProps({
canResetPassword: Boolean,
status: String,
});
const form = useForm({
email: '',
password: '',
remember: false,
});
const submit = () => {
form.post(route('login'), {
onFinish: () => form.reset('password'),
});
};
</script>
<template>
<SiteLayout content-class="flex justify-center items-center min-h-screen">
<Head title="Log in" />
<div v-if="status" class="mb-4 text-sm font-medium text-green-600">
{{ status }}
</div>
<div class="formcenter border p-6 rounded-lg shadow-lg bg-white">
<h2 class="text-center text-2xl font-bold">{{ t('Please sign in') }}</h2>
<form @submit.prevent="submit" class="mt-4">
<div>
<InputLabel for="email" :value="t('email', 'Email')" />
<TextInput
id="email"
type="email"
class="mt-1 block w-full"
v-model="form.email"
required
autofocus
autocomplete="username"
/>
<InputError class="mt-2" :message="form.errors.email" />
</div>
<div class="mt-4">
<InputLabel for="password" :value="t('password', 'Password')" />
<TextInput
id="password"
type="password"
class="mt-1 block w-full"
v-model="form.password"
required
autocomplete="current-password"
/>
<InputError class="mt-2" :message="form.errors.password" />
</div>
<div class="mt-4 block">
<label class="flex items-center">
<Checkbox name="remember" v-model:checked="form.remember" />
<span class="ml-2 text-sm text-gray-600">{{ t('remember_me', 'Remember me') }}</span>
</label>
</div>
<div class="mt-4 flex items-center justify-between">
<Link
v-if="canResetPassword"
:href="route('password.request')"
class="text-sm text-blue-600 hover:underline"
>
{{ t('forgot_password', 'Forgot your password?') }}
</Link>
<Link
v-if="canResetPassword"
:href="route('register')"
class="text-sm text-blue-600 hover:underline"
>
{{ t('register', 'Register') }}
</Link>
</div>
<div class="mt-4 flex justify-end">
<PrimaryButton
class="ms-4"
:class="{ 'opacity-25': form.processing }"
:disabled="form.processing"
>
{{ t('login', 'Log in') }}
</PrimaryButton>
</div>
<div class="mt-6">
<Link
:href="route('auth.redirect', 'google')"
class="block w-full text-center p-2 border border-gray-300 rounded-md text-gray-700 hover:bg-gray-100"
>
{{ t('login_with_google', 'Login with Google') }}
</Link>
<Link
:href="route('auth.redirect', 'github')"
class="mt-2 block w-full text-center p-2 border border-gray-300 rounded-md text-gray-700 hover:bg-gray-100"
>
{{ t('login_with_github', 'Login with GitHub') }}
</Link>
</div>
</form>
</div>
</SiteLayout>
</template>
—
### **Fixes Applied**
1. **Fixed `$t()` Translation Function**
– Imported `useI18n()` and initialized `t()`.
– Used `t('key', 'Fallback Text')` to prevent errors if the key is missing.
2. **Improved OAuth Login Buttons**
– Wrapped them in `block` and `text-center` styles to improve UI.
3. **Ensured Proper Form Styling**
– Added padding, border, and shadow to `formcenter` for a better look.
—
### **Next Steps: Fix CORS Issue**
Since OAuth providers (Google & GitHub) should not be affected by CORS errors, check:
#### **1. Verify Redirect URI in OAuth Settings**
– Ensure that in **Google Console** and **GitHub OAuth App settings**, the **Authorized Redirect URI** is set to:
https://syt.ddev.site/google-callback
https://syt.ddev.site/github-callback
#### **2. Ensure API Routes are Correct**
Your Laravel `web.php` routes should include:
use LaravelSocialiteFacadesSocialite;
Route::get('/auth/redirect/{provider}', function ($provider) {
return Socialite::driver($provider)->redirect();
})->name('auth.redirect');
Route::get('/auth/callback/{provider}', function ($provider) {
$user = Socialite::driver($provider)->user();
// Handle user login or registration
return redirect()->route('dashboard');
})->name('auth.callback');
#### **3. Allow CORS in Laravel**
Edit `app/Http/Middleware/Cors.php` (if you have custom CORS handling), or update `cors.php`:
return [
'paths' => ['api/*', 'auth/*'], // Allow OAuth endpoints
'allowed_methods' => ['*'],
'allowed_origins' => ['https://syt.ddev.site'],
'allowed_headers' => ['*'],
'supports_credentials' => true,
];
Then run:
php artisan config:clear
php artisan cache:clear
After these fixes, test again. Let me know if issues persist! π
### **Solution 1: Use `env()` in `config` files**
Instead of trying to replace the variable inside `.env`, reference it in a `config` file like `config/app.php`:
'custom_variable' => env('BASE_URL', 'http://default.url') . '/some-path',
This way, `BASE_URL` from `.env` is dynamically used.
### **Solution 2: Use `str_replace` in Laravel Configuration**
If you need to modify an environment variable dynamically:
'api_url' => str_replace('{BASE_URL}', env('BASE_URL'), env('API_ENDPOINT')),
Then in `.env`:
BASE_URL=https://example.com
API_ENDPOINT={BASE_URL}/api
After parsing, `API_ENDPOINT` will be replaced correctly.
### **Solution 3: Modify in `bootstrap/app.php`**
You can also manipulate `.env` values programmatically in `bootstrap/app.php`:
putenv('API_ENDPOINT=' . str_replace('{BASE_URL}', getenv('BASE_URL'), getenv('API_ENDPOINT')));
Since Laravel reads `.env` values only once when the application boots, direct replacements inside `.env` won't work. Instead, you need to handle it in PHP where Laravel reads the values.
APP_URL='dsda.com'
now
AAP_CALL=APP_URL.'/dsd'
APP_URL='dsda.com'
APP_CALL=APP_URL.'/dsd'
because `.env` files are parsed as plain text, and Laravel does not interpret variable references within them.
### **Workaround: Handle it in `config` files**
Instead, define them separately in `.env`:
APP_URL='dsda.com'
APP_CALL='/dsd'
Then, in `config/app.php`:
'call_url' => env('APP_URL') . env('APP_CALL'),
Now, when you access `config('app.call_url')`, it will return:
dsda.com/dsd
### **Alternative: Use `str_replace`**
If you still want to reference `APP_URL` in `.env`, you can handle it in `config/app.php` like this:
'call_url' => str_replace('{APP_URL}', env('APP_URL'), '{APP_URL}/dsd'),
Since `.env` variables are read only once and cannot refer to each other, handling them in `config` is the best solution.
on:
push:
branches:
– master # Trigger on push to master branch
jobs:
deploy:
runs-on: ubuntu-latest
steps:
– name: Checkout code
uses: actions/checkout@v2
– name: Set up SSH
env:
PEM_FILE: ${{ secrets.PEM_FILE }} # Store your PEM file content in GitHub secrets
run: |
echo "$PEM_FILE" > key.pem
chmod 600 key.pem
– name: Ensure proper permissions on EC2
env:
EC2_USER: ${{ secrets.EC2_USER }} # Store your EC2 username in GitHub secrets
EC2_HOST: ${{ secrets.EC2_HOST }} # Store your EC2 host in GitHub secrets
run: |
# Ensure that the correct permissions are set on the EC2 instance
ssh -i key.pem -o StrictHostKeyChecking=no $EC2_USER@$EC2_HOST "sudo chown -R $EC2_USER:$EC2_USER /var/www/shareyourthoughts && sudo chmod -R 775 /var/www/shareyourthoughts"
– name: Delete public/build folder from EC2
env:
EC2_USER: ${{ secrets.EC2_USER }} # Store your EC2 username in GitHub secrets
EC2_HOST: ${{ secrets.EC2_HOST }} # Store your EC2 host in GitHub secrets
run: |
ssh -i key.pem -o StrictHostKeyChecking=no $EC2_USER@$EC2_HOST "rm -rf /var/www/shareyourthoughts/public/build"
– name: Deploy to EC2
env:
EC2_USER: ${{ secrets.EC2_USER }} # Store your EC2 username in GitHub secrets
EC2_HOST: ${{ secrets.EC2_HOST }} # Store your EC2 host in GitHub secrets
run: |
# Run rsync with updated timestamps only for changed files, excluding storage if needed
rsync -avz –exclude 'storage/*' -e "ssh -i key.pem -o StrictHostKeyChecking=no" ./ $EC2_USER@$EC2_HOST:/var/www/shareyourthoughts
– name: Install Composer dependencies
env:
EC2_USER: ${{ secrets.EC2_USER }}
EC2_HOST: ${{ secrets.EC2_HOST }}
run: |
ssh -i key.pem -o StrictHostKeyChecking=no $EC2_USER@$EC2_HOST "
cd /var/www/shareyourthoughts &&
composer install –no-dev –optimize-autoloader &&
composer update –no-dev –optimize-autoloader"
– name: Change ownership to www-data
env:
EC2_USER: ${{ secrets.EC2_USER }} # Store your EC2 username in GitHub secrets
EC2_HOST: ${{ secrets.EC2_HOST }} # Store your EC2 host in GitHub secrets
run: |
# Change ownership to www-data:www-data
ssh -i key.pem -o StrictHostKeyChecking=no $EC2_USER@$EC2_HOST "sudo chown -R www-data:www-data /var/www/shareyourthoughts"
rm key.pem # Clean up the PEM file after the final deployment
also add php artisan ,migrate command
name: Deploy to EC2
on:
push:
branches:
- master # Trigger on push to master branch
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up SSH
env:
PEM_FILE: ${{ secrets.PEM_FILE }} # Store your PEM file content in GitHub secrets
run: |
echo "$PEM_FILE" > key.pem
chmod 600 key.pem
- name: Ensure proper permissions on EC2
env:
EC2_USER: ${{ secrets.EC2_USER }}
EC2_HOST: ${{ secrets.EC2_HOST }}
run: |
ssh -i key.pem -o StrictHostKeyChecking=no $EC2_USER@$EC2_HOST "
sudo chown -R $EC2_USER:$EC2_USER /var/www/shareyourthoughts &&
sudo chmod -R 775 /var/www/shareyourthoughts"
- name: Delete public/build folder from EC2
env:
EC2_USER: ${{ secrets.EC2_USER }}
EC2_HOST: ${{ secrets.EC2_HOST }}
run: |
ssh -i key.pem -o StrictHostKeyChecking=no $EC2_USER@$EC2_HOST "rm -rf /var/www/shareyourthoughts/public/build"
- name: Deploy to EC2
env:
EC2_USER: ${{ secrets.EC2_USER }}
EC2_HOST: ${{ secrets.EC2_HOST }}
run: |
rsync -avz --exclude 'storage/*' -e "ssh -i key.pem -o StrictHostKeyChecking=no" ./ $EC2_USER@$EC2_HOST:/var/www/shareyourthoughts
- name: Install Composer dependencies
env:
EC2_USER: ${{ secrets.EC2_USER }}
EC2_HOST: ${{ secrets.EC2_HOST }}
run: |
ssh -i key.pem -o StrictHostKeyChecking=no $EC2_USER@$EC2_HOST "
cd /var/www/shareyourthoughts &&
composer install --no-dev --optimize-autoloader &&
composer update --no-dev --optimize-autoloader"
- name: Run database migrations
env:
EC2_USER: ${{ secrets.EC2_USER }}
EC2_HOST: ${{ secrets.EC2_HOST }}
run: |
ssh -i key.pem -o StrictHostKeyChecking=no $EC2_USER@$EC2_HOST "
cd /var/www/shareyourthoughts &&
php artisan migrate --force"
- name: Change ownership to www-data
env:
EC2_USER: ${{ secrets.EC2_USER }}
EC2_HOST: ${{ secrets.EC2_HOST }}
run: |
ssh -i key.pem -o StrictHostKeyChecking=no $EC2_USER@$EC2_HOST "sudo chown -R www-data:www-data /var/www/shareyourthoughts"
rm key.pem # Clean up the PEM file after the final deployment
### Changes & Improvements:
1. **Added `php artisan migrate –force`** after installing dependencies to ensure the database schema is updated.
2. **Used `–force` flag** to avoid confirmation prompts in the migration.
3. **Preserved file ownership** by setting it to `www-data` after deployment.
4. **Cleaned up the `key.pem` file** at the end for security.
Let me know if you need further refinements! π