/** * 初期化(イテレーション用) * @return void */ public function rewind() { //1行目はヘッダ行なので読み飛ばす $this->position = 1; if (!$this->lines) { //CSVを読み込み $giscsv = new Dm_Geocoder_GISCSV($this->prefectureCode); $buf = $giscsv->read(); //1行ごとに分解 $ret = array(); $lines = explode("\r\n", $buf); array_pop($lines); foreach ($lines as $line) { $ret[] = $line; } $this->lines = $ret; } }
/** * csvを検索文字列で検索し、検索結果としてマッチする候補を複数返す * * 検索速度を速くするため、少し処理が複雑になっています * 都道府県、市区町村、大字町丁目名と、段階的に検索をかけていきます。 * * @param Dm_Geocoder_Query * @return Dm_Geocoder_Address[] */ public static function find(Dm_Geocoder_Query $query) { // 都道府県を特定できていれば絞り込む if ($query->prefectureCode) { //入力された権のみを検索対象とする $prefectureCodes = array($query->prefectureCode); //検索文字列の頭に県名がついていれば削除する $needle = mb_substr($query->address, mb_strlen($query->prefectureName)); //県名のみの検索の場合は該当県のAddressを全件返して終了 if (strlen($needle) === 0) { return Dm_Geocoder_GISCSV_Reader::readAll($query->prefectureCode); } } else { //全件を検索対象とする $prefectureCodes = array_keys(Dm_Geocoder_Prefecture::get()); //検索対象文字列 $needle = $query->address; } $finded = array(); foreach ($prefectureCodes as $prefectureCode) { //CSVを読み込む $giscsv = new Dm_Geocoder_GISCSV($prefectureCode); $buf = $giscsv->read(); //都道府県名以降の文字列を市区町村名とマッチングして //1文字ずつCSVから正規表現で検索する $findedInPref = array(); $code = '\\"\\d+\\"'; $l = mb_strlen($needle); for ($i = 1; $i <= $l; $i++) { $mun = mb_substr($needle, 0, $i); $mun = preg_quote($mun); $mun = '\\"' . $mun; $pattern = '/^' . $code . ',\\"[^\\"]+\\",' . $code . ',' . $mun . '.+$/m'; preg_match_all($pattern, $buf, $match); //1件も一致しなければ終了 if (count($match[0]) === 0) { break; } //1件でも一致していれば保持する。これまでのものは破棄する。 $findedInPref = array(); foreach ($match[0] as $key => $row) { $address = new Dm_Geocoder_Address(); $findedInPref[] = $address->importCsv($row); } } $finded = array_merge($finded, $findedInPref); } //これまでに検索した行は市区町村レベルのマッチングだったので //今度は大字町丁目名までを使って1行1行マッチングする $addressMatchedMost = array(); $addressMatchedMostLength = 0; foreach ($finded as $key => $row) { //市区町村と大字町丁目名で検索する $matchesLength = self::forwardMatchesLength($row->municipalityName . $row->localName, $needle); if ($matchesLength === 0) { continue; } if ($matchesLength > $addressMatchedMostLength) { $addressMatchedMostLength = $matchesLength; $addressMatchedMost = array($row); } else { if ($matchesLength === $addressMatchedMostLength) { $addressMatchedMost[] = $row; } } } return $addressMatchedMost; }