简体   繁体   中英

Can I use a php function to perform the equivalent of a mySQL left join?

The problem I am having is that using the current function below is taking much too long to load. The two tables that are being joined consist of thousands of rows apiece. The specific function that holds the table join is the &getFields() function in the model section below.

I was thinking that I could possibly have a function that initially checked whether the request was to edit or add new and then deal with separating the table join on only edit queries (No clue as to how to accomplish this).


- using an html form with post method- 使用 html 表单和 post 方法

if(count($this->fields)){
    for($i=0;$ifields);$i++){
        $field =& $this->fields[$i];
        $se = $field->section;
        $ti = $field->title;
        $ft = $field->type;
        $na = $field->name;
        $fva = $field->field_value;
        $nu = $field->unit;
        switch($se){
            case 'header' :
                        echo 'input type="blah...



function __construct() {
    parent::__construct();
    $this->registerTask('add','edit');
    JRequest::setVar('view','cpanel');
}

function edit() {
    JRequest::setVar('layout','form');
    parent::display();
}

function save() {
    $model = $this->getModel('cpanel');
    $msg = $model->store();
    $link = ;
    $this->setRedirect($link, $msg);
}



function __construct() {
    parent::__construct();
    global $mainframe;

    $array = JRequest::getVar('cid',  0, '', 'array');
    $this->setId((int)$array[0]);
}

function setId($id) {
    // Set id and wipe data
    $this->_id      = $id;
    $this->_data    = null;
}

function &getItem() {
    if(empty($this->_data)) {
        $query = ' SELECT * FROM #__directory_entry WHERE id = '.$this->_id;
        $this->_db->setQuery( $query );
        $this->_data = $this->_db->loadObject();
    }
    if(!$this->_data)   {
        $session =& JFactory::getSession();
        $post = $session->get('post');
        $this->_data->id = 0;
        $this->_data->title = isset($post['title'])?$post['title']:null;
    }
    return $this->_data;
}


    $this->_db->setQuery( $query );
    $fields = $this->_db->loadObjectList();
    $session =& JFactory::getSession();
    if($session->has('post') and !$this->_id) {
        $post = $session->get('post');
        for($i=0;$ifield_value = isset($post['field_'.$fields[$i]->name])?$post['field_'.$fields[$i]->name]:null;
    }
    return $fields;
}

function store() {
    // Check for request forgeries
    JRequest::checkToken() or jexit( JText::_('Invalid Token') );
    $post = JRequest::get( 'post' );
    $session =& JFactory::getSession();
    $session->set('post', $post);

    if($post["title"] == "")
        return JText::_('Please enter the title');

    $query = 'select * from #__directory_field where published = 1';
    $this->_db->setQuery( $query );
    $fields = $this->_db->loadObjectList();
    for($i=0;$irequired and $post['field_'.$fields[$i]->name] == "")
            return JText::_($fields[$i]->title . ' is required field and can not be left blank.');
    }

    if(!$post["id"]) {
        $date =& JFactory::getDate();
        $post['create_date'] = $date->toMySQL();
        $post['ordering'] = 1;
        $query = 'select ordering from #__directory_entry order by ordering desc limit 1';
        $this->_db->setQuery( $query );
        $post['ordering'] += $this->_db->loadResult();
        $post['published'] = 1;
    }
    $me =& JFactory::getUser();
    JTable::addIncludePath(JPATH_ADMINISTRATOR.DS.'components'.DS.'com_joomd'.DS.'tables');
    $row =& JTable::getInstance('entry', 'Table');
    if (!$row->bind( $post ))
        return JText::_('Sorry some Error Occurred.');

    if (!$row->store())
        return $this->_db->getErrorMsg();

    if(!$post['id']) {
        $post['id'] = $this->_db->insertid();
        JRequest::setVar('id', $post['id']);
        $msg = JText::_('Entry successfully added!');
        $query = 'insert into #__directory_enu (entry_id, user_id) values ('.$post['id'].', '.$me->id.')';
        $this->_db->setQuery( $query );
        $this->_db->query();
    }
    else
        $msg = JText::_('Entry successfully Updated!');

    $max_size = 10000000;
    jimport('joomla.filesystem.file');
    $time = time();
    for($i=0;$itype == "image")
            $allowed = array('.jpg', '.jpeg', '.gif', '.png');
        elseif($field->type == "file")
            $allowed = array('.doc', '.docx', '.pdf', '.txt', '.exl', '.xls', '.xlsx', '.jpg', '.jpeg', '.gif', '.png', '.zip');

        $flag = true;
        $query = 'select count(*) from #__directory_enf where entry_id = ' . $post["id"] .' and field_id = ' . $field->id;
        $this->_db->setQuery( $query );
        $count = $this->_db->loadResult();
        if($field->type == "image" or $field->type == "file")   {
            $image = JRequest::getVar("field_".$field->name, null, 'FILES', 'array');
            $image_name    = str_replace(' ', '', JFile::makeSafe($image['name']));     
            $image_tmp     = $image["tmp_name"];
            if($image_name  "")   {
                $ext = strrchr($image_name, '.');
                if(!in_array($ext, $allowed))
                    return sprintf(JText::_('File type for %s is not allowed.'), $field->title);
                if(filesize($image_tmp) > $max_size)
                    return sprintf(JText::_('File size for %s exceeds the maximum file size.'), $field->title);
                if(move_uploaded_file($image_tmp, JPATH_SITE.'/files/'.$time.$image_name))
                    $post["field_".$field->name] = $time.$image_name;
                else
                    return sprintf(JText::_('Sorry File for %s could not be uploaded.'), $field->title);
            }
            else
                $flag = false;
        }
        if($flag)   {
            if($count) {
                $query = 'select id from #__directory_enf where entry_id = '.$post["id"].' and field_id = ' . $field->id;
                $this->_db->setQuery( $query );
                $field_id = $this->_db->loadResult();
                $update = new stdClass();
                $update->id = $field_id;
                $update->field_value = $post["field_".$field->name];
                $this->_db->updateObject('#__directory_enf', $update, 'id');
            }
            else {
                $insert = new stdClass();
                $insert->id = null;
                $insert->field_id = $field->id;
                $insert->entry_id = $post["id"];
                $insert->field_value = $post["field_".$field->name];
                $this->_db->insertObject('#__directory_enf', $insert, 'id');
            }
        }
    }
    $session->clear('post');
    return $msg;
}

Left Join is the fastest method, but you have written your query in such a way that it will be very slow.

SELECT f.*, ef.field_value
   FROM #__directory_field AS f
   LEFT JOIN #__directory_enf AS ef ON (f.id = ef.field_id AND ef.entry_id = $this->_id)
   WHERE f.published = 1
   ORDER BY f.ordering ASC

Your ON clause is the main problem. Written this way you are ant trailing through every record, and not putting good use to indexes. You will want to reverse your table order, and put the id match in the where clause. Something like this.

SELECT ef.field_value, f.*
   FROM #__directory_enf AS ef
   LEFT JOIN #__directory_field AS f ON f.id = ef.field_id
   WHERE f.published = 1 AND ef.entry_id = $this->_id
   ORDER BY f.ordering ASC

You will then want to make sure your database has indexes on both the f.id and ef.entry_id fields. This should make your query many many times faster.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM