# cPanel Deployment Guide - Fix "symlink(): File exists" Error

## THE PROBLEM
Laravel creates symlinks from `public/storage` → `storage/app/public`, but **cPanel shared hosting often doesn't support symlinks** or the symlink gets corrupted during upload, causing the error:

```
symlink(): File exists
```

## THE SOLUTION
This project is configured to **NEVER use symlinks**. Instead:
- Files are saved **directly to `public/storage`**
- The `storage:link` command has been overridden to copy files instead
- The filesystem config points directly to `public/storage`

---

## 🚀 DEPLOYMENT STEPS

### METHOD 1: Using the Fix Script (RECOMMENDED)

#### Step 1: Upload Files to cPanel
1. Compress your project to `.zip`
2. Upload via cPanel File Manager
3. Extract in `public_html` or your domain folder

#### Step 2: Run Fix Script via SSH
```bash
cd /home/yourusername/public_html
php fix-symlinks.php
```

#### Step 3: Run Setup Script
```bash
chmod +x cpanel-setup.sh
./cpanel-setup.sh
```

#### Step 4: Configure Environment
Edit `.env` file with your production database credentials:
```
APP_URL=https://test.algopk.com
DB_HOST=localhost
DB_DATABASE=your_database
DB_USERNAME=your_username
DB_PASSWORD=your_password
```

#### Step 5: Final Optimization
```bash
php artisan config:cache
php artisan route:cache
php artisan view:cache
```

---

### METHOD 2: Manual Fix (If SSH Not Available)

#### Via cPanel Terminal or File Manager

1. **Delete the symlink** (if it exists):
   - Navigate to `public_html/public/`
   - Look for `storage` (it might show as a link/arrow icon)
   - Delete it completely

2. **Create real directory**:
   - In `public_html/public/`, create a new folder named `storage`
   - Set permissions to `755`

3. **Ensure storage/app/public exists**:
   - Navigate to `storage/app/`
   - Create `public` folder if it doesn't exist
   - Set permissions to `755`

4. **Set all permissions**:
   ```
   storage/ → 755 (and all subfolders)
   bootstrap/cache/ → 755
   public/storage/ → 755
   .env → 644
   ```

---

### METHOD 3: Before Upload (Prevent the Issue)

Run this on your local machine **BEFORE** uploading:

```bash
# Remove any existing symlink
php fix-symlinks.php

# OR manually:
rm -rf public/storage         # Unix/Mac
rmdir public\storage          # Windows

# Create real directory
mkdir public/storage
mkdir -p storage/app/public
```

Then upload to cPanel.

---

## 🔧 TROUBLESHOOTING

### Error: "symlink(): File exists"
**Cause**: A symlink or file already exists at `public/storage`

**Solution**:
```bash
rm -rf public/storage  # Remove it completely
mkdir public/storage   # Create as real directory
php artisan storage:link  # This will copy files (not create symlink)
```

### Error: "No such file or directory"
**Cause**: `storage/app/public` doesn't exist

**Solution**:
```bash
mkdir -p storage/app/public
chmod 755 storage/app/public
```

### Files Upload to Storage but Don't Show
**Cause**: Files might be in `storage/app/public` instead of `public/storage`

**Solution**:
```bash
# Copy files from storage/app/public to public/storage
cp -r storage/app/public/* public/storage/
```

### Permission Denied Errors
**Solution**:
```bash
chmod -R 755 storage
chmod -R 755 bootstrap/cache
chmod -R 755 public/storage
```

---

## ⚙️ CONFIGURATION FILES MODIFIED

The following files have been modified for cPanel compatibility:

### 1. `config/filesystems.php`
```php
'public' => [
    'driver' => 'local',
    'root' => public_path('storage'),  // Direct path, no symlink needed
    'url' => env('APP_URL').'/storage',
    'visibility' => 'public',
],
```

### 2. `app/Console/Commands/StorageLinkCommand.php`
- Overrides Laravel's default `storage:link` command
- Creates real directory instead of symlink
- Copies files from `storage/app/public` to `public/storage`

### 3. `app/Console/Commands/StorageLinkSafe.php`
- Alternative safe linking command
- Use: `php artisan storage:link-safe`

---

## 🎯 BEST PRACTICES FOR CPANEL

1. **Never use `php artisan storage:link` on local** before uploading (it creates symlinks)

2. **Always run the fix script** after uploading:
   ```bash
   php fix-symlinks.php
   ```

3. **Use rsync for file sync** (if you update local files):
   ```bash
   rsync -av storage/app/public/ public/storage/
   ```

4. **Check after deployment**:
   ```bash
   ls -la public/ | grep storage
   ```
   Should show: `drwxr-xr-x` (directory) NOT `lrwxrwxrwx` (symlink)

5. **Set up cron job** for storage sync (optional):
   ```
   0 * * * * cd /home/user/public_html && rsync -a storage/app/public/ public/storage/
   ```

---

## 📝 VERIFICATION CHECKLIST

After deployment, verify:

- [ ] No `symlink(): File exists` errors
- [ ] `public/storage` is a **real directory** (not a symlink)
- [ ] `storage/app/public` exists
- [ ] Permissions: `storage/` = 755, `bootstrap/cache/` = 755
- [ ] `.env` has correct database credentials
- [ ] `APP_URL` in `.env` matches your domain
- [ ] Can upload files through application
- [ ] Uploaded files are accessible via browser
- [ ] Clear cache: `php artisan cache:clear`

---

## 🆘 STILL HAVING ISSUES?

If you're still getting symlink errors:

1. **Check if old symlink exists**:
   ```bash
   ls -la public/storage
   ```

2. **Force remove everything**:
   ```bash
   rm -rf public/storage
   rm -rf storage/app/public
   ```

3. **Recreate properly**:
   ```bash
   mkdir -p public/storage
   mkdir -p storage/app/public
   chmod -R 755 public/storage
   chmod -R 755 storage/app/public
   ```

4. **Clear all caches**:
   ```bash
   php artisan config:clear
   php artisan cache:clear
   php artisan view:clear
   php artisan route:clear
   ```

5. **Run the custom command**:
   ```bash
   php artisan storage:link
   ```

---

## 📞 SUPPORT

If problems persist:
- Check cPanel error logs: `public_html/storage/logs/laravel.log`
- Check PHP error logs in cPanel
- Verify PHP version is 8.1+ in cPanel
- Ensure all required PHP extensions are enabled

---

**Last Updated**: 2025
**Compatible With**: Laravel 10.x, cPanel/WHM
