+ static function multiGetClass($cls, $keyCol, array $keyVals)
+ {
+ $obj = new $cls;
+
+ // PHP compatible datatype for settype() below
+ $colType = $obj->columnType($keyCol);
+
+ if (!in_array($colType, array('integer', 'int'))) {
+ // This is because I'm afraid to escape strings incorrectly
+ // in the way we use them below in FIND_IN_SET for MariaDB
+ throw new ServerException('Cannot do multiGet on anything but integer columns');
+ }
+
+ $obj->whereAddIn($keyCol, $keyVals, $colType);
+
+ // Since we're inputting straight to a query: format and escape
+ foreach ($keyVals as $key=>$val) {
+ settype($val, $colType);
+ $keyVals[$key] = $obj->escape($val);
+ }
+
+ // FIND_IN_SET will make sure we keep the desired order
+ $obj->orderBy(sprintf("FIND_IN_SET(%s, '%s')", $keyCol, implode(',', $keyVals)));
+ $obj->find();
+
+ return $obj;
+ }
+
+ /**
+ * Get multiple items from the database by key
+ *
+ * @param string $cls Class to fetch
+ * @param string $keyCol name of column for key
+ * @param array $keyVals key values to fetch
+ * @param boolean $otherCols Other columns to hold fixed
+ *
+ * @return array Array mapping $keyVals to objects, or null if not found
+ */
+ static function pivotGetClass($cls, $keyCol, array $keyVals, array $otherCols = array())
+ {
+ if (is_array($keyCol)) {
+ foreach ($keyVals as $keyVal) {
+ $result[implode(',', $keyVal)] = null;
+ }
+ } else {
+ $result = array_fill_keys($keyVals, null);
+ }
+
+ $toFetch = array();
+
+ foreach ($keyVals as $keyVal) {
+
+ if (is_array($keyCol)) {
+ $kv = array_combine($keyCol, $keyVal);
+ } else {
+ $kv = array($keyCol => $keyVal);
+ }
+
+ $kv = array_merge($otherCols, $kv);
+
+ $i = self::multicache($cls, $kv);
+
+ if ($i !== false) {
+ if (is_array($keyCol)) {
+ $result[implode(',', $keyVal)] = $i;
+ } else {
+ $result[$keyVal] = $i;
+ }
+ } else if (!empty($keyVal)) {
+ $toFetch[] = $keyVal;
+ }
+ }
+
+ if (count($toFetch) > 0) {
+ $i = new $cls;
+ foreach ($otherCols as $otherKeyCol => $otherKeyVal) {
+ $i->$otherKeyCol = $otherKeyVal;
+ }
+ if (is_array($keyCol)) {
+ $i->whereAdd(self::_inMultiKey($i, $keyCol, $toFetch));
+ } else {
+ $i->whereAddIn($keyCol, $toFetch, $i->columnType($keyCol));
+ }
+ if ($i->find()) {
+ while ($i->fetch()) {
+ $copy = clone($i);
+ $copy->encache();
+ if (is_array($keyCol)) {
+ $vals = array();
+ foreach ($keyCol as $k) {
+ $vals[] = $i->$k;
+ }
+ $result[implode(',', $vals)] = $copy;
+ } else {
+ $result[$i->$keyCol] = $copy;
+ }
+ }
+ }
+
+ // Save state of DB misses
+
+ foreach ($toFetch as $keyVal) {
+ $r = null;
+ if (is_array($keyCol)) {
+ $r = $result[implode(',', $keyVal)];
+ } else {
+ $r = $result[$keyVal];
+ }
+ if (empty($r)) {
+ if (is_array($keyCol)) {
+ $kv = array_combine($keyCol, $keyVal);
+ } else {
+ $kv = array($keyCol => $keyVal);
+ }
+ $kv = array_merge($otherCols, $kv);
+ // save the fact that no such row exists
+ $c = self::memcache();
+ if (!empty($c)) {
+ $ck = self::multicacheKey($cls, $kv);
+ $c->set($ck, null);
+ }
+ }
+ }
+ }
+
+ return $result;
+ }
+
+ static function _inMultiKey($i, $cols, $values)