# Routing

# Service Provider

When Lodata is installed via composer it registers (opens new window) a Service Provider.

This provider sets up an instance of Flat3\Lodata\Model as a singleton in the service container, and configures all the routes and middleware. There are hooks in the configuration to modify the behaviour of the service provider.

View the service provider
<?php

declare(strict_types=1);

namespace Flat3\Lodata;

use Flat3\Lodata\Controller\Monitor;
use Flat3\Lodata\Controller\OData;
use Flat3\Lodata\Controller\ODCFF;
use Flat3\Lodata\Controller\PBIDS;
use Flat3\Lodata\Controller\Response;
use Flat3\Lodata\Helper\Filesystem;
use Flat3\Lodata\Helper\Flysystem;
use Flat3\Lodata\Helper\Symfony;
use Illuminate\Support\Facades\Route;
use Symfony\Component\HttpKernel\Kernel;

/**
 * Service Provider
 * @link https://laravel.com/docs/8.x/providers
 * @package Flat3\Lodata
 */
class ServiceProvider extends \Illuminate\Support\ServiceProvider
{
    /**
     * Get the endpoint of the OData service document
     * @return string
     */
    public static function endpoint(): string
    {
        return url(self::route()).'/';
    }

    /**
     * Get the configured route prefix
     * @return string
     */
    public static function route(): string
    {
        return rtrim(config('lodata.prefix'), '/');
    }

    /**
     * Service provider registration method
     */
    public function register()
    {
        $this->mergeConfigFrom(__DIR__.'/../config.php', 'lodata');
    }

    /**
     * Service provider boot method
     */
    public function boot()
    {
        if ($this->app->runningInConsole()) {
            $this->publishes([__DIR__.'/../config.php' => config_path('lodata.php')], 'config');
        }

        $this->loadJsonTranslationsFrom(__DIR__.'/../lang');

        $this->app->singleton(Model::class, function () {
            return new Model();
        });

        $this->app->bind('lodata.model', function ($app) {
            return $app->make(Model::class);
        });

        $this->app->bind(Response::class, function () {
            return Kernel::VERSION_ID < 60000 ? new Symfony\Response5() : new Symfony\Response6();
        });

        $this->app->bind(Filesystem::class, function () {
            return class_exists('League\Flysystem\Adapter\Local') ? new Flysystem\Flysystem1() : new Flysystem\Flysystem3();
        });

        $route = self::route();
        $middleware = config('lodata.middleware', []);

        Route::get("{$route}/_lodata/odata.pbids", [PBIDS::class, 'get']);
        Route::get("{$route}/_lodata/{identifier}.odc", [ODCFF::class, 'get']);
        Route::resource("{$route}/_lodata/monitor", Monitor::class);
        Route::any("{$route}{path}", [OData::class, 'handle'])->where('path', '(.*)')->middleware($middleware);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

# Existing controllers

In addition to using the standard routing provided out of the box, Lodata supports mounting resources on routes managed by existing controllers. This can be useful if you are adding Lodata to an existing project that has middleware, authentication, authorization and a routing structure already in place.

The first step is to define the OData resource route, somewhere inside an existing service provider. In this example we have a UserController mounting the OData path as query within the users group.

public function boot()
{   
    $this->configureRateLimiting();

    $this->routes(function () {
        Route::prefix('users')->group(function ($router) {
            $router->any("query{path}", [UserController::class, 'query'])->where('path', '(.*)');
        });
    });
}
1
2
3
4
5
6
7
8
9
10

Then the query method is added to the controller, rewriting the path to the original OData route for processing. Note the use of Lodata's own Request object being injected into the method, not the standard Laravel object.

use Flat3\Lodata\Controller\Request;
use Flat3\Lodata\Controller\Transaction;
use Flat3\Lodata\Tests\Request;
use Flat3\Lodata\Tests\TestCase;
use Illuminate\Routing\Controller;

class UserController extends Controller
{
    public function query(Request $request, Transaction $transaction, ?string $path = '')
    {
        $request->setPath('/odata/airports'.$path);

        return $transaction->initialize($request)->execute();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Now the airports entity set can be accessed using the URL http://localhost:8000/users/query. With the controller function having early access to the Request object, you could also overwrite or set default query parameters and headers if required to support your client application.

The canonical entity ID and read link metadata exposed on this customized route will still refer to the standard OData URL such as http://localhost:8000/odata/Users(1), making this route effectively an alias for the canonical route.