Тематика? Ссылки покупаете? Как часто обновляется контент? Текста сами пишите или переводом через deepl?
Сайт под США очень тяжело поднять, все известные вам способы в ру сегменте не помогут от слова совсем.
Тематика? Ссылки покупаете? Как часто обновляется контент? Текста сами пишите или переводом через deepl?
Сайт под США очень тяжело поднять, все известные вам способы в ру сегменте не помогут от слова совсем.
Удалять
activeстолбец из этой таблицы, но создайте еще одну таблицу, в которой будут храниться одна строка и один столбец с текущей активной строкой.
id. Измените это сохраненное значение в триггере AFTER INSERT:
CREATE TABLE entity ( id INT(11), name VARCHAR(50) ); CREATE TABLE active_entity ( active_id INT(11) ) SELECT 0 active_id; CREATE TRIGGER store_active AFTER INSERT ON entity FOR EACH ROW UPDATE active_entity SET active_entity.active_id = CASE @active WHEN TRUE THEN NEW.id ELSE active_entity.active_id END;
Следующее предложение может работать здесь как альтернатива вашему нынешнему подходу. Вместо текущего дизайна таблицы используйте этот:
CREATE TABLE entity ( id INT NOT NULL AUTO_INCREMENT, name VARCHAR(50), -- other columns here );
Предполагая, что последовательность автоматического увеличения всегда увеличивается, вы можете просто найти запись активного имени, используя:
SELECT * FROM entity WHERE name = 'blah' ORDER BY id DESC LIMIT 1;
В случае, если две вставки с одинаковым именем поступают почти одновременно, MySQL всегда гарантирует, что одной из них будет присвоен самый высокий (последний)
idценить. Обратите внимание, что существуют сценарии, в которых следующее сгенерированное значение автоматического приращения не обязательно должно быть больше предыдущего. Но если вы никогда не удаляете записи из
entityстол, этого не должно произойти.
А смысл писать, если там этот компонент выйдет в новой версии, тем более логично что там пишет команда, а тут Вы один будете, проще дождаться уже.
Вот общий план, как можно реализовать компонент бронирования в ДСТ Мед:
Backend1. Модель бронирования:
class Booking extends Model { protected $fillable = ['doctor_id', 'user_id', 'status', 'appointment_time']; public function doctor() { return $this->belongsTo(Doctor::class); } public function user() { return $this->belongsTo(User::class); } }
1. Контроллер бронирования:
class BookingController extends Controller { public function create(Request $request) { $booking = Booking::create([ 'doctor_id' => $request->doctor_id, 'user_id' => $request->user_id, 'status' => 'pending', 'appointment_time' => $request->appointment_time, ]); return response()->json($booking); } public function updateStatus(Request $request, $id) { $booking = Booking::find($id); $booking->status = $request->status; $booking->save(); return response()->json($booking); } public function index() { $bookings = Booking::with('doctor', 'user')->get(); return response()->json($bookings); } }
1. Маршруты:
Route::post('/bookings', [BookingController::class, 'create']); Route::put('/bookings/{id}/status', [BookingController::class, 'updateStatus']); Route::get('/bookings', [BookingController::class, 'index']);
Frontend1. Форма бронирования:
<form id="bookingForm"> <input type="hidden" name="doctor_id" value="{{ doctor.id }}"> <input type="hidden" name="user_id" value="{{ user.id }}"> <input type="datetime-local" name="appointment_time" required> <button type="submit">Забронировать</button> </form>
<script> document.getElementById('bookingForm').addEventListener('submit', function(e) { e.preventDefault(); const formData = new FormData(this); fetch('/bookings', { method: 'POST', body: formData }).then(response => response.json()) .then(data => { alert('Бронирование успешно создано!'); }); }); </script>
1. Админка для управления бронированиями:
<table id="bookingsTable"> <thead> <tr> <th>Врач</th> <th>Пациент</th> <th>Время</th> <th>Статус</th> <th>Действия</th> </tr> </thead> <tbody> <!-- Здесь будут строки с бронированиями --> </tbody> </table>
<script> function loadBookings() { fetch('/bookings') .then(response => response.json()) .then(data => { const tableBody = document.querySelector('#bookingsTable tbody'); tableBody.innerHTML = ''; data.forEach(booking => { const row = document.createElement('tr'); row.innerHTML = ` <td>${booking.doctor.name}</td> <td>${booking.user.name}</td> <td>${booking.appointment_time}</td> <td>${booking.status}</td> <td> <select onchange="updateStatus(${booking.id}, this.value)"> <option value="pending" ${booking.status === 'pending' ? 'selected' : ''}>В ожидании</option> <option value="accepted" ${booking.status === 'accepted' ? 'selected' : ''}>Принято</option> <option value="rejected" ${booking.status === 'rejected' ? 'selected' : ''}>Отказано</option> </select> </td> `; tableBody.appendChild(row); }); }); } function updateStatus(id, status) { fetch(`/bookings/${id}/status`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ status }) }).then(response => response.json()) .then(data => { alert('Статус обновлен!'); loadBookings(); }); } loadBookings(); </script>
База данных1. Миграция для таблицы бронирований:
Schema::create('bookings', function (Blueprint $table) { $table->id(); $table->foreignId('doctor_id')->constrained(); $table->foreignId('user_id')->constrained(); $table->string('status'); $table->timestamp('appointment_time'); $table->timestamps(); });
Этот пример демонстрирует базовую реализацию компонента бронирования. Вы можете адаптировать его под вашу конкретную архитектуру и требования.
Использовать:
SELECT t.contactid FROM YOUR_TABLE t WHERE flag IN ('Volunteer', 'Uploaded') GROUP BY t.contactid HAVING COUNT(DISTINCT t.flag) = 2 Главное, чтобы подсчет
t.flag должно равняться количеству аргументов в INпункт.
Использование
COUNT(DISTINCT t.flag)в случае, если нет уникального ограничения на комбинацию контактного идентификатора и флага — если нет вероятности дублирования, вы можете опустить DISTINCT из запроса:
SELECT t.contactid FROM YOUR_TABLE t WHERE flag IN ('Volunteer', 'Uploaded') GROUP BY t.contactid HAVING COUNT(t.flag) = 2 Вы можете использовать
GROUP BYи
HAVING COUNT(*) = _:
SELECT contact_id FROM your_table WHERE flag IN ('Volunteer', 'Uploaded', ...) GROUP BY contact_id HAVING COUNT(*) = 2 -- // must match number in the WHERE flag IN (...) list (при условии
contact_id, flag является уникальным). Или используйте объединения:
SELECT T1.contact_id FROM your_table T1 JOIN your_table T2 ON T1.contact_id = T2.contact_id AND T2.flag = 'Uploaded' -- // more joins if necessary WHERE T1.flag = 'Volunteer'
Если список флагов очень длинный и много совпадений, первый, вероятно, будет быстрее. Если список флагов короткий и совпадений мало, вы, вероятно, обнаружите, что второй быстрее. Если производительность вызывает беспокойство, попробуйте протестировать оба варианта на своих данных, чтобы определить, какой из них работает лучше всего.
Если вы создадите индекс на
table(col1, col2), и ты делаешь
WHERE col1 = 'something' AND col2 = 'something'вы будете использовать индекс; это будет очень избирательно. То же самое с
WHERE col1 = 'something'
Но
WHERE col1 IS NOT NULL вам придется протестировать. WHERE col1 IS NULL будет сканировать таблицу, поскольку в этой ситуации индекс вовсе не является избирательным. Обновление индекса с помощью INSERT или UPDATE требует небольших накладных расходов. Это не может быть УНИКАЛЬНЫЙ индекс, поэтому рабочая нагрузка немного меньше. Но в большинстве случаев об этом не стоит беспокоиться, если только ваша рабочая нагрузка INSERT/UPDATE не намного тяжелее рабочей нагрузки SELECT. Если вы можете сделать столбцы
COLLATE latin1_binвы получите максимально легкие индексы. Но никаких смайлов, китайских иероглифов или нечувствительности к регистру.
type Options = ({ settings?: Settings<true>; enforceAdvancedOrder?: boolean; } | { settings?: Settings<false | undefined>; enforceAdvancedOrder?: never; }); type Settings<B extends boolean | undefined = boolean> = B extends undefined ? { enableAdvancedFeature?: B; } : { enableAdvancedFeature: B; };
const validOption1: Options = { settings: { enableAdvancedFeature: true }, enforceAdvancedOrder: true, }; const validOption2: Options = { settings: { enableAdvancedFeature: false }, enforceAdvancedOrder: undefined, // enforceAdvancedOrder should be undefined }; const validOption3: Options = { settings: {}, enforceAdvancedOrder: undefined, // enforceAdvancedOrder should be undefined }; const invalidOption: Options = { settings: { enableAdvancedFeature: false }, enforceAdvancedOrder: true, // This should cause a TypeScript error }; const invalidOption2: Options = { settings: {}, enforceAdvancedOrder: true, // This should cause a TypeScript error };
type ConditionalOption = | { enforceAdvancedOrder?: boolean, settings?: { enableAdvancedFeature?: true } } | { enforceAdvancedOrder?: undefined, settings?: { enableAdvancedFeature?: false | undefined } }
let a: ConditionalOption = { settings: { enableAdvancedFeature: true }, enforceAdvancedOrder: true } // okay let b: ConditionalOption = { settings: { enableAdvancedFeature: false }, enforceAdvancedOrder: true } // throws error let c: ConditionalOption = { settings: { enableAdvancedFeature: false }, enforceAdvancedOrder: undefined } // okay
@import url(https://fonts.googleapis.com/css?family=Open+Sans);
@import url(https://fonts.googleapis.com/css?family=Open+Sans); body{ font-family: 'Open Sans',serif; }
@import url('https://fonts.googleapis.com/css?family=Open+Sans&display=swap');
По моему мнению, поработав с несколькими разными системами, создание маркетплейса на DST Маркетплейс имеет несколько ключевых преимуществ по сравнению с другими популярными платформами, такими как CS Cart и 1С-Битрикс: 1. Битрикс это все таки Интернет-магазин, а маркетплейс это лишь расширение т.е. отдельный модуль, что конечно сразу усложняет всю ситуацию с дальнейшим масштабированием. 2. С Agora не работал, так что тут ничего сказать не могу. 3. На CS Cart нам не хватило функционала, даже купив самую дорогую лицензию ее оказалось меньше чем в базовой DST Маркетплейс. 4. Также попробовали и WordPress с модулем WooCommerce, оказалась вообще игрушкой, нет ни ЛК поставщика, не серьезных инструментов аналитики, ни системы уведомлений, да вообще ничего. Так что если рассматривать альтернативы, то сейчас на рынке 2 системы для запуска своего маркетплейса это CS Cart и DST Маркетплейс, мы выбрали последнее.
Ну а главные преимущества это конечно огромное количество разного функционала, просто сравните ЛК клиента и ЛК поставщика в DST Маркетплейс и сразу поймете в чем разница.
Автотрейд, спасибо за ответ, а не подскажите может у Вас какая то расширенная лицензия — Энтерпрайз, у меня просто лицензия Премиум, а также если не секрет во сколько обходиться содержание сервера?
Владимир Соколов