2

I'm completely new to Zend and am having a hard time grasping how to use Ajax to dynamically populate a dropdown menu. I created a working version that didn't use the Zend framework, but now putting my code into Zend is proving much more difficult than I had originally thought. When I try to run my application, Chrome's Developer Tools outputs to console:

GET http://example.com/crm/getcities.php?name=CDS%20Midwinter%20Meeting 404 (Not Found)tradeshowOptions @ tradeshows:423onchange @ tradeshows:484 

In my application controller folder, I have a controller called CrmController.php which looks like this:

<?php
class CrmController extends Zend_Controller_Action {

public function init() {        
    if(!Zend_Auth::getInstance()->getIdentity() || !in_array('crm', unserialize(Zend_Auth::getInstance()->getIdentity()->permission))){
        $this->_helper->redirector('index', 'fm');
    } 
    $this->view->headLink()->appendStylesheet('/public/css/crm.css');
    $this->_auth = Zend_Auth::getInstance()->getIdentity();

    $this->_users = new Application_Model_User;       
    $this->_crms = new Application_Model_Crm;  
    $this->_products = new Application_Model_Product;

    $this->_helper->ajaxContext->addActionContext('crm', 'html')
                                   ->initContext();
}

public function tradeshowsAction()
{    
}

I have a view entitled tradeshows.phtml which looks like:

<?php require_once('config.php'); ?>
<div class="row">
    <div class="col-lg-12">                   
        <h2 class="page-header">Sales CRM</h2>
        <ol class="breadcrumb">               
            <li><a href="/crm/prospect">Leads</a></li> 
            <li><a href="/crm/prospect">Prospects</a></li>             
            <li><a href="/crm/accounts">Accounts</a></li> 
            <li><a href="/crm/activity">Activities</a></li>
            <li class="active">Tradeshows</li>
        </ol>
    </div>    
</div>

<h3>Tradeshows</h3>



<script>
var name = "";
var city = "";
var year = "";

// Gets the list of cities to populate the second drop down.
function tradeshowOptions(tsname) {
        name = tsname;
    if (tsname == "") {
        document.getElementById("txtHint").innerHTML = "";
        return;
    } else { 
        if (window.XMLHttpRequest) {
            // code for IE7+, Firefox, Chrome, Opera, Safari
            xmlhttp = new XMLHttpRequest();
        } else {
            // code for IE6, IE5
            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        }
        xmlhttp.onreadystatechange = function() {
            if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                document.getElementById("txtHint").innerHTML = xmlhttp.responseText;
            }
        };

        xmlhttp.open("GET","getcities.php?name="+name,true);
        xmlhttp.send();

                name = tsname;
                console.log(name);
    }
}

// Get the list of cities to populate the third drop down.
function yearOptions(tscity) {
        city = tscity;
    if (tscity == "") {
        document.getElementById("txtHint2").innerHTML = "";
        return;
    } else { 
        if (window.XMLHttpRequest) {
            // code for IE7+, Firefox, Chrome, Opera, Safari
            xmlhttp = new XMLHttpRequest();
        } else {
            // code for IE6, IE5
            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        }
        xmlhttp.onreadystatechange = function() {
            if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                document.getElementById("txtHint2").innerHTML = xmlhttp.responseText;
            }
        };
        xmlhttp.open("GET","get_year.php?name="+name+"&city="+city,true);
        xmlhttp.send();
                city = tscity;
                console.log(name + " " + city);
    }
}

// Get the data list.
function dataSet(tsyear) {
        year = tsyear;
    if (tsyear == "") {
        document.getElementById("txtHint3").innerHTML = "";
        return;
    } else { 
        if (window.XMLHttpRequest) {
            // code for IE7+, Firefox, Chrome, Opera, Safari
            xmlhttp = new XMLHttpRequest();
        } else {
            // code for IE6, IE5
            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        }
        xmlhttp.onreadystatechange = function() {
            if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                document.getElementById("txtHint3").innerHTML = xmlhttp.responseText;
            }
        };
        xmlhttp.open("GET","get_data.php?name="+name+"&city="+city+"&year="+year,true);
        xmlhttp.send();
                console.log(name + " " + city + " " + year);
    }
}
</script>

<form>  
    Select Tradeshow:
    <select name="shows" onchange="tradeshowOptions(this.value)">
          <option value="">Select a Tradeshow:</option>
            <?php
              $sql = 'SELECT * FROM tradeshows GROUP BY name ORDER BY name asc;';
              $i = 0;
                foreach ($conn->query($sql) as $row) {
                    echo "<option value='$row[name]'>$row[name]</option>";                  
                    $i++;
              }
            ?>
    </select>
</form>

<br>
<div id="txtHint">&nbsp;</div>
<div id="txtHint2">&nbsp;</div>
<div id="txtHint3">&nbsp;</div>

<link href='/public/css/crm.css' rel='stylesheet' />

Last but not least, I have my getcities.php file, which I do not know where to place. I've also tried naming it getcities.ajax.phtml and putting it in the views, but nothing seems to work.

<!DOCTYPE html>
<html>
<head></head>
<body>
<form>  
    Select City:
    <select name="cities" onchange="yearOptions(this.value)">
            <option>Please select a city...</option>
            <?php
                // Database Connection
                require('config.php');

                // Global Variables from _GET
                $name = strval($_GET['name']);

                // MySQL Query
              $sql = "SELECT * FROM tradeshows WHERE name LIKE '$name' GROUP BY city ORDER BY city asc;";

                // Output Each MySQL Result in Dropdown Menu
              $i = 0;
                foreach ($conn->query($sql) as $row) {
                    echo "<option value='$row[city]'>$row[city]</option>";
                    $i++;
              }
            ?>
    </select>
</form>
</body>
</html>

Please feel free to rip apart my code. I would really like to learn. Also, I realize my code is not that DRY, and I would appreciate it if someone could offer some recommendations.

Thank you!

1 Answers1

0

You might consider reviewing a guide to the MVC pattern, which Zend Framework is built around: https://softwareengineering.stackexchange.com/questions/127624/what-is-mvc-really.

I suggest understanding MVC because otherwise you are going to be fighting against the framework to jam code into places it doesn't want to be. For example, getcities.php is a combination of things that should be separated out to a model class, a view script and a controller action. You don't know where to put this file because it really doesn't belong in your application as-is.

Here is the approach I would take... First, let's create an example controller that will be used to respond to AJAX requests for the list of cities:

<?php
class NewController extends Zend_Controller_Action
{

    public function init()
    {
        $contextSwitch = $this->_helper->getHelper('contextSwitch');

        // The helper will detect a request for JSON and setup the getcities
        // action to return JSON automatically.  No view script required.
        $contextSwitch->addActionContext('getcities', 'json')->initContext();
    }

    public function getcitiesAction()
    {
        // Instantiate cities model.
        $cities_model = new Application_Model_Cities();

        // Get list of cities by simply getting all records.
        $cities_list = $cities_model->getCities();

        // JSON helper will emit all view variables in JSON format.
        $this->view->cities_list = $cities_list;

    }
}

Next, create a model to represent and return your list of cities:

/**
 * Model class to represent cities and interact with database.
 *
 */
class Application_Model_Cities extends Zend_Db_Table_Abstract
{
    // Tell the class what table to use.
    protected $_name = 'tradeshows';

    public function getCities($name = false)
    {
        if($name === false){
          // If no name supplied, match all.
          $name = '%';
        }
        $sql = 'SELECT * FROM tradeshows WHERE name LIKE ? GROUP BY city ORDER BY city asc';
        return $this->getAdapter()->fetchAll($sql,$name);
    }
}

Put the model class in your application's "models" directory. It looks like you're currently connecting to your DB manually in config.php. You should consider bootstrapping your database connection with Zend DB. My example model relies on a default database connection: Registering Zend Database Adapter in Registry

You can call the above code via URL like this: http://example.com/crm/getcities/format/json and you should see a list of cities displayed in JSON format.

I think that should be enough to get you pointed in the right direction. Don't use this code in production, I've taken some shortcuts to make things easier for the purposes of this example.

Community
  • 1
  • 1
ski4404
  • 311
  • 1
  • 6