opencart get the product seo url from within admin
Asked Answered
C

3

10

I am extending the newsletter area so that I can send out an email with a list of products but I can't find out how to get the seo url for each product?

When I do this I actually end up with the admin URL.

$this->url->link('product/product', 'product_id=' . $row['product_id'])

This same code in the store front works fine and returns the seo url if it exists.

The only way I can get it to work is if I manually build the URL, obviously no seo url.

HTTP_CATALOG .'index.php?route=product/product&product_id='.$row['product_id']

Looking into this further I see that the admin area is missing the following code but I can't figure out how this actually works and ties in with $this->url->link so that I can modify it to work for me.

$controller->addPreAction(new Action('common/seo_url'));    

UPDATE - in the end the easiest solution was to add my own method like this:

public function getUrl($route, $key, $value){
    $url = "index.php?route={$route}&{$key}={$value}";

    if($this->config->get('config_seo_url')){
        $query = $this->db->query("SELECT * FROM " . DB_PREFIX . "url_alias WHERE `query` = '" . $this->db->escape($key . '=' . (int)$value) . "'");        
        if($query->row['keyword']){
            $url = $query->row['keyword'];
        } 
    } 

    return $url;
}
Comma answered 27/11, 2013 at 15:0 Comment(0)
N
14

Front-end links

The best way to make a front-end link from the Admin area without modifying core files is to create your own URL object:

$url = new Url(HTTP_CATALOG, $this->config->get('config_secure') ? HTTP_CATALOG : HTTPS_CATALOG);

To create URLs you then use $url instead of $this->url, so your example would be:

$url->link('product/product', 'product_id=' . $row['product_id']);

SEO URLs

Getting SEO URLs is a bit harder and unfortunately requires copying some code or a bit of bodging.

Copied Code

Basically, copy the entire rewrite($link) function from catalog/controller/common/seo_url.php and add it to the controller class that you're creating. Then add the following line after the new $url line mentioned above:

$url->addRewrite($this);

The current controller is then used as a rewriter and all URLs get rewritten. You might be able to use a separate class, but then there are dependencies to get the database access. This seemed the most direct way of doing it, even if it is ugly.

Your code should then be:

<?php
class ControllerMyController extends Controller {
  public function index() {
    ...
    $url = new Url(HTTP_CATALOG, $this->config->get('config_secure') ? HTTP_CATALOG : HTTPS_CATALOG);
    if ($this->config->get('config_seo_url')) {
      $url->addRewrite($this);
    }
    $url->link('product/product', 'product_id=' . $row['product_id']);
    ...
  }

  public function rewrite($link) {
    ... [stuff from seo_url.php] ...
  }
}

and you'll get SEO'd URLs from the admin area.

Bodging

If you're happy with an arbitrary require statement, then you can alternatively do the following and use the existing SEO code (which means that it'll stay up-to-date if it changes, but will fail if the file moves).

To create SEO URLs this way your code needs to be:

            $url = new Url(HTTP_CATALOG, $this->config->get('config_secure') ? HTTP_CATALOG : HTTPS_CATALOG);
            if ($this->config->get('config_seo_url')) {
                    // Require the SEO file directly - path is relative to /admin/index.php
                    require_once('../catalog/controller/common/seo_url.php');
                    $rewriter = new ControllerCommonSeoUrl($this->registry);
                    $url->addRewrite($rewriter);
            }
            $url->link('product/product', 'product_id=' . $row['product_id']);
Nissen answered 25/1, 2014 at 21:11 Comment(4)
Hopefully the SEO parts work for you as well. It isn't pretty, but it works for me.Nissen
You should use require_once in "Bodging" otherwise "Cannot redeclare class" error is thrown if ControllerCommonSeoUrl class was declared (required) before.Grimm
Made the change. As I was requiring a class from outside the normal hierarchy (hence "bodge") then I'd assumed it wasn't going to be included already, but best practice is to require_once anyway.Nissen
Just like to add that as of today, seo_url is located at startup folder, so it should be require_once('../catalog/controller/startup/seo_url.php'); $rewriter = new ControllerStartUpSeoUrl($this->registry);. Lifesaver regardless.Urethrectomy
H
1

Administration part do not need the preAction for SEO, as there are no SEO links in administration.

The problem You are getting is because on frontend the constant HTTP[S]_SERVER points to http[s]://mydomain.com/ while in administration the same constant points to http[s]://mydomain.com/admin/.

What are You looking for is maybe an edit of url class (system/library/url.php) and adding a new method frontend_link by copying link method and replacing HTTP[S]_SERVER constant in the method body by HTTP[S]_CATALOG constant that is present only in administration...

Haddington answered 28/11, 2013 at 22:40 Comment(3)
You can do this using vQmod so that You do not really overwrite the core library file...Haddington
I'm trying to do the same thing now - get SEO URLs from an action triggered in the ACP. Your change seems to get a front-end URL, but /not/ a SEO'd URL.Nissen
My change? I did not change here, I only suggested what should be done. I do not know what changes did You provide. Maybe it would be better to turn this into a new question while providing the code You are using and the changes You have made.Haddington
P
0

Expanding a little on @IBBoard's very informative answer: in Opencart 3.0.2 and above, seo_url.php is no longer in the catalog/common folder. It was moved to catalog/startup.

Also, it is highly recommended to run the filename in the require_once statement through opencart's modification function, like:

require_once modification(DIR_CATALOG . 'controller/startup/seo_url.php');
Phenacetin answered 1/5, 2021 at 12:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.