• Как передать значения?

    pvsaintpe
    @pvsaintpe
    Senior PHP Developer
    В mysql в отличие от Postgres нет массивов и прочих плюшек, вам надо создать процедуру которая по разделителю разделит строку на части и вставит во временную таблицу и вернет результат в виде набора (выборки) тогда этот результат вы можете использовать в where другого запроса

    DELIMITER |
    
    CREATE PROCEDURE explode( pDelim VARCHAR(32), pStr TEXT)                                
    BEGIN                                
      DROP TABLE IF EXISTS temp_explode;                                
      CREATE TEMPORARY TABLE temp_explode (id INT AUTO_INCREMENT PRIMARY KEY NOT NULL, word VARCHAR(40));                                
      SET @sql := CONCAT('INSERT INTO temp_explode (word) VALUES (', REPLACE(QUOTE(pStr), pDelim, '\'), (\''), ')');                                
      PREPARE myStmt FROM @sql;                                
      EXECUTE myStmt;                                
    END |   
    
    DELIMITER ;


    Ну и в каком то запросе делайте так
    SET @str  = "The quick brown fox jumped over the lazy dog"; 
     SET @delim = " "; 
    
    CALL explode(@delim,@str);
    
    Select * from some_table where field in (
      SELECT word FROM temp_explode
    )


    Пример грубый но идею вы должны понять.
    Можно доработать чтобы процедура возвращала выборку, поэкспериментировать с переменными в общем если ваш путь через mysql.

    А так смотрите в сторону postgres
    Ответ написан
    Комментировать
  • Как сделать подстановку из массива?

    pvsaintpe
    @pvsaintpe
    Senior PHP Developer
    Слишком много вопросов и мало конкретки.

    У вас есть phpфайл примерно такого содержимого:
    <?
    
    return [
        101 => 'Москва',
        204 => 'Санкт-Петербург',
        // ...
    ];


    API требует ID, а для вывода на сайте вам нужен Name, так как в url у вас будет примерно такое

    ?city_id=101

    Файл с городами вы будете заполнять воучную, насколько я понял.

    Если вы хотите получать айди по названию Вам нужно сделать функцию, которая будет делать примерно это

    function getIdByName(string $name): int
    {
    $cities = require "cities.php";
    
    foreach ($cities as $id => $name) {
       if ((int) $_GET['citi_name'] === $name) {
           return $id;
       }
    }
    
    throw new Exception('город не существует');
    }


    Если вы хотите получать название по айди достаточно этого
    $name = $cities[$_GET['city_id']] ?? 'Invalid name';
    Ответ написан
  • Как сделать unique валидацию столбцов в laravel вместе с другим столбцом?

    pvsaintpe
    @pvsaintpe
    Senior PHP Developer
    для начала исправьте вашу структуру, сделайте поля start / end: timestamp или datetime чтобы те хранили часы тоже, иначе закрыв сессию одним днем, вы не сможете с вашей проверкой открыть сессию повторно в этот же день

    во-вторых, где выхотите валидировать в БД или в Laravel, я тут вижу скрин с базы.

    если у вас Postgres, на уровне БД можно контролировать добавив Exclude constraint

    use Illuminate\Database\Migrations\Migration;
    use Illuminate\Support\Facades\Schema;
    use Umbrellio\Postgres\Schema\Blueprint;
    
    class UpdateSessionsTable extends Migration
    {
        public function up()
        {
            Schema::table('sessions', function (Blueprint $table) {
                $table->datetime('start')->change();
                $table->datetime('end')->change();
                $table
                    ->exclude(['room_id', 'start', 'end'])
                    ->method('gist')
                    ->using('daterange(start, end)', '&&')
                    ->using('room_id', '=');
            });
        }
        ...
    }


    такая миграция добавит в вашу БД такой констрейнт
    ALTER TABLE sessions
        ADD CONSTRAINT sessions_room_id_start_end_excl
            EXCLUDE USING gist (room_id WITH =, daterange(start, end) WITH &&)


    поддержку exclude-ограничений в Laravel можно добавить используя расширение для Postgres:
    composer require umbrellio/laravel-pg-extensions

    Чтобы добавить валидацию в Laravel и можно было ее переиспользовать, вам нужно добавить макрос в Query\Builder сделать это можно так
    use Illuminate\Database\Query\Builder;
    use Illuminate\Support\ServiceProvider;
    
    class QueryServiceProvider extends ServiceProvider
    {
        public function boot()
        {
            Builder::macro(
                'overlaps',
                function ($startDate, $endDate, $startDateColumn, $endDateColumn, $bounds = '[]') {
                    $expression = implode(' && ', [
                        "daterange(?::date, ?::date, '{$bounds}')",
                        "daterange({$startDateColumn}, {$endDateColumn}, '{$bounds}')",
                    ]);
    
                    return $this->whereRaw($expression, [$startDate, $endDate]);
                }
            );
        }
    }


    т.к. в Request ну или где вы делаете валидацию через UniqueDatabaseRule, используется Query\Builder

    ну и в реквесте делайте так
    use Illuminate\Foundation\Http\FormRequest;
    
    class SaveSessionRequest extends FormRequest
    {
        public function rules(): array
        {
            return [
                'session.room_id' => Rule::unique('sessions', 'room_id')->overlaps(
                    $this->input('session.start'),
                    $this->input('session.end'),
                    'start',
                    'end',
                    '[]'
                ),
               // ..
            ];
        }
    
        // ...
    }


    Либо если не хотите макросом, перенести этот where прямо в ваш Request

    А если у вас MySQL, то вам нужно придумать что-то аналогичное, т.к. из коробки MySQL такие финты не поддерживает.
    Ответ написан
    Комментировать