2

2021: This was in fact an issue with the package. Regex link matching has since been implemented with the solution I created to solve it for myself. You can read about it in the documentation here.


I'm using Laravel 5.8 with AdminLTE for Laravel.

There's several options to create a menu, one of which is to create it in the provided config file, which I use.

You can specify an active key in the menu that allows you to make the menu have the class that makes the menu item active and activates the dropdown.

I have a menu item, which I would like to make active on these pages:

  • /posts (works with active => ['/posts'])
  • /posts/{post_id} (id are only numbers)

These URL's shouldn't match:

  • /posts/create
  • /posts/anyotherlink
  • /posts/1text

I can not use /posts/* because that would make the create page and some others active.

The readme suggest that you can also use regex to do this. I don't use regex at all, but I came to this, which, according tot regex101 seems to match what I need it to:

^\/posts\/[0-9]+$

I've tried to implement it like so:

[
    'text'    => 'Posts overview',
    'url'     => '/posts',
    'icon'    => 'list',
    'active'  => ['/posts', '^\/posts\/[0-9]+$'],
    'active'  => ['/posts', '/posts/[^0-9]'] // also tried this
],

Unfortunately, this does not seem to work as it doesn't make the menu item active on the pages listed above.

Edit: I've also created an issue in the GitHub repository as I suspect that this might be an issue with the package.

Am I missing something, or doing something wrong?

rpm192
  • 2,630
  • 3
  • 20
  • 38
  • Try `'active' => ['/^\/posts(?:\/\d+)?$/']` – Wiktor Stribiżew May 11 '19 at 17:50
  • @WiktorStribiżew Thanks for your suggestion, however the result remains the same: the menu doesn't light up. I'm starting to think that this might be an issue with the package on GitHub. – rpm192 May 11 '19 at 18:01
  • Ok, probably, I just wanted to point out that regexps in PHP are defined with regex delimiters, and in most cases adding them is enough. Also, `'/^\/posts(?:\/\d+)?$/'` regex matches a string that starts with `/posts` and ends either immediately here or has `/` and 1+ digits after (optional). Maybe once you figure out how to make regex work within this code it will be helpful. – Wiktor Stribiżew May 11 '19 at 18:03

4 Answers4

3

In the ActiveChecker.php class of the project you can find this piece of code

protected function checkPattern($pattern)
{
    $fullUrlPattern = $this->url->to($pattern);

    $fullUrl = $this->request->fullUrl();

    return Str::is($fullUrlPattern, $fullUrl);
}

Based on laravel documentation, Str::is does not run regexp matching, but justs supports asterisks for wildcards.

In your case you could post a PR that will use regexo if the given pattern is a regular expression, otherwise, run Str::is

Leonardo Rossi
  • 2,922
  • 2
  • 20
  • 28
  • I was also thinking about something like this, but checking if a string is a regex with another regex is a solution that will not work for all regexes. Another solution would be something like the accepted answer of [this question](https://stackoverflow.com/questions/10778318/test-if-a-string-is-regex). But it seems really hacky to me. – rpm192 May 15 '19 at 14:33
  • Hey, I've opened a [pull request](https://github.com/jeroennoten/Laravel-AdminLTE/pull/301) for a similar solution to what you suggested, I'll award you the bounty. – rpm192 May 20 '19 at 14:40
  • Thanks! I had a look at the PR and it's good stuff. Just fix the syntax (I guess their CI doesn't allow adding empty lines in commit), and push to get it merged – Leonardo Rossi May 20 '19 at 16:18
0

You can try using the below pattern in your code:

/^\/posts(\/[0-9]+)?$/

This will work for the below test scenarios:

/posts
/posts/3829
/posts/921
/posts/1

You can check the requirement with the provided solution on REGEX_Solution

Hope it works!

Shweta
  • 661
  • 6
  • 11
0

This is where route naming is really helpful. So, in my code this route would named something like admin:post.index. Then to check if it was active I could use the request helper and a method called routeIs().

Using the name I'd use, here's an example:

request()->routeIs('admin:post.index')

Now, if I wanted this link to be active for the create, edit, delete etc routes I'd do the following:

request()->routeIs('admin:post.*')

This would work since I apply route names following a dot notation hierarchy.

You can optionally provide multiple patterns to that method if there were specific routes you wanted to match.

ollieread
  • 6,018
  • 1
  • 20
  • 36
0

I have created a solution for my problem, it's by no means the prettiest solution, but it'll work, for now.

I have edited the ActiveChecker.php file and edited the checkPattern() function, so it evaluates regex if the pattern in the config file starts with regex:.

protected function checkPattern($pattern)
{
    $fullUrlPattern = $this->url->to($pattern);

    $fullUrl = $this->request->fullUrl();

    if(mb_substr($pattern, 0, 6) === "regex:") {

      $regex = mb_substr($pattern, 6);

      if(preg_match($regex, request()->path()) == 1) {
        return true;
      }

      return false;
    }
    return Str::is($fullUrlPattern, $fullUrl);
}

In my config file, I can now just do this, to use a regex pattern, simply by using the regex: prefix.

'active'  => ['/suppliers', 'regex:@^posts/[0-9]+$@'],

The path of the request which is posts/1 for example, will get compared with the regex, not the full URL.

rpm192
  • 2,630
  • 3
  • 20
  • 38