Post by rph » Fri Apr 24, 2015 3:07 am

RFC: Simplify OpenCart URL Query String Generation

One of the features lacking in OpenCart is simple URL query string generation. This has lead to a significant amount of boilerplate code manually generating them:

Code: Select all

$url = '';

if (isset($this->request->get['filter_name'])) {
    $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8'));
}

if (isset($this->request->get['filter_model'])) {
    $url .= '&filter_model=' . urlencode(html_entity_decode($this->request->get['filter_model'], ENT_QUOTES, 'UTF-8'));
}

if (isset($this->request->get['filter_price'])) {
    $url .= '&filter_price=' . $this->request->get['filter_price'];
}

if (isset($this->request->get['filter_quantity'])) {
    $url .= '&filter_quantity=' . $this->request->get['filter_quantity'];
}

if (isset($this->request->get['filter_status'])) {
    $url .= '&filter_status=' . $this->request->get['filter_status'];
}

if (isset($this->request->get['sort'])) {
    $url .= '&sort=' . $this->request->get['sort'];
}

if (isset($this->request->get['order'])) {
    $url .= '&order=' . $this->request->get['order'];
}

if (isset($this->request->get['page'])) {
    $url .= '&page=' . $this->request->get['page'];
}

$this->response->redirect($this->url->link('catalog/product', 'token=' . $this->session->data['token'] . $url, 'SSL'));
 
With a small amount of code hundreds of lines could be removed from controllers.

Proof Of Concept

The issue could be addressed many ways. The following is a simple controller-based method:

Code: Select all

protected function makeQueryString($defaults = []) {
    $queries = array(
        'filter_name'     => null,
        'filter_model'    => null,
        'filter_price'    => null,
        'filter_quantity' => null,
        'filter_status'   => null,
        'sort'            => null,
        'order'           => null,
        'page'            => null
    );

    $queries = array_merge($queries, $defaults);

    $url = 'token=' . $this->session->data['token'];

    foreach ($queries as $query => $value) {
        if (isset($this->request->get[$query])) {
            $url .= '&' . $query . '=' . urlencode(html_entity_decode($this->request->get[$query]));
            continue;
        }

        if (!is_null($value)) {
            $url .= '&' . $query . '=' . urlencode(html_entity_decode($value));
        }
    }

    return $url;
}
The original code could then be reduced to a single line:

Code: Select all

$this->response->redirect($this->url->link('catalog/product', $this->makeQueryString(), 'SSL'));
 
Query parameters could easily be added passing in an array of values:

Code: Select all

$this->response->redirect($this->url->link(
    'catalog/product', 
    $this->makeQueryString(['filter_category' => null, 'sort' => 'DESC']), 
    'SSL'
));
 
Advantages

Along with eliminating redundant code it will also make the core easier to learn and debug. It could also be expanded for use with the event system so developers could add or modify GET parameters. Small mistakes developers make like forgetting to include the URL token could also be prevented.

-Ryan


rph
Expert Member

Posts

Joined
Fri Jan 08, 2010 5:05 am
Location - Lincoln, Nebraska

Post by rph » Fri Apr 24, 2015 3:48 am

This can also be achieved with a class. Here's a quick and dirty gist I threw together. Its use would be like:

Code: Select all

$query_string = new QueryString($this->request, [
        'token'           => $this->session->data['token'],   
        'filter_name'     => null,
        'filter_model'    => null,
        'filter_price'    => null,
        'filter_quantity' => null,
        'filter_status'   => null,
        'sort'            => null,
        'order'           => null,
        'page'            => null
]);

// ...

// Standard
$standard = $this->url->link(
    'catalog/product',
     $query_string->make(),
    'SSL'
);

// Extended
$extended = $this->url->link(
    'catalog/product',
     $query_string->make(['filter_category' => null, 'sort' => 'ASC']),
    'SSL'
);

// Exclude queries with chaining
$excluded = $this->url->link(
    'catalog/product',
     $query_string->exclude(['page', 'filter_status'])->make(),
    'SSL'
);

// Combined
$combined = $this->url->link(
    'catalog/product',
     $query_string->exclude(['filter_quantity'])->make(['limit' => 10]),
    'SSL'
);

// Override a submitted value
$override = $this->url->link(
    'catalog/product',
     $query_string->exclude(['sort'])->make(['sort' => 'DESC']),
    'SSL'
);

-Ryan


rph
Expert Member

Posts

Joined
Fri Jan 08, 2010 5:05 am
Location - Lincoln, Nebraska

Post by rph » Fri Apr 24, 2015 12:36 pm

Added to User Voice.

https://opencart.uservoice.com/forums/5 ... generation

We'll see if anything comes of it. As far as I know none of the ideas there have been implemented or even acknowledged. :-\

-Ryan


rph
Expert Member

Posts

Joined
Fri Jan 08, 2010 5:05 am
Location - Lincoln, Nebraska

Post by Qphoria » Fri Apr 24, 2015 9:31 pm

That type of forward thinking is frowned upon here! ;D

And I like it. The url code in all the controllers has always perturbed me. Repetitive code is evil!

Image


User avatar
Administrator

Posts

Joined
Tue Jul 22, 2008 3:02 am

Post by rph » Sun Apr 26, 2015 3:53 am

Qphoria wrote:That type of forward thinking is frowned upon here! ;D
Is this Schrödinger's Joke? Both a joke and not a joke at the same time?

-Ryan


rph
Expert Member

Posts

Joined
Fri Jan 08, 2010 5:05 am
Location - Lincoln, Nebraska

Post by Qphoria » Wed Apr 29, 2015 4:48 am

rph wrote:
Qphoria wrote:That type of forward thinking is frowned upon here! ;D
Is this Schrödinger's Joke? Both a joke and not a joke at the same time?
Quantum joking is the new fad!

Image


User avatar
Administrator

Posts

Joined
Tue Jul 22, 2008 3:02 am

Post by saliverdim » Mon Mar 07, 2016 12:33 am

how to fix

Remove query strings from static resources
A (92)
CONTENT HIGH
What's this mean?
Resources with a "?" in the URL are not cached by some proxy caching servers. Remove the query string and encode the parameters into the URL for the following resources:

http://www.yoursite.net/catalog/view/ja ... ff?v=4.1.0
http://www.yoursite.net/catalog/view/th ... ons.png?v7

2.0.3.1
help me ?

Active Member

Posts

Joined
Wed Oct 07, 2015 12:15 am
Who is online

Users browsing this forum: No registered users and 2 guests