Эта проблема сводит меня с ума.
Похоже, что клонирование запроса не работает должным образом со времени моего последнего обновления композитора.
Странно то, что если я не буду выступать ->get()
при первом клонировании запроса второй запрос выполняется нормально. С того момента, как я выполняю ->get
на обоих клонах запроса я получаю сообщение об ошибке:
General error: 2031
clone
следует создать глубокую копию исходного запроса, но что-то не так.
Есть идеи? Вот мой запрос (он выглядит более сложным, чем он есть, и сам запрос в порядке):
//Query dates
$query_onetime = clone $query;
$query_onetime = $query_onetime->join('events_dates', function($join) use ($input_date_start, $input_date_end){
$join->on('events.id', '=', 'events_dates.event_id');
$join->where('events_dates.start_date', "<=", $input_date_end);
$join->where('events_dates.end_date', '>=', $input_date_start);
});
//Select fields
$events_onetime = $query_onetime->select('events.id AS id', 'events.name AS name', 'event_categories.id as category_id', 'event_categories.category as category',
'event_subcategories.id as subcategory_id', 'event_subcategories.subcategory as subcategory',
'short_description', 'time_description',
'price_description', 'nr_going', 'nr_checkedin', 'homepage', 'fbpage', 'profile_pic',
'places.id AS place_id', 'places.name AS place_name', 'lat', 'lng', 'address')
->groupBy('events.id')
->get();
if(isset($data["include_recurrent"]) && $data["include_recurrent"]){
//Query recurrent dates
$query_recurrent = clone $query;
$query_recurrent = $query_recurrent->join('events_dates_recurrent', 'events.id', '=', 'events_dates_recurrent.event_id')
->where(function($join) use ($input_date_start, $input_date_end) {
//Create a dynamic query to get all recurrent dates within the input time interval
$query_string = "ABS(DATEDIFF('" . $input_date_start . "', CAST(events_dates_recurrent.start_date AS DATE)) % events_dates_recurrent.repeat_interval) = 0";
$temp_date_start = $input_date_start;
while(strtotime($temp_date_start) < strtotime($input_date_end)){
$temp_date_start = date('Y-m-d', strtotime($temp_date_start . " +1 day"));
//Create a raw query string
$query_string = $query_string . " OR ABS(DATEDIFF('" . $temp_date_start . "', CAST(events_dates_recurrent.start_date AS DATE)) % events_dates_recurrent.repeat_interval) = 0";
}
$join->whereRaw($query_string);
});
//Select fields
$events_recurrent = $query_recurrent->select('events.id AS id', 'events.name AS name', 'event_categories.id as category_id', 'event_categories.category as category',
'event_subcategories.id as subcategory_id', 'event_subcategories.subcategory as subcategory',
'short_description', 'time_description',
'price_description', 'nr_going', 'nr_checkedin', 'homepage', 'fbpage', 'profile_pic',
'places.id AS place_id', 'places.name AS place_name', 'lat', 'lng', 'address')
->groupBy('events.id')
->get();
$events = array_merge($events_onetime, $events_recurrent);
РЕДАКТИРОВАТЬ: для получения информации по запросу, здесь полный запрос.
Я избегал этого, потому что это довольно долго.
// Queries events based on map bounds, category and date
$query = DB::table('events')
->join('places', function($join) use ($data){
$join->on('events.place_id', '=', 'places.id')
->where('places.lat', '>', $data['sw_lat'])
->where('places.lat', '<', $data['ne_lat'])
->where('places.lng', '>', $data['sw_lng'])
->where('places.lng', '<', $data['ne_lng']);
})->join('event_categories', function($join) use ($data){
$join->on('events.category_id', '=', 'event_categories.id');
});
// The category id is optional
if(isset($data["category_id"])){
$query = $query->where('event_categories.id', '=', $data['category_id']);
}
//Query subcategory
$query = $query->leftJoin('event_subcategories', function($join) use ($data){
$join->on('events.subcategory_id', "=", "event_subcategories.id");
});
//Query keywords
$query = $query->join('events_keywords', 'events.id', '=', 'events_keywords.event_id');
//Reverse date format
$input_date_start = date("Y-m-d", strtotime($data["date_start"]));
$input_date_end = date("Y-m-d", strtotime($data["date_end"]));
//Query dates
$query_onetime = clone $query;
$query_onetime = $query_onetime->join('events_dates', function($join) use ($input_date_start, $input_date_end){
$join->on('events.id', '=', 'events_dates.event_id');
$join->where('events_dates.start_date', "<=", $input_date_end);
$join->where('events_dates.end_date', '>=', $input_date_start);
});
//Select fields
$events_onetime = $query_onetime->select('events.id AS id', 'events.name AS name', 'event_categories.id as category_id', 'event_categories.category as category',
'event_subcategories.id as subcategory_id', 'event_subcategories.subcategory as subcategory',
'short_description', 'time_description',
'price_description', 'nr_going', 'nr_checkedin', 'homepage', 'fbpage', 'profile_pic',
'places.id AS place_id', 'places.name AS place_name', 'lat', 'lng', 'address')
->groupBy('events.id')
->get();
foreach($events_onetime as $event){
$temp_event = EventModel::find($event->id);
$event->keywords = $temp_event->keywords;
}
if(isset($data["include_recurrent"]) && $data["include_recurrent"]){
//Query recurrent dates
$query_recurrent = clone $query;
$query_recurrent = $query_recurrent->join('events_dates_recurrent', 'events.id', '=', 'events_dates_recurrent.event_id')
->where(function($join) use ($input_date_start, $input_date_end) {
//Create a dynamic query to get all recurrent dates within the input time interval
$query_string = "ABS(DATEDIFF('" . $input_date_start . "', CAST(events_dates_recurrent.start_date AS DATE)) % events_dates_recurrent.repeat_interval) = 0";
$temp_date_start = $input_date_start;
while(strtotime($temp_date_start) < strtotime($input_date_end)){
$temp_date_start = date('Y-m-d', strtotime($temp_date_start . " +1 day"));
//Create a raw query string
$query_string = $query_string . " OR ABS(DATEDIFF('" . $temp_date_start . "', CAST(events_dates_recurrent.start_date AS DATE)) % events_dates_recurrent.repeat_interval) = 0";
}
$join->whereRaw($query_string);
});
//Select fields
$events_recurrent = $query_recurrent->select('events.id AS id', 'events.name AS name', 'event_categories.id as category_id', 'event_categories.category as category',
'event_subcategories.id as subcategory_id', 'event_subcategories.subcategory as subcategory',
'short_description', 'time_description',
'price_description', 'nr_going', 'nr_checkedin', 'homepage', 'fbpage', 'profile_pic',
'places.id AS place_id', 'places.name AS place_name', 'lat', 'lng', 'address')
->groupBy('events.id')
->get();
//At this point we just have the events, but we also need the keywords per event.
foreach($events_recurrent as $event){
$temp_event = EventModel::find($event->id);
$event->keywords = $temp_event->keywords;
}
$events = array_merge($events_onetime, $events_recurrent);
} else {
//Else return only the non-recurrent events
$events = $events_onetime;
}
return $events;
}
Ваш $query
объект является экземпляром Illuminate\Database\Eloquent\Builder
и он поддерживает ссылку на Illuminate\Database\Query\Builder
который содержит фактический запрос. Согласно PHP Документы, clone
Ключевое слово выполняет поверхностную копию объекта, что означает, что ссылки копируются как ссылки. Таким образом, $query
а также $query_onetime
оба поддерживают ссылку на одно и то же Illuminate\Database\Query\Builder
экземпляр и изменения одного влияют на другой.
Эта проблема с необходимостью клонирования базового запроса была исправлена в Laravel 4.1, но если вы не хотите обновляться, вы можете попробовать этот обходной путь:
$query_onetime = clone $query;
$query_onetime->setQuery(clone $query->getQuery());
// Any additional joins specific to $query_onetime
Других решений пока нет …