skip to Main Content

I’ve got this code architecture :

  • root
    • locales
    • subdomain1
      • locales
    • subdomain2
      • locales
    • .env

In my .env, I’ve got an env file called "DOMAIN=XXX". If that variable is not set, /root/locales is used. If it’s set DOMAIN=subdomain1, I want the locales file of the subdomain to be used /root/subdomain1/locales.

Knowing that in my env I got DOMAIN=subdomain1, I want PHP to change that path to /root/subdomain1/locales/XXX.

Example :

// In index.php I got 
symlink('/root/locales/XXX', '/root/subdomain1/locales/XXX'); // I get the "subdomain1" from the .env variable

// In other files I've got
require_once('/root/locales/XXX')

I’ve tried using PHP’s symlink function, but it doesn’t do anything. Am I using that function properly? Does any of you have other ways of doing this? I can not change the path manually in every require/include cuz I’ve got thousands.

EDIT :
In other files I’ve got require_once(‘/root/locales/XXX’) that I’m not able to change, that’s why I want to create a symlink, to update the path for all the require_once that exists without having to edit each and every one.

2

Answers


  1. You can’t have both a file and a symlink with the same name in the same directory, so your call to symlink() can’t work.

    A solution would be to change your hierarchy to the following:

    • root
      • main
        • locales
      • subdomain1
        • locales
      • subdomain2
        • locales
      • .env

    When DOMAIN is not defined, create a symlink like this (beware of the parameter order of symlink()):

    symlink('/root/main/locales', '/root/locales');
    

    When DOMAIN is defined, create a symlink like this:

    symlink('/root/'.$_ENV['DOMAIN'].'/locales', '/root/locales');
    

    You can handle both cases at once:

    $domain = $_ENV['DOMAIN'] ?? 'main';
    @unlink('/root/locales');
    symlink("/root/$domain/locales", '/root/locales');
    

    You will find a simple online test here which shows that symlinks actually work.

    Of course, the PHP user will need permission to create a symlink in /root, so it may still fail.

    But do you really need to create it on the fly? Can the .env file suddenly change? If not, then you should just
    manually create the symlink on the command line.

    Finally, another solution would be to fix your PHP scripts to include the correct file. You said
    "I cannot change the path manually" because you have many, but nothing prevents you from writing a utility that
    automatically scans and fixes your scripts. Basically you just need to replace the line:

    require_once('/root/locales/XXX');
    

    with another implementation, so it’s a simple search and replace.

    Login or Signup to reply.
  2. You can achieve the desired behavior by dynamically creating symbolic links based on the value of the "DOMAIN" environment variable in your .env file. Here’s a PHP script that you can use to create the appropriate symbolic link:

    // Load the value of the "DOMAIN" environment variable from .env
    $domain = getenv("DOMAIN");
    
    if ($domain) {
        // Define the source and target paths for the symbolic link
        $source = "/root/locales/XXX";
        $target = "/root/{$domain}/locales/XXX";
    
        // Check if the symbolic link already exists
        if (!file_exists($target)) {
            // Create the symbolic link
            if (symlink($source, $target)) {
                echo "Symbolic link created successfully.";
            } else {
                echo "Failed to create symbolic link.";
            }
        } else {
            echo "Symbolic link already exists.";
        }
    } else {
        echo "The 'DOMAIN' environment variable is not set.";
    }
    

    This script first checks if the "DOMAIN" environment variable is set. If it’s set to "subdomain1," for example, it will create a symbolic link from /root/locales/XXX to /root/subdomain1/locales/XXX. If the symbolic link already exists, it will display a message indicating that. If the "DOMAIN" variable is not set, it will indicate that as well.

    You can place this code in your PHP application where it initializes, and it will automatically create the necessary symbolic links based on the "DOMAIN" variable, without the need to manually change paths in your require_once statements.

    If there’s a folder or directory in the way of the symlink, creating the symlink might fail unless you ensure that the intermediate directories exist. You can use PHP’s mkdir function to create the necessary intermediate directories if they don’t already exist. Here’s an updated version of the PHP script that includes this check:

    // Load the value of the "DOMAIN" environment variable from .env
    $domain = getenv("DOMAIN");
    
    if ($domain) {
        // Define the source and target paths for the symbolic link
        $source = "/root/locales/XXX";
        $target = "/root/{$domain}/locales/XXX";
    
        // Create the intermediate directories if they don't exist
        $dir = dirname($target);
        if (!file_exists($dir)) {
            if (!mkdir($dir, 0755, true)) {
                echo "Failed to create intermediate directories.";
                exit;
            }
        }
    
        // Check if the symbolic link already exists
        if (!file_exists($target)) {
            // Create the symbolic link
            if (symlink($source, $target)) {
                echo "Symbolic link created successfully.";
            } else {
                echo "Failed to create symbolic link.";
            }
        } else {
            echo "Symbolic link already exists.";
        }
    } else {
        echo "The 'DOMAIN' environment variable is not set.";
    }
    

    This updated script first checks if the intermediate directories exist and creates them if needed using mkdir. Then, it proceeds to create the symbolic link as before. This should handle cases where directories along the path of the symlink might not exist yet.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search