Jump to content

Archived

This topic is now archived and is closed to further replies.

acidvertigo

Implementing PSR-7 HTTP messages into oscommerce

Recommended Posts

Hello,

 

I'm recently working to revamp my oscommerce site and just want to share a tip that can help in developing.

 

PSR-7 HTTP messages is just a way to describe common php interfaces to reperesent http messages: http://www.php-fig.org/psr/psr-7/

 

A good implementation i found is Zend Diactoros: https://github.com/zendframework/zend-diactoros

 

Include this implementation in oscommerce is pretty easy but requires PHP version > 5.4 and composer installedhttps://getcomposer.org

 

in includes/function/compatibility

 

find:

if (PHP_VERSION >= 4.1) {
    $HTTP_GET_VARS =& $_GET;
    $HTTP_POST_VARS =& $_POST;
    $HTTP_COOKIE_VARS =& $_COOKIE;
    $HTTP_SESSION_VARS =& $_SESSION;
    $HTTP_POST_FILES =& $_FILES;
    $HTTP_SERVER_VARS =& $_SERVER;
  } else {
    if (!is_array($HTTP_GET_VARS)) $HTTP_GET_VARS = array();
    if (!is_array($HTTP_POST_VARS)) $HTTP_POST_VARS = array();
    if (!is_array($HTTP_COOKIE_VARS)) $HTTP_COOKIE_VARS = array();
  }

replace with:

 

// include composer autoloader
require 'vendor/autoload.php';

$request = Zend\Diactoros\ServerRequestFactory::fromGlobals();

$HTTP_GET_VARS = $request->getQueryParams();
$HTTP_POST_VARS = $request->getParsedBody();
$HTTP_COOKIE_VARS = $request->getCookieParams();
$HTTP_SESSION_VARS =& $_SESSION;
$HTTP_POST_FILES = $request->getUploadedFiles();
$HTTP_SERVER_VARS = $request->getServerParams();

and in admin/includes/function/compatibility

 

find:

if (PHP_VERSION >= 4.1) {
$HTTP_GET_VARS =& $_GET;
$HTTP_POST_VARS =& $_POST;
$HTTP_COOKIE_VARS =& $_COOKIE;
$HTTP_SESSION_VARS =& $_SESSION;
$HTTP_POST_FILES =& $_FILES;
$HTTP_SERVER_VARS =& $_SERVER;
} else {
if (!is_array($HTTP_GET_VARS)) $HTTP_GET_VARS = array();
if (!is_array($HTTP_POST_VARS)) $HTTP_POST_VARS = array();
if (!is_array($HTTP_COOKIE_VARS)) $HTTP_COOKIE_VARS = array();
}

replace with:

// include composer autoloader
require '../vendor/autoload.php';

$request = Zend\Diactoros\ServerRequestFactory::fromGlobals();

$HTTP_GET_VARS = $request->getQueryParams();
$HTTP_POST_VARS = $request->getParsedBody();
$HTTP_COOKIE_VARS = $request->getCookieParams();
$HTTP_SESSION_VARS =& $_SESSION;
$HTTP_POST_FILES = $request->getUploadedFiles();
$HTTP_SERVER_VARS = $request->getServerParams();

from console you have to run the following composer command:

composer require zendframework/zend-diactoros

this will install zend diactoros in the vendor folder.

 

Thats it, every time you will call for example $HTTP_GET_VARS you don't will get directly the $_GET superglobal anymore, but you will get the $request->getQueryParams() resulting array. 

 

This is not much special, but the intersting point is that you can use directly every PSR-7 ServerRequest interface method in all the oscommerce site for example:

$request->getUri(); // To get the current uri 
$request->getUri()->getScheme(); // To get current uri scheme
$request->getUri()->getPath(); // To get uri path
$request->getMethod(); // to get request method
$request->withMethod('PUT'); // to change current request method from GET to PUT and etc...

you can still use $HTTP_XXX_VARS to get or manipulate superglobals this tip is only to use a more nice object interface. This can also be estended to Response interface to implement for example e json api of the website:

 

for example in an ipotetic new_products_json.php file:


<?php
  require('includes/application_top.php');
  
  $listing_sql =  "select " . $select_column_list . " p.products_id, SUBSTRING_INDEX(pd.products_description, ' ', 20) as products_description, p.manufacturers_id, p.products_price, p.products_tax_class_id, IF(s.status, s.specials_new_products_price, NULL) as specials_new_products_price, IF(s.status, s.specials_new_products_price, p.products_price) as final_price from " . TABLE_PRODUCTS_DESCRIPTION . " pd, " . TABLE_PRODUCTS . " p left join " . TABLE_MANUFACTURERS . " m on p.manufacturers_id = m.manufacturers_id left join " . TABLE_SPECIALS . " s on p.products_id = s.products_id where p.products_status = '1' and p.products_id = pd.products_id and pd.language_id = '" . (int)$languages_id . "'";

$data = tep_db_fetch_array($listing_query);

$response = new Zend\Diactoros\Response\JsonResponse($data, 200, [ 'Content-Type' => ['application/hal+json']]);

return new Zend\Diactoros\Response\SapiEmitter($reponse); // Emit the response to the client
Hope you find this post usefull as I've found it. Enjoy.

Share this post


Link to post
Share on other sites

Another approach with Zend Diactoros can be the use of an external router library to routing seo urls.

 

for example adding nikic/fastroute:

composer require nikic/fast-route

and zend diactoros:

composer require zendframework/zend-diactoros

creating a route.php file:

 

<?php
// include composer autoloader
   require 'vendor/autoload.php';

$request = Zend\Diactoros\ServerRequestFactory::fromGlobals();
$dispatcher = FastRoute\simpleDispatcher(function(FastRoute\RouteCollector $r) {
    $r->addRoute('GET', '/', 'index.php');
    $r->addRoute('GET', '/{slug:[a-z0-9-/]+}-c-{cPath:[0-9_]+}', 'index.php');
    $r->addRoute('GET', '/{slug:[a-z0-9-/]+}-m-{manufacturers_id:\d+}', 'index.php');
    // {id} must be a number (\d+)
    $r->addRoute('GET', '/{slug:[a-z0-9-/]+}-p-{products_id:\d+}', 'product_info.php');
    });
  
   $routeInfo = $dispatcher->dispatch($request->getMethod(), $request->getUri()->getPath());
 
   switch ($routeInfo[0]) {
    case FastRoute\Dispatcher::NOT_FOUND:
        $reponse = new Zend\Diactoros\Response\HtmlResponse('<h1>Not Found</h1>', 404);
        $emitter =  new Zend\Diactoros\Response\SapiEmitter;
        return $emitter->emit($reponse);
        break;
    case FastRoute\Dispatcher::METHOD_NOT_ALLOWED:
        $allowedMethods = $routeInfo[1];
        $reponse = new Zend\Diactoros\Response\HtmlResponse('<h1>Method Not Allowed</h1>', 405);
        $emitter =  new Zend\Diactoros\Response\SapiEmitter;
        return $emitter->emit($reponse);
        break;
    case FastRoute\Dispatcher::FOUND:
        $_GET = $routeInfo[2];
        return include $routeInfo[1];
        break;
}

and modifing .htaccess file to move all requests to route.php file:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ route.php [QSA,L]

I'm still working on reverse routing, to generate urls in this way via tep_href_link function

 

 

 
 function tep_href_link($page = '', $parameters = '', $connection = 'NONSSL', $add_session_id = true, $search_engine_safe = true) {
    global $request_type, $session_started, $SID;


    $page = tep_output_string($page);
    parse_str($parameters, $var);


    if (!tep_not_null($page)) {
      die('</td></tr></table></td></tr></table><br /><br /><font color="#ff0000"><strong>Error!</strong></font><br /><br /><strong>Unable to determine the page link!<br /><br />');
    }


    if ($connection == 'NONSSL') {
      $link = HTTP_SERVER . DIR_WS_HTTP_CATALOG;
    } elseif ($connection == 'SSL') {
      if (ENABLE_SSL == true) {
        $link = HTTPS_SERVER . DIR_WS_HTTPS_CATALOG;
      } else {
        $link = HTTP_SERVER . DIR_WS_HTTP_CATALOG;
      }
    } else {
      die('</td></tr></table></td></tr></table><br /><br /><font color="#ff0000"><strong>Error!</strong></font><br /><br /><strong>Unable to determine connection method on a link!<br /><br />Known methods: NONSSL SSL</strong><br /><br />');
    }


    if (tep_not_null($parameters)) {
      $link .= $page . '?' . tep_output_string($parameters);
      $separator = '&';
    } else {
      $link .= $page;
      $separator = '?';
    }


    while ( (substr($link, -1) == '&') || (substr($link, -1) == '?') ) $link = substr($link, 0, -1);


// Add the session ID when moving from different HTTP and HTTPS servers, or when SID is defined
    if ( ($add_session_id == true) && ($session_started == true) && (SESSION_FORCE_COOKIE_USE == 'False') ) {
      if (tep_not_null($SID)) {
        $_sid = $SID;
      } elseif ( ( ($request_type == 'NONSSL') && ($connection == 'SSL') && (ENABLE_SSL == true) ) || ( ($request_type == 'SSL') && ($connection == 'NONSSL') ) ) {
        if (HTTP_COOKIE_DOMAIN != HTTPS_COOKIE_DOMAIN) {
          $_sid = tep_session_name() . '=' . tep_session_id();
        }
      }
    }


    if (isset($_sid)) {
      $link .= $separator . tep_output_string($_sid);
    }


    while (strpos($link, '&&') !== false) $link = str_replace('&&', '&', $link);


    if ( (SEARCH_ENGINE_FRIENDLY_URLS == 'false') && ($search_engine_safe == true) ) {
      $link = str_replace('?', '/', $link);
      $link = str_replace('&', '/', $link);
      $link = str_replace('=', '/', $link);
    } else {
      $link = str_replace('&', '&', $link);
    }
 
    switch($page){
      case 'index.php':
          $link = 'this-is-index-page-c-' . $var['cPath'];
          break;
      case 'product_info.php':
          $link = 'this-is-product-page-p-'. $var['products_id'];
          break;
    }


    return $link;
  }

 

 

Share this post


Link to post
Share on other sites

×