Выполнение SQL-запроса непосредственно из контроллера - PullRequest
0 голосов
/ 01 марта 2012

Я работаю над модулем администрирования magento и в настоящее время выполняю небрежный запрос к базе данных, напрямую загружая файл php и подключаясь к файлу php вне модуля:

<?php 
header("Content-type: text/xml");
$host           = "localhost";
$user           = "root";
$pw             = "foo";
$database       = "db";
$link           = mysql_connect($host,$user,$pw) or die ("Could not connect.");
$db_selected = mysql_select_db($database, $link); if (!$db_selected) {
    die ('Can\'t use ' . $database . ' : ' . mysql_error()); }


// connect to database
$link   = mysql_connect($host . ":" . $port,$user,$pw) or die ("Could not connect.");

// Select DB
$db_selected = mysql_select_db($database, $link); if (!$db_selected) {
    die ('Can\'t use ' . $database . ' : ' . mysql_error()); }

// Database query
$query = ("SELECT cpsl.parent_id AS 'foo'
  , cpe.type_id AS 'bar'
  , LEFT(cpe.sku, 10) AS 'color'
  ....
GROUP BY 1,2,3,4,5,6,7,8,9
ORDER BY 1,2,3,4,5,6,7,8,9
;");

// Execute query
$result = mysql_query($query, $link) or die("Could not complete database query");

// Populate array
while(($resultArray[] = mysql_fetch_assoc($result)) || array_pop($resultArray));

  $doc = new DOMDocument();
  $doc->formatOutput = true;

  $r = $doc->createElement( "DATA" );
  $doc->appendChild( $r );

  foreach( $resultArray as $product )
  {
  $b = $doc->createElement( "ITEM" );

  // MagentoID
  $magento_id = $doc->createElement( "MAGENTO_ID" );
  $magento_id->appendChild(
  $doc->createTextNode( $product['MagentoID'] )
  );
  $b->appendChild( $magento_id );
....

 }

// Save XML
  echo $doc->saveXML();

// Close connection
mysql_close($link);

?>

Может кто-нибудь объяснить, как лучше записать это в модуль? Я знаю, что могу сделать соединение намного проще (более безопасным?), Используя методы magentos. Могу ли я поместить весь этот запрос непосредственно в контроллер для модуля? Что-то вроде этого? :

public function queryAction()
    {
$readConnection = $resource->getConnection('core_read');
$query = ("SELECT cpsl.parent_id AS 'foo'
...
}

1 Ответ

3 голосов
/ 01 марта 2012

Да, вы можете делать то, что вы предлагаете.

У меня есть что-то вроде следующего:

class Foo {
    protected $db;

    public function _construct() {
        /* Change core_write to core_read if you're just reading */
        $this->db = Mage::getSingleton('core/resource')->getConnection('core_write');
    }

    private function doAQuery() {
        $sql = "SELECT * FROM foobar f;";
        $data = $this->db->fetchAll($sql);
        /* do something with the data here */
    }

    private function doAQueryADifferentWay() {
        $sql = $this->db->select();
        $sql->from(array('f' => 'foobar'));
        $data = $this->db->fetchAll($sql);
        /* do something with the data */
    }
}

отредактировано для добавления

Вы можете сделать вызов непосредственно из контроллера, определив методы в контроллере и вызвав их примерно так: $this->doAQuery(); Я довольно большой поклонник размещения вещей в нужном месте для облегчения обслуживания, поэтому я опишу шаги, необходимые для этого.

Я собираюсь предположить, что вы знаете, как / можете читать документы о том, как создать каркасный модуль, но я могу немного поговорить. Извиняюсь заранее.

Ради аргумента я собираюсь вызвать наш пример модуля Zac_Example. Таким образом, мы представим, что у нас есть модуль в app / code / local / Zac / Example. Любые дальнейшие пути предполагают, что мы начинаем в этом каталоге.

Во-первых, вам нужно определить модель (я думаю, вы могли бы использовать помощника, если хотите) и контроллер, поэтому мы определяем их в etc / config.xml

...
  <frontend>
    <routers>
      <zac_example>
        <use>standard</use>
        <args>
          <module>Zac_Example</module>
          <!-- Mind the capital N, it gets me every time -->
          <frontName>example</frontName>
        </args>
      </zac_example>
    </routers>
  </frontend>
  <global>
    <models>
      <zac_example>
        <class>Zac_Example_Model</class>
      </zac_example>
    </models>
  </global>
...

Теперь мы определим нашу модель в Model / Query.php, который равен Foo сверху, но с использованием соглашения об именовании Magento:

class Zac_Example_Model_Query extends Mage_Core_Model_Abstract {
    protected $db;

    /* you don't have to do this, as you can get the singleton later if you prefer */
    public function __construct() {
        $this->db = Mage::getSingleton('core/resource')->getConnection('core_write');
    }

    public function doAQuery() {
        /* If you chose not to do this with the constructor:
         * $db = Mage::getSingleton('core/resource')->getConnection('core_write');
         */

        $sql = "SELECT * FROM foobar f;";
        /* or $db->fetchAll($sql); */
        $this->db-fetchAll($sql);
        /* do something with the data here */
        return $response
    }

    public function doAQueryADifferentWay($somerequestdata) {
        $sql = $this->db->select();
        $sql->from(array('f' => 'foobar'));
        $sql->where('f.somedata', array('eq' => $somerequestdata));

        $data = $this->db->fetchAll($sql);
        /* do something with the data */
    }
}

Теперь, имея модель, мы можем настроить контроллер. Мы назовем контроллер test , так что следующее идет в controllers / TestController.php. Действия мы будем называть foo и bar .

class Zac_Example_TestController extends Mage_Core_Controller_Front_Action {

    public function fooAction() {
        $model = Mage::getModel('zac_example/query');
        $result = $model->doAQuery();
        $this->getResponse()->setBody(Zend_Json::encode($result));
        $this->getResponse()->sendResponse();
        exit; // We're done, right?
    }

    /* This assumes the request has a post variable called 'whatever' */
    public function barAction() {
        $model = Mage::getModel('zac_example/query');
        $param = $this->getRequest()->getParam('whatever');
        $result = $model->doAQueryADifferentWay($param);
        $this->getResponse()->setBody(Zend_Json::encode($result));
        $this->getResponse()->sendResponse();
        exit; // We're done, right?
    }

Учитывая этот конкретный набор фактов, рассматриваемые URL-адреса будут http://yourserver/example/test/foo и http://yourserver/example/test/bar. Если бы мы назвали файл контроллера IndexController.php, они были бы http://yourserver/example/index/foo и http://yourserver/example/index/bar.

Если у вас есть только одно действие, которое вам нужно сделать доступным, вы можете назвать файл контроллера IndexController.php и метод в контроллере indexAction и использовать URL http://yourserver/example/ .

Я стреляю с бедра, поэтому не удивляйтесь, если где-нибудь есть хотя бы один брейно или опечатка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...