phphtml

How to use preg_replace for replacing href attribute values with a Javascript function name in a PHP string


I have the following HTML code as a string in a PHP variable:

<ul class="pagination">
<li class="active">
<a href="http://localhost:8080/admin/locationlist?filter_name=emirate&filter_value=dubai&page=1">
1</a>
</li>
<li >
<a href="http://localhost:8080/admin/locationlist?filter_name=emirate&filter_value=dubai&page=2">
2</a>
</li>
<li >
<a href="http://localhost:8080/admin/locationlist?filter_name=emirate&filter_value=dubai&page=3">
3</a>
</li>
<li>
<a href="http://localhost:8080/admin/locationlist?filter_name=emirate&filter_value=dubai&page=4" aria-label="Next">
<span aria-hidden="true">Next</span>
</a>
</li>
<li>
<a href="http://localhost:8080/admin/locationlist?filter_name=emirate&filter_value=dubai&page=60" aria-label="Last">
<span aria-hidden="true">Last</span>
</a>
</li>
</ul>

I would like to replace the URL from the HTML tags and instead replace with the following text:

javascript:loadItems(<pagenumber>);

Please note that the query parameters filter_name=emirate&filter_value=dubai can change based on user search. For example: filter_name=location&filter_value=Samha

The final replaced HTML string should be as follows:

<ul class="pagination">
<li class="active">
<a href="javascript:loadLocationList(1);">
1</a>
</li>
<li >
<a href="javascript:loadLocationList(2);">
2</a>
</li>
<li >
<a href="javascript:loadLocationList(3);">
3</a>
</li>
<li>
<a href="javascript:loadLocationList(4);" aria-label="Next">
<span aria-hidden="true">Next</span>
</a>
</li>
<li>
<a href="javascript:loadLocationList(60);" aria-label="Last">
<span aria-hidden="true">Last</span>
</a>
</li>
</ul>

How to do this replacement?

EDIT:

I tried this:

$pager_links = str_replace("http://localhost:8080/admin/locationlist?filter_name=&filter_value=&page=", "javascript:loadLocationList();", $pager_links);

$pattern = '/\);([0-9]+)/i';
$replacement = '$1);';
$pager_links = preg_replace($pattern, $replacement, $pager_links);

When there is some content inside filter_name and filter_value parameters, I am not able to replace it properly.


Solution

  • It is never a Good Idea to use regex to parse HTML.

    I suggest you change it to insert a simple piece of JS in the document

    Your loadItems became loadLocationList, so I kept the latter

    window.addEventListener('load', () => {
      const loadLocationList = page => console.log(page);
      
      document.querySelector('ul.pagination') // Targeting the pagination <ul> specifically
        .addEventListener('click', (e) => {
          // Find the closest <a> element to e.target
          const link = e.target.closest('a');
    
          // If no <a> is found, ignore the event
          if (!link) return;
    
          // Prevent default link behavior
          e.preventDefault();
    
          // Get the href attribute
          const href = link.getAttribute('href');
    
          try {
            // Parse the href using the URL interface
            const url = new URL(href, window.location.origin); // Use origin as base for relative URLs
            const page = url.searchParams.get('page');
    
            // If page parameter exists, call loadItems with the page number
            if (page !== null) {
              loadLocationList(Number(page));
            }
          } catch (e) {
            // Ignore invalid URLs or non-URL hrefs 
            return;
          }
        });
    });
    <ul class="pagination">
      <li class="active">
        <a href="http://localhost:8080/admin/locationlist?filter_name=emirate&filter_value=dubai&page=1">1</a>
      </li>
      <li>
        <a href="http://localhost:8080/admin/locationlist?filter_name=emirate&filter_value=dubai&page=2">2</a>
      </li>
      <li>
        <a href="http://localhost:8080/admin/locationlist?filter_name=emirate&filter_value=dubai&page=3">3</a>
      </li>
      <li>
        <a href="http://localhost:8080/admin/locationlist?filter_name=emirate&filter_value=dubai&page=4" aria-label="Next">
    <span aria-hidden="true">Next</span>
    </a>
      </li>
      <li>
        <a href="http://localhost:8080/admin/locationlist?filter_name=emirate&filter_value=dubai&page=60" aria-label="Last">
    <span aria-hidden="true">Last</span>
    </a>
      </li>
    </ul>

    If you MUST do it in PHP, then give this a try, a combination of dom parsing and url parsing - not tested

    function transformPaginationUrls($html) {
      $doc = new DOMDocument();
      @$doc->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
      
      $links = $doc->getElementsByTagName('a');
      
      foreach ($links as $link) {
        $href = $link->getAttribute('href');
       
        // Parse the URL
        $parsedUrl = parse_url($href);
            
        // Check if the URL has a query string
        if (isset($parsedUrl['query'])) {
          // Parse query string into an array
          parse_str($parsedUrl['query'], $queryParams);
              
          // Check if the page parameter exists
          if (isset($queryParams['page'])) {
            $pageNumber = $queryParams['page'];
            // Replace href with JavaScript call
            $link->setAttribute('href', "javascript:loadLocationList({$pageNumber});");
          }
        }
      }
      return $doc->saveHTML();
    }
    
    
    
        // Calling the method
    $urlFragment  = '<ul>.....</ul>';
    $replacedHref = transformPaginationUrls($urlFragment);