<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: marouane moutih</title>
    <description>The latest articles on DEV Community by marouane moutih (@mmoutih).</description>
    <link>https://dev.to/mmoutih</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F597257%2Fcbcd66d9-5d87-4682-be77-b0640ca2edc3.png</url>
      <title>DEV Community: marouane moutih</title>
      <link>https://dev.to/mmoutih</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mmoutih"/>
    <language>en</language>
    <item>
      <title>Semantic search with OpenAi, SpringBoot, Vaadin, ElasticSearch</title>
      <dc:creator>marouane moutih</dc:creator>
      <pubDate>Tue, 04 Jul 2023 21:21:36 +0000</pubDate>
      <link>https://dev.to/mmoutih/semantic-search-with-openai-springboot-vaadin-elasticsearch-4lhg</link>
      <guid>https://dev.to/mmoutih/semantic-search-with-openai-springboot-vaadin-elasticsearch-4lhg</guid>
      <description>&lt;h2&gt;
  
  
  Semantic search
&lt;/h2&gt;

&lt;p&gt;Semantic search is an information search approach that seeks to understand the meaning and intent behind a query rather than relying solely on the specific keywords used. Unlike traditional search based on exact textual matches, semantic search considers the context, meaning and relationship between words to provide more relevant and accurate results.&lt;/p&gt;

&lt;p&gt;Semantic research uses language analysis, natural language processing (NLP) and artificial intelligence techniques to understand the meaning of words in a given context. It can take into account elements such as synonym, antonymy, co-occurrence, semantic relationships and grammatical structures to improve the understanding of queries and indexed documents.&lt;/p&gt;

&lt;p&gt;One of the key aspects of semantic research is the ability to interpret the intent of the user behind a query. For example, if you enter the query "Best sailing catamarans in Corsica", a semantic search engine will be able to understand that you are looking for sailing catamarans in Corsica, rather than just looking for the words "best", "catamaran", "sailing" and "Corsica" separately.&lt;/p&gt;

&lt;p&gt;In short, semantic research goes beyond keyword matching to understand the overall meaning of a query and provide more relevant results based on the semantic understanding of the language.&lt;/p&gt;

&lt;h2&gt;
  
  
  Give a sense to a request (embedding)
&lt;/h2&gt;

&lt;p&gt;Word embedding is a technique used in the field of automatic natural language processing (TALN) to represent words in the form of numerical vectors in a multidimensional space. These word dips are usually learned from large amounts of text through machine learning models, such as neural networks, which are able to capture the semantic and syntactic relationships between words.&lt;/p&gt;

&lt;p&gt;These vector representations of words are used in many TALN tasks, such as machine translation, information retrieval, sentiment analysis and text classification. Word embedding allows machine learning algorithms to better understand and work with textual data, transforming words into a numerical form more suitable for analysis and modeling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cosine similarity
&lt;/h2&gt;

&lt;p&gt;In data analysis, cosine similarity is a measure of similarity between two non-zero vectors defined in an inner product space. Cosine similarity is the cosine of the angle between the vectors; that is, it is the dot product of the vectors divided by the product of their lengths. It follows that the cosine similarity does not depend on the magnitudes of the vectors, but only on their angle.&lt;/p&gt;

&lt;h2&gt;
  
  
  Elasticsearch
&lt;/h2&gt;

&lt;p&gt;Elasticsearch is a distributed, open-source and highly scalable data search and analysis engine. It is designed to process and analyze large amounts of data in real time. Elasticsearch uses a data structure called "inverted index" to enable quick search and retrieval of information.&lt;/p&gt;

&lt;p&gt;Elasticsearch’s main goal is to provide fast, flexible and easy to implement data search and analysis. It is particularly suitable for indexing and searching text documents, but can also be used for log analysis, real-time monitoring, content recommendation, report generation, and many other use cases.&lt;/p&gt;

&lt;p&gt;In addition to full-text search, Elasticsearch offers advanced features such as data aggregation, geospatial search, similarity search, term suggestion, automatic correction, etc. It also provides RESTful APIs to interact with the system and manage indexes and data.&lt;/p&gt;

&lt;h2&gt;
  
  
  how does it work
&lt;/h2&gt;

&lt;p&gt;Our example combines the three concepts (Semantic search, embedding, Cosine similarity) to create a more powerful search system based on an elasticsearch engine, using java as a programming language, spring-boot and vaadin as stuck and OpenAi for the generation of embedding.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Model
&lt;/h3&gt;

&lt;p&gt;Our model will be a simple post with a content title and our embedding vector.&lt;br&gt;
Using spring-boot-starter-data-elasticsearch we must specify to elasticsearch that our embedding field is a dense vector with a dimension of 1536 bytes to be OpenAi compliant on this subject.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Document&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;indexName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"posts"&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@ToString&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Post&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Id&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Field&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FieldType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Field&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FieldType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Field&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FieldType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Dense_Vector&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dims&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1536&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Double&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;embedding&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Repository
&lt;/h3&gt;

&lt;p&gt;Our repository will simply extend the ElasticsearchRepository. We will just define a function, which will make a match_all request with a scripted score based on cosine similarity between the embedding vector and the search text vector.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Repository&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;PostRepository&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ElasticsearchRepository&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Query&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;"    \"script_score\": {"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;"       \"query\": {\"match_all\": {}},"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;"       \"script\": {"&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;"           \"source\": \"cosineSimilarity(params.queryVector, 'embedding') +0.1\","&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;"           \"params\": {\"queryVector\": ?0}"&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;"       }"&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;"   }"&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;"}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;findBySimilar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The service
&lt;/h3&gt;

&lt;p&gt;Our service must ensure the generation of embedding for each post during  creation and for the text of each search request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Post&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Double&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Double&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;getEmbedding&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="o"&gt;()));&lt;/span&gt;
        &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;embedding&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Double&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Double&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;getEmbedding&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findBySimilar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JsonData&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;toJson&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;JacksonJsonpMapper&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The full exemple
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/mmoutih/sementic-search"&gt;https://github.com/mmoutih/sementic-search&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;flow me on &lt;a href="https://twitter.com/foussil"&gt;twitter&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Laravel multiPatternRoute</title>
      <dc:creator>marouane moutih</dc:creator>
      <pubDate>Wed, 05 May 2021 22:36:45 +0000</pubDate>
      <link>https://dev.to/mmoutih/laravel-multipatternroute-2459</link>
      <guid>https://dev.to/mmoutih/laravel-multipatternroute-2459</guid>
      <description>&lt;p&gt;when we develop a multilingual web application, sometimes we face a case where the pattern of the route is different between two languages.&lt;/p&gt;

&lt;h3&gt;
  
  
  how we can solve such a problem?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;First, we need to create our standard for route names, in our case, we opt for this scheme: "{name}.{locale}" when {name} is the route name and {locale} is a language or a group of languages.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Route::get('/', App\Http\Controllers\Front\HomeController::class)-&amp;gt;name("home.fr");
Route::get('/{locale}', App\Http\Controllers\Front\HomeController::class)-&amp;gt;where(['locale' =&amp;gt; '[a-z]{2,3}'])
    -&amp;gt;name("home.locale");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Second, we need our own Helper to generate URLs. 
we will need a class that will parse the list of routes and get the routes linked to the name we provide, After that the class will take the list of parameters that we pass and return just the parameters needed for the current pattern, also it will inject constant parameters if they exist.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class MultiPatternRoute{

    protected string $locale;
    protected $routes;

    public function __construct()
    {
        $this-&amp;gt;routes =  Route::getRoutes()-&amp;gt;getRoutesByName();
        $this-&amp;gt;locale = app()-&amp;gt;getLocale();
    }

    public function getParameters (string $routeName,array $parameters) : array
    {
        if(!isset($this-&amp;gt;routes[$routeName.".fr"]) || !isset($this-&amp;gt;routes[$routeName.".locale"]))
            throw new \Exception("unknown route : ". $routeName.".fr");

        $route_fr = $this-&amp;gt;getCompiledRoute($this-&amp;gt;routes[$routeName.".fr"]);
        $route_locale = $this-&amp;gt;getCompiledRoute($this-&amp;gt;routes[$routeName.".locale"]);
        if($this-&amp;gt;locale === "fr"){
            $route = $routeName.".fr";
            return [$route,$this-&amp;gt;getStaticParameters($route ,$this-&amp;gt;cleanParameters($parameters, $route_fr-&amp;gt;getVariables(), $route_locale-&amp;gt;getVariables()))];
        }
        $route = $routeName.".locale";
        $parameters = $this-&amp;gt;getStaticParameters($route, $this-&amp;gt;cleanParameters($parameters, $route_locale-&amp;gt;getVariables(), $route_fr-&amp;gt;getVariables()));
        $parameters["locale"] = app()-&amp;gt;getLocale();
        return [$route,$parameters];

    }

    private function getCompiledRoute(RoutingRoute $route): CompiledRoute
    {
        return $route-&amp;gt;getCompiled()!==null?$route-&amp;gt;getCompiled():$route-&amp;gt;toSymfonyRoute()-&amp;gt;compile();
    }

    private  function cleanParameters(array $parameters, array $neededParametersA, array $neededParametersB) : array
    {
        $neededParameters = array_intersect(array_keys($parameters), $neededParametersA);
        $queryStringParameters = array_diff(array_keys($parameters), $neededParametersB);
        $parameters_keys = array_unique (array_merge ($neededParameters,$queryStringParameters));
        return array_filter($parameters, fn($k)=&amp;gt;in_array($k,$parameters_keys),ARRAY_FILTER_USE_KEY);
    }

    private function getStaticParameters(string $routeName, array $parameters) : array
    {

        $controller = $this-&amp;gt;routes[$routeName]-&amp;gt;getController();
        if(!method_exists($controller,'getConstantRouteParameters'))
            return $parameters;
        return array_merge($this-&amp;gt;routes[$routeName]-&amp;gt;getController()::getConstantRouteParameters($this-&amp;gt;locale),$parameters);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Third, we provide this class as Singleton via the container in our AppServiceProvider.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$this-&amp;gt;app-&amp;gt;singleton(
            'MultiPatternRoute',
           function(){
              return new  MultiPatternRoute();
           }
        );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Fourth, we create a helper function that will consume our class and generate our URL.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if ( !function_exists('multiPatternRoute') )
{
    function multiPatternRoute(string $routeName, array $parameters =[], bool $isAbsolute = true){
        list($route, $parameters) = app("MultiPatternRoute")-&amp;gt;getParameters($routeName, $parameters);
        return route($route, $parameters, $isAbsolute);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Fifth, we prepare our controllers to communicate with our class by providing constant parameters if they exist. we do that thanks to a trait as a result.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;trait MultiPatternRoutable
{

    public static function getConstantRouteParameters($locale): array
    {
        return  isset(static::$constantRouteParameters)?static::$constantRouteParameters[$locale]:[];
    }

    public function loadConstantRouteParameters($locale): array
    {
        return array_keys(static::getConstantRouteParameters($locale));
    }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then in the controller&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class DestinationController extends Controller
{
    use MultiPatternRoutable;

    protected static array $constantRouteParameters =[
        "fr" =&amp;gt; [],
        "en" =&amp;gt; ["slugSeo"=&amp;gt;"destinations"],
        "de" =&amp;gt; ["slugSeo"=&amp;gt;"unsere-reiseziele"],
        "it" =&amp;gt; ["slugSeo"=&amp;gt;"destinazioni"],
    ];

    public function __invoke(Request $request, string $slug){
        return view("front.pages.destination", compact("slug"));
    }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;finally, we add a middleware to clean the request object from the constant or unnecessary parameters for the current route.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Locale
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle(Request $request, Closure $next)
    {
        $locale = isset($request-&amp;gt;route()-&amp;gt;parameters['locale'])?$request-&amp;gt;route()-&amp;gt;parameters['locale']:null;
        if($locale){
            app()-&amp;gt;setLocale($locale);
            $request-&amp;gt;route()-&amp;gt;forgetParameter('locale');
        }
        $otherParameterToForgot =$request-&amp;gt;route()-&amp;gt;getController()-&amp;gt;loadConstantRouteParameters(app()-&amp;gt;getLocale());
        foreach($otherParameterToForgot as $parameter){
            $request-&amp;gt;route()-&amp;gt;forgetParameter($parameter);
        }
        return $next($request);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then in our route file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Route::group(["middleware" =&amp;gt; ["locale"]], function () {

    Route::get('/', App\Http\Controllers\Front\HomeController::class)-&amp;gt;name("home.fr");
    Route::get('/{locale}', App\Http\Controllers\Front\HomeController::class)-&amp;gt;where(['locale' =&amp;gt; '[a-z]{2,3}'])
    -&amp;gt;name("home.locale");

    Route::get("/{locale}/{slugSeo}", App\Http\Controllers\Front\DestinationsController::class)
        -&amp;gt;where(['locale' =&amp;gt; '[a-z]{2,3}', 'slugSeo' =&amp;gt; 'tutte-destinazioni|unsere-reiseziele|destinations-all'])
        -&amp;gt;name("destinations.locale");
    Route::get("/destinations/notre-list-destination", App\Http\Controllers\Front\DestinationsController::class)
        -&amp;gt;name("destinations.fr");

    Route::get("/{locale}/{slugSeo}/{slug}", App\Http\Controllers\Front\DestinationController::class)
        -&amp;gt;where(['locale' =&amp;gt; '[a-z]{2,3}', 'slugSeo' =&amp;gt; 'destinazioni|reiseziele|destinations'])
        -&amp;gt;name("destination.locale");
    Route::get("/destinations-{slug}-produit-{slugAlt}.html", App\Http\Controllers\Front\DestinationController::class)
        -&amp;gt;name("destination.fr");
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then in blade file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; &amp;lt;a href="{{ multiPatternRoute('destination',["slug"=&amp;gt;"france","slugAlt"=&amp;gt;"france"]) }}"&amp;gt;France&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>laravel</category>
      <category>php</category>
    </item>
  </channel>
</rss>
