Laravel 8和9 API路线从子文件夹,它仍然有效吗?

发布于 2025-02-05 18:14:09 字数 1610 浏览 4 评论 0 原文

我刚刚使用Postman测试API。当我不使用子目录时,API正常工作正常

但是,如果我使用了子目录,它将找不到404,即使我配置 nano/etc/etc/nginx/stites-abailable/mobilku 也通过添加此行遵循此链接: subfolder中的laravel for Laravel for Subfolder

location /mobilku {
    alias var/www/html/mobilku/public;
    try_files $uri $uri/ /index.php$args;
    location ~ \.php$ {
        include snippet/fastcgi-php.conf;
        fastcgi_param SCRIPT_FILENAME $request_filename;
        fastcgi_pass unix:/run/php/php8.1-fpm.sock;
    }
}

中这样返回

问题是,如何使子文件夹中的API路线仍然像上面的图片一样工作? 这是我使用API​​获取汽车的示例代码

Route::prefix('car')->group(function () {
    Route::get('/', [CarController::class, 'all'])->name('car');
    Route::get('/details/{id}', [CarController::class, 'details'])->name('car.detail');
    Route::post('/search', [CarController::class, 'search'])->name('car.search');
    Route::post('/filter', [CarController::class, 'filter'])->name('car.filter');
});

,我刚刚读取此链接 laravel路线子文件夹,但我不确定这个答案仍然适用于Laravel 8和9。

I've just test the API using Postman. When I don't using sub-directory, the API works fine like this
enter image description here

But if I using sub-directory, it returns 404 Not Found, like this, even I configure nano/etc/nginx/sites-available/mobilku by adding this line following this link :
Config nginx for Laravel In a subfolder

location /mobilku {
    alias var/www/html/mobilku/public;
    try_files $uri $uri/ /index.php$args;
    location ~ \.php$ {
        include snippet/fastcgi-php.conf;
        fastcgi_param SCRIPT_FILENAME $request_filename;
        fastcgi_pass unix:/run/php/php8.1-fpm.sock;
    }
}

the output when I using subfolder it return like this
enter image description here

the question is, how to make API routes from subfolder still works like picture in above?
Here is my example code for get car using API

Route::prefix('car')->group(function () {
    Route::get('/', [CarController::class, 'all'])->name('car');
    Route::get('/details/{id}', [CarController::class, 'details'])->name('car.detail');
    Route::post('/search', [CarController::class, 'search'])->name('car.search');
    Route::post('/filter', [CarController::class, 'filter'])->name('car.filter');
});

I just read this link Laravel routes not working with subfolder, but I'm not sure that answer still works for Laravel 8 and 9.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

少女七分熟 2025-02-12 18:14:10

Laravel应用程序知道它默认情况下是服务器的根。

尝试一下,希望它能为您提供帮助:

源: https://lucabecchetti.medium.com/configure-laravel-to-work-work-work-work-work-work-in-a-a-a-subdirectory-and-with-with-with-with-with-with-with-artisan-serv-serv------ -same-time-654ba0c1fd0b

添加app_dir环境变量在.env文件中,包含安装在Laravel的子目录中,如下所示:

APP_DIR = "laravel_subdir"

然后创建一个助手提供商来定义我们的自定义功能,创建一个File file helperServiceProvide.phpservice.php.phpper.php.php.php内部提供程序目录,具有以下代码:

<?php
    namespace App\Providers;
    use Illuminate\Support\ServiceProvider;
    class HelperServiceProvider extends ServiceProvider{
    /**
    * Bootstrap services.
    *
    * @return void
    */
    public function boot(){
    }
    /**
    * Register services.
    *
    * @return void
    */
    public function register(){
      foreach (glob(app_path() . '/Helpers/*.php') as $file) {
        require_once($file);
      }
    }
}

然后,在App Directory级别,添加助手目录,并在其中创建一个文件subdirectoryAssetshelper.php,并使用以下代码:

<?php
    if (! function_exists('subdirAsset')) {
    function subdirAsset($path){
        return asset( (App::environment('production') ? env('APP_DIR') : '')."/".$path);
        }
    }
    if (! function_exists('subdirMix')) {
        function subdirMix($path){
            return mix( (App::environment('production') ? env('APP_DIR') : '')."/".$path);
        }
    }

现在通过将此行添加到配置/应用程序来注册提供商.php文件:

App\Providers\HelperServiceProvider::class

现在替换文件routeserviceProvider.php的函数mapWebrout,如下所示:

/**
* Define the "web" routes for the application.
*
* These routes all receive session state, CSRF protection, etc.
*
* @return void
*/
protected function mapWebRoutes(){
    Route::prefix(App::environment('production') ? env('APP_DIR') : '')
    ->middleware('web')
    ->namespace($this->namespace)
    ->group(base_path('routes/web.php'));
}

并在文件顶部导入应用程序类:

use app;
仅此而已,现在您可以使用函数子dirasset,而不是资产和子签名,而不是在刀片文件中混合。

开关环境
如果您使用的是代客或工匠服务,请将您的app_env变量保持在“本地”:

APP_ENV = local

如果您处于共享托管的生产环境中,请使用:

APP_ENV = production

The Laravel application understands that it is at the root of the server by default.

Try this, I hope it helps you:

source: https://lucabecchetti.medium.com/configure-laravel-to-work-in-a-subdirectory-and-with-artisan-serve-at-the-same-time-654ba0c1fd0b

Add APP_DIR environment variable to your .env file, containing the subdirectory where Laravel is installed into, like showed below:

APP_DIR = "laravel_subdir"

Then create a Helper Provider to define our custom functions, create a file HelperServiceProvider.php inside Providers directory, with the following code:

<?php
    namespace App\Providers;
    use Illuminate\Support\ServiceProvider;
    class HelperServiceProvider extends ServiceProvider{
    /**
    * Bootstrap services.
    *
    * @return void
    */
    public function boot(){
    }
    /**
    * Register services.
    *
    * @return void
    */
    public function register(){
      foreach (glob(app_path() . '/Helpers/*.php') as $file) {
        require_once($file);
      }
    }
}

Then, at the level of App directory, add Helpers directory, and inside it, create a file SubdirectoryAssetsHelper.php, with the following code:

<?php
    if (! function_exists('subdirAsset')) {
    function subdirAsset($path){
        return asset( (App::environment('production') ? env('APP_DIR') : '')."/".$path);
        }
    }
    if (! function_exists('subdirMix')) {
        function subdirMix($path){
            return mix( (App::environment('production') ? env('APP_DIR') : '')."/".$path);
        }
    }

Now register the provider by adding this line to config/app.php file:

App\Providers\HelperServiceProvider::class

Now replace the function mapWebRoutes of file RouteServiceProvider.php, like showed below:

/**
* Define the "web" routes for the application.
*
* These routes all receive session state, CSRF protection, etc.
*
* @return void
*/
protected function mapWebRoutes(){
    Route::prefix(App::environment('production') ? env('APP_DIR') : '')
    ->middleware('web')
    ->namespace($this->namespace)
    ->group(base_path('routes/web.php'));
}

And import App class in top of file:

use App;
That’s all, now you can use function subdirAsset instead of asset and subdirMix instead of mix inside your blade files.

Switch environment
If you are using valet or artisan serve, keep your APP_ENV variable to “local”:

APP_ENV = local

If you are in a production environment of shared hosting, use:

APP_ENV = production
橘和柠 2025-02-12 18:14:09

Laravel Web应用程序配置

根据laravel v8 v8 和 v9 文档,laravel v5 (此外,您的路线现在应该从/与V5中的前缀不同。引用 v9 )以在全球范围内定义这样的前缀。

但是,当您将应用程序放置在附加的URI前缀下时,它将所有路由都视为/mobilku/api/.... 而不是/api/..... ,因此,您应该更改Laravel应用程序的其他代码部分,而您在问题中没有显示以进行此类更改(或者您可以从某种程度上“欺骗”它会从一边看到的uri;请参阅最后一部分答案)。您还可以考虑仅重命名/api uri前缀/mobilku 一个。

nginx配置

使用别名指令在URI前面使用PHP Web应用程序有点棘手97“ rel =“ nofollow noreferrer”> try_files 的副作用与 Alias 一起使用的指令由于以某种方式对这些效果采用了太多配置,因此主要的Nginx版本会更改。常用的解决方法是:

  • 使用PHP处理程序作为自定义HTTP 404错误处理程序,而不是 try_files 指令:

      location /mobilku {
        别名var/www/html/mobilku/public;
        error_page 404 = /mobilku/index.php$iis_args$Args;
        位置〜\ .php $ {
            包括摘要/fastcgi-php.conf;
            fastcgi_param script_filename $ request_filename;
            fastcgi_pass unix:/run/php/php8.1-fpm.sock;
        }
    }
     
  • 复制 try_files 指令>指令最后一个参数前缀:

      location /mobilku {
        别名var/www/html/mobilku/public;
        try_files $ uri $ uri///mobilku/mobilku/index.php $ is_args$Args;
        位置〜\ .php $ {
            包括摘要/fastcgi-php.conf;
            fastcgi_param script_filename $ request_filename;
            fastcgi_pass unix:/run/php/php8.1-fpm.sock;
        }
    }
     
  • 使用而不是而不是 try_files

      location /mobilku {
        别名var/www/html/mobilku/public;
        如果(!-e $ request_filename){重写 ^ /mobilku/index.php last; }
        位置〜\ .php $ {
            包括摘要/fastcgi-php.conf;
            fastcgi_param script_filename $ request_filename;
            fastcgi_pass unix:/run/php/php8.1-fpm.sock;
        }
    }
     
  • 使用附加命名的位置作为 try_files 指令最后参数:

      location /mobilku {
        别名var/www/html/mobilku/public;
        try_files $ uri $ uri/ @mobilku;
        位置〜\ .php $ {
            包括摘要/fastcgi-php.conf;
            fastcgi_param script_filename $ request_filename;
            fastcgi_pass unix:/run/php/php8.1-fpm.sock;
        }
    }
    位置@mobilku {
        重写 ^ /mobilku/index.php last;
    }
     

但是,当您提供根本没有静态文件的API Web应用程序时,都不需要这些解决方法,任何传入的请求都应应由 index.php 控制器服务。更有效的方法,而无需通过不同的位置遍历请求,检查静态文件存在并与 \。php $ REGEX模式(调用昂贵的PCRE库调用)将是以下内容:

location /mobilku {
    root /var/www/html/mobilku/public;
    rewrite ^ /index.php break;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$uri;
    fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}

欺骗一个请求URI,Laravel应用将看到Laravel应用程序

看到的原始请求URI通过 request> request_uri fastcgi变量传递给PHP-fpm后端,该变量已在 fastcgi_params file好像

fastcgi_param  REQUEST_URI        $request_uri;

出于某种原因无法更改后端Laravel(或任何其他基于PHP的)Web应用程序,您仍然可以更改正在传递的 request> request_uri fastcgi变量值到后端。

- 只有nginx变量,因此您无法使用 set 指令更改其值。但是,您可以在之后重新定义其值,它将在 fastcgi_params 文件中定义。 The PHP-FPM FastCGI backend will use the last defined value (although other FastCGI backends can behave differently; you can check

location /mobilku {
    root /var/www/html/mobilku/public;
    rewrite /mobilku/?(.*) /$1;
    set $tweaked_uri $uri$is_args$args;
    rewrite ^ /index.php break;
    include fastcgi_params;
    fastcgi_param REQUEST_URI $tweaked_uri;
    fastcgi_param SCRIPT_FILENAME $document_root$uri;
    fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}

或以下一个替换/mobilku 带有/api 的前缀:

location /mobilku {
    root /var/www/html/mobilku/public;
    rewrite /mobilku/?(.*) /api/$1;
    set $tweaked_uri $uri$is_args$args;
    rewrite ^ /index.php break;
    include fastcgi_params;
    fastcgi_param REQUEST_URI $tweaked_uri;
    fastcgi_param SCRIPT_FILENAME $document_root$uri;
    fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}

但是,如果您的原始URI包含一些在URI归一化过程中被URL编码的字符,则可能是不可靠的(例如,某些特殊字符或来自国家字母的两个字节UTF-8字符),因为重写指令(以及 location 一个)与标准化的URI一起使用,而PHP后端期望看到一个URL编码一个。一种更可靠的方法是使用剥离或替换URI前缀的块,例如

map $request_uri $tweaked_uri {
    ~^/mobilku/?(.*)  /$1;
    default           $request_uri;
}

map $request_uri $tweaked_uri {
    ~^/mobilku/?(.*)  /api/$1;
    default           $request_uri;
}

您可以使用映射的 $ tweaked_uri 变量与上一个示例中所示的方式相同:

location /mobilku {
    root /var/www/html/mobilku/public;
    rewrite ^ /index.php break;
    include fastcgi_params;
    fastcgi_param REQUEST_URI $tweaked_uri;
    fastcgi_param SCRIPT_FILENAME $document_root$uri;
    fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}

laravel web app configuration

According to the laravel v8 and v9 documentation, there are no big changes from the laravel v5 (besides that your routes should now start with the / prefix unlike it was in v5). Both answers from the referred thread also suggests to use a RouteServiceProvider (v8, v9) to define such a prefix globally.

However when you place your app under an additional URI prefix, it will see all the routes as /mobilku/api/... rather than /api/..., so you should change some other code part of your laravel app that you didn't show in your question to made it ready for such a change (or you can somewhat "spoof" the URI it will see from it's side; see the last part of the answer). You may also consider to just rename an /api URI prefix to the /mobilku one.

nginx configuration

Serving a PHP web app under an URI prefix using the alias directive is a bit tricky due the the long standing side effects of the try_files directive used together with the alias one, which are unlikely to be fixed at least until the major nginx version gets changed since there are too many configurations exists adopted to those effects in some way. Commonly used workarounds are:

  • using PHP handler as the custom HTTP 404 error handler instead of the try_files directive:

    location /mobilku {
        alias var/www/html/mobilku/public;
        error_page 404 = /mobilku/index.php$is_args$args;
        location ~ \.php$ {
            include snippet/fastcgi-php.conf;
            fastcgi_param SCRIPT_FILENAME $request_filename;
            fastcgi_pass unix:/run/php/php8.1-fpm.sock;
        }
    }
    
  • duplicating the try_files directive last argument prefix:

    location /mobilku {
        alias var/www/html/mobilku/public;
        try_files $uri $uri/ /mobilku/mobilku/index.php$is_args$args;
        location ~ \.php$ {
            include snippet/fastcgi-php.conf;
            fastcgi_param SCRIPT_FILENAME $request_filename;
            fastcgi_pass unix:/run/php/php8.1-fpm.sock;
        }
    }
    
  • using an if instead of the try_files:

    location /mobilku {
        alias var/www/html/mobilku/public;
        if (!-e $request_filename) { rewrite ^ /mobilku/index.php last; }
        location ~ \.php$ {
            include snippet/fastcgi-php.conf;
            fastcgi_param SCRIPT_FILENAME $request_filename;
            fastcgi_pass unix:/run/php/php8.1-fpm.sock;
        }
    }
    
  • using an additional named location as the try_files directive last argument:

    location /mobilku {
        alias var/www/html/mobilku/public;
        try_files $uri $uri/ @mobilku;
        location ~ \.php$ {
            include snippet/fastcgi-php.conf;
            fastcgi_param SCRIPT_FILENAME $request_filename;
            fastcgi_pass unix:/run/php/php8.1-fpm.sock;
        }
    }
    location @mobilku {
        rewrite ^ /mobilku/index.php last;
    }
    

However none of those workarounds are needed when you are serving an API web app that doen't have any static files at all, and any incoming request should be served by the index.php controller. The much more efficient way, without traversing the request though different location, checking the static files existence and matching an URI against the \.php$ regex pattern (invoking an expensive PCRE library call) will be the following:

location /mobilku {
    root /var/www/html/mobilku/public;
    rewrite ^ /index.php break;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$uri;
    fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}

Spoofing a request URI that will be seen by the laravel app

An original request URI seen by laravel application is passed to the PHP-FPM backend via the REQUEST_URI FastCGI variable, which is being defined inside the fastcgi_params file as

fastcgi_param  REQUEST_URI        $request_uri;

If for some reason you can't change your backend laravel (or any other PHP based) web app, you still can change the REQUEST_URI FastCGI variable value that is being passed to the backend.

That $request_uri is an internal read-only nginx variable, so you can't change its value using set directive. However you can redefine its value after it will be defined inside the fastcgi_params file. The PHP-FPM FastCGI backend will use the last defined value (although other FastCGI backends can behave differently; you can check this ServerFault thread to find out more some details). To strip the /mobilku URI prefix from the REQUEST_URI FastCGI variabe you can use an additional rewrite directive:

location /mobilku {
    root /var/www/html/mobilku/public;
    rewrite /mobilku/?(.*) /$1;
    set $tweaked_uri $uri$is_args$args;
    rewrite ^ /index.php break;
    include fastcgi_params;
    fastcgi_param REQUEST_URI $tweaked_uri;
    fastcgi_param SCRIPT_FILENAME $document_root$uri;
    fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}

or the following one to replace the /mobilku prefix with the /api:

location /mobilku {
    root /var/www/html/mobilku/public;
    rewrite /mobilku/?(.*) /api/$1;
    set $tweaked_uri $uri$is_args$args;
    rewrite ^ /index.php break;
    include fastcgi_params;
    fastcgi_param REQUEST_URI $tweaked_uri;
    fastcgi_param SCRIPT_FILENAME $document_root$uri;
    fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}

However it can be unreliable if your original URI contain some characters that are getting url-decoded during the URI normalization process (for example, some special characters or two bytes UTF-8 characters from national alphabets) because the rewrite directive (as well as the location one) works with the normalized URI while a PHP backend expect to see an url-encoded one. A more reliable way would be to use a map block to strip or replace URI prefix, e.g.

map $request_uri $tweaked_uri {
    ~^/mobilku/?(.*)  /$1;
    default           $request_uri;
}

or

map $request_uri $tweaked_uri {
    ~^/mobilku/?(.*)  /api/$1;
    default           $request_uri;
}

Then you can use a mapped $tweaked_uri variable the same way as shown in the previous example:

location /mobilku {
    root /var/www/html/mobilku/public;
    rewrite ^ /index.php break;
    include fastcgi_params;
    fastcgi_param REQUEST_URI $tweaked_uri;
    fastcgi_param SCRIPT_FILENAME $document_root$uri;
    fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文