변경 파일 목록
총 2개
변경 파일 코드
추가삭제
변경 전Board.php
| } else { | |
| $extraData['arrGoodsNo'][] = $extraData['goodsNoText']; | |
| } | |
| foreach ($extraData['arrGoodsNo'] as $key => $goodsNo) { | |
| $extraData['arrGoodsData'][$key] = $goods->getGoodsInfo($goodsNo); | |
| } | |
| } | |
| if ($extraData['orderGoodsNoText']) { | |
| $extraData['arrOrderGoodsNo'][] = $extraData['orderGoodsNoText']; | |
| } | |
| $order = new Order(); | |
| foreach ($extraData['arrOrderGoodsNo'] as $key => $orderGoodsNo) { | |
| $isAddGoods = substr($orderGoodsNo, 0, 1) == 'A' ? true : false; | |
| if ($isAddGoods) { | |
| $orderGoodsNo = substr($orderGoodsNo, 1); | |
| } | |
| $orderGoodsData = $order->getOrderGoods(null, $orderGoodsNo, null, null, null)[0]; | |
| $extraData['arrOrderGoodsData'][$key] = $orderGoodsData; | |
| $_arrOrderGoodsData = $extraData['arrOrderGoodsData'][$key]; | |
| $goodsNo = $_arrOrderGoodsData['goodsNo']; | |
| $extraData['arrOrderGoodsData'][$key]['goodsNo'] = $orderGoodsData['parentGoodsNo']; | |
| $extraData['arrOrderGoodsData'][$key]['totalGoodsPrice'] = $_arrOrderGoodsData['goodsCnt'] * ($addGoodsData['goodsPrice'] + $_arrOrderGoodsData['optionPrice'] + $_arrOrderGoodsData['optionTextPrice']); | |
| } else { | |
| $goodsImage = $goods->getGoodsImage($goodsNo, 'main'); | |
| $goodsInfo = $goods->getGoodsInfo($goodsNo); | |
| $goodsImageSrc = SkinUtils::imageViewStorageConfig($goodsImage[0]['goodsImageStorage'] == 'obs' ? $goodsImage[0]['imageUrl'] : $goodsImage[0]['imageName'], $goodsInfo['imagePath'], $goodsInfo['imageStorage'], 100, 'goods')[0]; | |
| $extraData['arrOrderGoodsData'][$key]['totalGoodsPrice'] = $_arrOrderGoodsData['goodsCnt'] * ($_arrOrderGoodsData['goodsPrice'] + $_arrOrderGoodsData['optionPrice'] + $_arrOrderGoodsData['optionTextPrice']); | |
| } | |
변경 후Board.php
| } else { | |
| $extraData['arrGoodsNo'][] = $extraData['goodsNoText']; | |
| } | |
| // N+1 쿼리 패턴 개선: 연관상품 개별 getGoodsInfo() 반복 -> IN절 배치 1회 | |
| // (user/module Goods 오버라이드가 배치 메서드 미상속 시 fatal 방지 가드) | |
| if (method_exists($goods, 'getGoodsInfoByNos')) { | |
| $batchGoodsData = $goods->getGoodsInfoByNos($extraData['arrGoodsNo']); | |
| foreach ($extraData['arrGoodsNo'] as $key => $goodsNo) { | |
| $extraData['arrGoodsData'][$key] = $batchGoodsData[$goodsNo] ?? []; | |
| } | |
| } else { | |
| foreach ($extraData['arrGoodsNo'] as $key => $goodsNo) { | |
| $extraData['arrGoodsData'][$key] = $goods->getGoodsInfo($goodsNo); | |
| } | |
| } | |
| } | |
| if ($extraData['orderGoodsNoText']) { | |
| $extraData['arrOrderGoodsNo'][] = $extraData['orderGoodsNoText']; | |
| } | |
| $order = new Order(); | |
| // N+1 쿼리 패턴 개선: 주문상품/이미지/정보 개별 반복 조회 -> 루프 진입 전 IN절 배치 선조회 | |
| // add-goods 의 getDataAddGoods 만 per-item 유지. user/module Goods 미상속 시 기존 per-item 폴백 | |
| $useBatch = method_exists($goods, 'getGoodsInfoByNos'); | |
| $orderGoodsMap = $goodsInfoMap = $goodsImageMap = []; | |
| if ($useBatch) { | |
| $snoList = []; | |
| foreach ($extraData['arrOrderGoodsNo'] as $orderGoodsNo) { | |
| $snoList[] = (substr($orderGoodsNo, 0, 1) == 'A') ? substr($orderGoodsNo, 1) : $orderGoodsNo; | |
| } | |
| $orderGoodsList = $order->getOrderGoods(null, $snoList, null, null, null); | |
| if (is_array($orderGoodsList)) { | |
| foreach ($orderGoodsList as $orderGoodsRow) { | |
| $orderGoodsMap[$orderGoodsRow['sno']] = $orderGoodsRow; | |
| } | |
| } | |
| $normalGoodsNos = []; | |
| foreach ($extraData['arrOrderGoodsNo'] as $orderGoodsNo) { | |
| if (substr($orderGoodsNo, 0, 1) == 'A') { | |
| continue; | |
| } | |
| if (isset($orderGoodsMap[$orderGoodsNo]['goodsNo'])) { | |
| $normalGoodsNos[] = $orderGoodsMap[$orderGoodsNo]['goodsNo']; | |
| } | |
| } | |
| $goodsInfoMap = $goods->getGoodsInfoByNos($normalGoodsNos); | |
| $goodsImageMap = $goods->getGoodsImageByNos($normalGoodsNos, 'main'); | |
| } | |
| foreach ($extraData['arrOrderGoodsNo'] as $key => $orderGoodsNo) { | |
| $isAddGoods = substr($orderGoodsNo, 0, 1) == 'A' ? true : false; | |
| if ($isAddGoods) { | |
| $orderGoodsNo = substr($orderGoodsNo, 1); | |
| } | |
| $orderGoodsData = $useBatch | |
| ? ($orderGoodsMap[$orderGoodsNo] ?? []) | |
| : ($order->getOrderGoods(null, $orderGoodsNo, null, null, null)[0] ?? []); | |
| $extraData['arrOrderGoodsData'][$key] = $orderGoodsData; | |
| $_arrOrderGoodsData = $extraData['arrOrderGoodsData'][$key]; | |
| $goodsNo = $_arrOrderGoodsData['goodsNo']; | |
| $extraData['arrOrderGoodsData'][$key]['goodsNo'] = $orderGoodsData['parentGoodsNo']; | |
| $extraData['arrOrderGoodsData'][$key]['totalGoodsPrice'] = $_arrOrderGoodsData['goodsCnt'] * ($addGoodsData['goodsPrice'] + $_arrOrderGoodsData['optionPrice'] + $_arrOrderGoodsData['optionTextPrice']); | |
| } else { | |
| $goodsImage = $useBatch ? ($goodsImageMap[$goodsNo] ?? false) : $goods->getGoodsImage($goodsNo, 'main'); | |
| $goodsInfo = $useBatch ? ($goodsInfoMap[$goodsNo] ?? []) : $goods->getGoodsInfo($goodsNo); | |
| $goodsImageSrc = SkinUtils::imageViewStorageConfig($goodsImage[0]['goodsImageStorage'] == 'obs' ? $goodsImage[0]['imageUrl'] : $goodsImage[0]['imageName'], $goodsInfo['imagePath'], $goodsInfo['imageStorage'], 100, 'goods')[0]; | |
| $extraData['arrOrderGoodsData'][$key]['totalGoodsPrice'] = $_arrOrderGoodsData['goodsCnt'] * ($_arrOrderGoodsData['goodsPrice'] + $_arrOrderGoodsData['optionPrice'] + $_arrOrderGoodsData['optionTextPrice']); | |
| } | |
변경 전Goods.php
| $this->db->set_insert_db(DB_LOG_REGULAR_GOODS, $arrBind['param'], $arrBind['bind'], 'y'); | |
| } | |
| } | |
| } | |
변경 후Goods.php
| $this->db->set_insert_db(DB_LOG_REGULAR_GOODS, $arrBind['param'], $arrBind['bind'], 'y'); | |
| } | |
| } | |
| /** | |
| * 상품정보 배치 조회 — getGoodsInfo() 의 IN절 배치판 (게시판 상세보기 N+1 쿼리 패턴 개선) | |
| * | |
| * 단건 getGoodsInfo() 를 goodsNo 건수만큼 반복 호출하던 구간을 IN 절 1회 조회로 대체한다. | |
| * | |
| * 게시판 상세보기 배치 전용 내부 헬퍼. 호출부(Board::getExtraData)가 method_exists 가드로 미구현(튜닝 fork) 환경을 단건 경로로 폴백하므로 외부 튜닝 확장점이 아니다. 시그니처 안정 유지를 권장한다. | |
| * | |
| * @param array $arrGoodsNo 상품번호 배열 | |
| * @param string|null $goodsField 출력 필드 (기본 null = 단건 getGoodsInfo 와 동일 전체 조회). goodsNo 컬럼은 결과 맵의 키이므로 부분 필드 지정 시에도 반드시 포함할 것 | |
| * @return array goodsNo 를 키로 하는 상품정보 맵 [goodsNo => row] | |
| */ | |
| public function getGoodsInfoByNos(array $arrGoodsNo, $goodsField = null): array | |
| { | |
| $arrGoodsNo = array_values(array_unique(array_filter($arrGoodsNo))); | |
| if (empty($arrGoodsNo)) { | |
| return []; | |
| } | |
| $arrBind = null; | |
| $bindQuery = []; | |
| foreach ($arrGoodsNo as $goodsNo) { | |
| $bindQuery[] = '?'; | |
| $this->db->bind_param_push($arrBind, 'i', $goodsNo); | |
| } | |
| $inClause = ' g.goodsNo IN (' . implode(',', $bindQuery) . ') '; | |
| if ($this->db->strWhere) { | |
| $this->db->strWhere = $inClause . ' AND ' . $this->db->strWhere; | |
| } else { | |
| $this->db->strWhere = $inClause; | |
| } | |
| if ($goodsField) { | |
| $this->db->strField = $this->db->strField ? $goodsField . ', ' . $this->db->strField : $goodsField; | |
| } | |
| $query = $this->db->query_complete(); | |
| $strSQL = 'SELECT ' . array_shift($query) . ' FROM ' . DB_GOODS . ' g ' . implode(' ', $query); | |
| $getData = $this->db->secondary()->query_fetch($strSQL, $arrBind); | |
| $goodsInfoMap = []; | |
| foreach ((array) $getData as $row) { | |
| $row = gd_htmlspecialchars_stripslashes($row); | |
| $goodsInfoMap[$row['goodsNo']] = $row; | |
| } | |
| return $goodsInfoMap; | |
| } | |
| /** | |
| * 상품이미지 배치 조회 — getGoodsImage() 의 IN절 배치판 (게시판 상세보기 N+1 쿼리 패턴 개선) | |
| * | |
| * 게시판 상세보기 배치 전용 내부 헬퍼. 호출부(Board::getExtraData)가 method_exists 가드로 미구현(튜닝 fork) 환경을 단건 경로로 폴백하므로 외부 튜닝 확장점이 아니다. 시그니처 안정 유지를 권장한다. | |
| * | |
| * @param array $arrGoodsNo 상품번호 배열 | |
| * @param string $imageKind 이미지 종류 (기본 'main') | |
| * @return array goodsNo 를 키로 하는 이미지행 맵 [goodsNo => [row, ...]] | |
| */ | |
| public function getGoodsImageByNos(array $arrGoodsNo, $imageKind = 'main'): array | |
| { | |
| $arrGoodsNo = array_values(array_unique(array_filter($arrGoodsNo))); | |
| if (empty($arrGoodsNo)) { | |
| return []; | |
| } | |
| $arrBind = null; | |
| $bindQuery = []; | |
| foreach ($arrGoodsNo as $goodsNo) { | |
| $bindQuery[] = '?'; | |
| $this->db->bind_param_push($arrBind, 'i', $goodsNo); | |
| } | |
| $this->db->bind_param_push($arrBind, 's', $imageKind); | |
| // 단건 getGoodsImage 는 goodsNo 를 SELECT 에서 제외하나, 배치는 매핑 키로 필요 → goodsNo 추가 | |
| $arrField = DBTableField::setTableField('tableGoodsImage', null, 'goodsNo'); | |
| $strSQL = "SELECT goodsNo, sno, " . implode(', ', $arrField) . " FROM " . DB_GOODS_IMAGE | |
| . " WHERE goodsNo IN (" . implode(',', $bindQuery) . ") AND imageKind = ? " | |
| . " ORDER BY imageKind ASC, imageNo ASC"; | |
| $getData = $this->db->secondary()->query_fetch($strSQL, $arrBind); | |
| $goodsImageMap = []; | |
| foreach ((array) $getData as $row) { | |
| $row = gd_htmlspecialchars_stripslashes($row); | |
| $goodsImageMap[$row['goodsNo']][] = $row; | |
| } | |
| return $goodsImageMap; | |
| } | |
| } | |