我们在配置有PHP的Apache服务器上部署了一个静态文件。它支持PHP代码的搜索功能,并在多个页面上显示搜索结果。第一次可以在页面上显示10个结果,搜索效果很好。当我单击“下一步”按钮以查看下一页的结果时,它表示会话属性未定义。当我查看session.save_path时,它确实创建了2个会话文件。一种是第一次搜索时(不是空白),另一种是我单击下一个按钮时(始终为0 KB,始终为空白)。 在配置了SSL / TLS的环境中,这种情况发生在https协议中。对于http协议,它工作正常。 在存在默认Apache PHP SSL配置的第二个环境中,这会发生在http协议中。对于https协议,它工作正常。
我的php代码如下(Apache 2.4,PHP 5.6.3)
<?php
require_once 'SearchContext.php';
require_once 'NewSearchContext.php';
session_start();
$searchString = $_REQUEST["searchString"];
if(isset($_REQUEST["action"]) && $_REQUEST["action"]!="")
{
$action = $_REQUEST["action"];
}
$hitsPerPage = $_REQUEST["hitsPerPage"];
$protocol = 'http://';
if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'||
$_SERVER['SERVER_PORT'] == 443) {
$protocol = 'https://';
}
if (isset($searchString)&&isset($hitsPerPage))
{
$dispatcher = $protocol.$_SERVER['SERVER_NAME'].':'.$_SERVER["SERVER_PORT"].$_SERVER['PHP_SELF'];
$context = new SearchContext($dispatcher, $searchString, $hitsPerPage);
$_SESSION["searchcontext"] =$context;
echo $context->getNextPage();
}
else if ($_SESSION["searchcontext"]&&isset($action))
{
$context = $_SESSION["searchcontext"];
if ($action == "next")
{
echo $context->getNextPage();
}
else if ($action == "prev")
{
echo $context->getPrevPage();
}
}
?>
SearchContext.php:
<?php
require_once 'SearchSettings.php';
require_once SearchSettings::ZEND_PATH;
require_once 'TextParser.php';
class SearchContext {
const XML_AMP = '&';
const XML_APOS = ''';
const XML_CR = ' ';
const XML_GT = '>';
const XML_LT = '<';
const XML_LF = ' ';
const XML_QUOT = '"';
const XML_TAB = '	';
const XML_DECLARATION = '<?xml version="1.0" encoding="UTF-8"?>';
protected static $keyWords = array('Product', 'Descriptor', 'Process', 'Pattern',
'Type', 'Definition', 'Set', 'Asset', 'Considerations',
'Category', 'Material', 'Grouping', 'Tool');
protected $indexPath;
protected $hitsPerPage;
protected $searchString;
protected $xsl;
protected $docBase;
protected $docFolder;
protected $searchResults;
protected $hitsCount;
protected $phpPageName;
protected $currentPage;
protected $dispatherPage;
protected $isCJKAnalyzer;
public function __construct($dispatherPage, $searchString, $hitsPerPage)
{
if (isset($dispatherPage))
{
$this->dispatherPage = $dispatherPage;
}
$this->searchString = $searchString;
$this->hitsPerPage = $hitsPerPage;
$this->_initialize();
$this->_doSearch();
}
private function _initialize()
{
$this->indexPath = realpath('./index/');
$this->xsl = realpath('./search_result.xsl');
$version = file($this->indexPath."/version.txt");
if (preg_match('/^CJKAnalyzer$/u', isset($version[1]) ? $version[1] : null))
{
$this->isCJKAnalyzer = true;
}
else
{
$this->isCJKAnalyzer = false;
}
$this->docFolder = explode('*',$version[0]);
$this->docFolder = $this->docFolder[0];
$protocol = 'http://';
if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'|| $_SERVER['SERVER_PORT'] == 443) {
$protocol = 'https://';
}
$this->phpPageName = $protocol.$_SERVER['SERVER_NAME'].':'.$_SERVER["SERVER_PORT"].$_SERVER['PHP_SELF'];
$this->docBase = substr($this->phpPageName, 0, strrpos($this->phpPageName, '/'));
$this->docBase = substr($this->docBase, 0, strrpos($this->docBase, '/'));
}
private function _doSearch()
{
$this->currentPage = -1;
if ($this->_isInvalidSearchString($this->searchString))
{
$this->hitsCount = 0;
return;
}
Zend_Search_Lucene_Analysis_Analyzer::setDefault(new TextAnalyzer($this->isCJKAnalyzer));
Zend_Search_Lucene::setDefaultSearchField('contents');
$index = Zend_Search_Lucene::open($this->indexPath);
$query = TextParser::parse($this->searchString, "UTF-8");
$hits = $index->find($query);
$this->hitsCount = count($hits);
for ($i = 0; $i < $this->hitsCount; $i++)
{
$hit = $hits[$i];
$document = $hit->getDocument();
$url = $document->getFieldValue('url');
$title = $document->getFieldValue('title');
$summary = $document->getFieldValue('summary');;
$umaType = $document->getFieldValue('uma.type');
if(strcasecmp($umaType, "udt")==0){
$searchicon=$document->getFieldValue('searchicon');
$this->searchResults[$i]['searchicon']=$searchicon;
}
$this->searchResults[$i]['url'] = $url;
$this->searchResults[$i]['title'] = $title;
$this->searchResults[$i]['summary'] = $summary;
$this->searchResults[$i]['uma.type'] = $umaType;
}
}
public function getPrevPage()
{
$this->currentPage--;
$result = $this->_getResults();
return $result;
}
public function getNextPage()
{
$this->currentPage++;
$result = $this->_getResults();
return $result;
}
private function _getResults()
{
try {
$initPageNumber = $this->currentPage * $this->hitsPerPage;
$maxPageNumber = min($this->hitsCount, $initPageNumber + $this->hitsPerPage);
$nextEnabled = ($this->hitsCount > ($initPageNumber + $this->hitsPerPage)) ? 'true' : 'false';
$prevEnabled = ($this->currentPage > 0) ? 'true' : 'false';
$searchResultXML = self::XML_DECLARATION.'<SearchResult'.
' totalHits="'.$this->hitsCount.
'" initPageNum="'.(($initPageNumber > 0) ? $initPageNumber + 1 : (($this->hitsCount < 1) ? 0 : 1)).
'" maxPageNum="'.$maxPageNumber.
'" hitsPerPage="'.$this->hitsPerPage.
'" nextEnabled="'.$nextEnabled.
'" prevEnabled="'.$prevEnabled.
'" nextText="'.SearchSettings::NEXT_ACTION_TEXT.
'" prevText="'.SearchSettings::PREVIOUS_ACTION_TEXT.
'" imagePath="'.$this->docBase.'/search/images/'.
'" searchString="'.TextParser::_filterCharacter($this->searchString).
'" nextHref="'.$this->dispatherPage.'?action=next'.
'" prevHref="'.$this->dispatherPage.'?action=prev'.
'">';
for($i = $initPageNumber; $i < $maxPageNumber; $i++)
{
$url = $this->searchResults[$i]['url'];
$title = $this->searchResults[$i]['title'];
$summary = $this->searchResults[$i]['summary'];
$umaType = $this->searchResults[$i]['uma.type'];
$searchResultXML.= '<SearchHit';
if (isset($url))
{
$fixedUrl = $this->docBase.substr($url, strpos($url, $this->docFolder)+ strlen($this->docFolder));
$searchResultXML.= ' url="'.$this->urlEscape($fixedUrl).'"';
}
if (isset($title))
{
//$searchResultXML.= ' title="'.$title.'"';
$searchResultXML.= ' title="'.$this->htmlEscape($title).'"';
}
if (isset($summary))
{
$searchResultXML.= ' summary="'.$this->htmlEscape($summary).'"';
}
if (isset($umaType))
{
// Here will be modified later
if (strcasecmp($umaType, 'General_content') == 0)
{
$searchResultXML.= ' icon="Other.gif"';
}else if(strcasecmp($umaType, "udt")==0){
$shapeImage=$this->searchResults[$i]['searchicon'];
if(isset($shapeImage)){
$searchIcon="./../../".$shapeImage;
$searchResultXML.=' icon="'.$searchIcon.'"';
}else{
$searchResultXML.=' icon="Other.gif"';
}
}
else
{
$searchResultXML.= ' icon="'.$this->convertFirstLetterCase($umaType, self::$keyWords).'.gif"';
}
}
$searchResultXML.= '/>';
}
$searchResultXML.= '</SearchResult>';
//echo htmlentities($searchResultXML);
// XML transform
$processor = new XSLTProcessor;
$xsl = new DOMDocument;
$xsl->load($this->xsl);
$xml = new DOMDocument;
$xml->loadXML($searchResultXML);
$processor ->importStyleSheet($xsl);
$result = $processor ->transformToXML($xml);
// echo htmlentities($result);
} catch(Exception $e) {
$result = SearchSettings::SEARCH_FAILED;
}
return $result;
}
protected function urlEscape($url)
{
$result = str_replace('\\', '/', $url);
return $result;
}
protected function htmlEscape($content)
{
$result = "";
$len = strlen($content);
for ($i = 0; $i < $len; $i++) {
$ch = $content[$i];
switch ($ch) {
case '<':
$result .= self::XML_LT;
break;
case '>':
$result .= self::XML_GT;
break;
case '&':
$result .= self::XML_AMP;
break;
case '"':
$result .= self::XML_QUOT;
break;
case '\'':
$result .= self::XML_APOS;
break;
case '\r':
$result .= self::XML_CR;
break;
case '\n':
$result .= self::XML_LF;
break;
default:
$result .= $ch;
break;
}
}
return $result;
}
protected function convertFirstLetterCase($str, $keyWords)
{
$lstr = ucfirst(strtolower($str));
foreach($keyWords as $keyWord)
{
$lstr = str_ireplace($keyWord, $keyWord, $lstr);
}
return $lstr;
}
private function _isInvalidSearchString($str)
{
if (($str==null)||(trim($str)=='')||(iconv_strlen($str, 'UTF-8')==1))
{
return true;
}
return false;
}
}
?>