Вопрос: Почему не получается записать в базу данных?

Лучший ответ:
База данных всегда сама подробно расскажет, почему у неё не получилось выполнить запрос. Надо её только об этом попросить. 

Поэтому сначала учимся правильно соединяться.
Весь этот детский лепет "не могу соединиться с БД" выкидываем и пишем нормальный код, который сам, без всяких проверок, сообщит нам об ошибках.
В случае mysqli это 
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$link = mysqli_connect($host, $user, $pass, $db_name);
$link->set_charset("utf8mb4");
Здесь первая строчка отвечает как раз за информирование об ошибках

Кроме того надо не забыть про ошибки РНР
Во-первых, всегда в коде должно быть error_reporting(E_ALL);
Плюс на домашнем компе ini_set('display_errors',1);, а на боевом - ini_set('display_errors',0);ini_set('log_errors',1);, и смотреть, соответственно, в логах.

После этого переписываем запрос.  Причем так, чтобы данные в БД всегда попадали  отдельно от самого запроса. Это непреложное правило, которое надо соблюдать всегда. 
Для этого надо

Заменить все переменные в запросе на специальные маркеры, которые называются плейсхолдеры или параметры, а по сути - просто знаки вопроса
Подготовить запрос к исполнению с помощью функции prepare(). Эта функция принимает строку запроса и возвращает экземпляр специального класса stmt, с которым в дальнейшем и производятся все манипуляции
Привязать переменные к запросу.
Выполнить подготовленный ранее запрос с помощью с помощью execute()

В mysqli это будет так
$sql = "INSERT INTO `events` (`title`, `discription`, `date`, `img`) VALUES (?,?,?,?)";
$stmt = $link->prepare($sql);
$stmt->bind_param("sssss", $title, $discription, $date, $path);
$stmt->execute();
bind_param() принимает в качестве параметров все переменные, которые должны попасть в запрос, в том же самом порядке, в котором стоят плейсхолдеры в запросе. Но кроме того, сначала в этой функции должны быть указаны типы для всех переменных, в виде строки, где тип переменной обозначается одной буквой. То есть букв в этой строке должно быть ровно столько, сколько дальше будет переменных. К счастью, можно особо не париться с типами и для всех переменных указывать тип "s".

И тогда никаких ошибок запроса уже никогда не будет. Не говоря уже о том что при любых других вариантах твой сайт поломает любой пятиклассник

Но по-хорошему для работы с БД в РНР лучше использовать PDO, Тем более что там колупаться с bind_param не нужно, а можно сразу отправить все данные в execute

Подключение
$host = '127.0.0.1';
$db   = 'test';
$user = 'root';
$pass = '';
$port = "3306";
$charset = 'utf8mb4';
$options = [
    \PDO::ATTR_ERRMODE            => \PDO::ERRMODE_EXCEPTION,
    \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
    \PDO::ATTR_EMULATE_PREPARES   => false,
];
$dsn = "mysql:host=$host;dbname=$db;charset=$charset;port=$port";
$pdo = new \PDO($dsn, $user, $pass, $options);
Здесь за информирование об ошибках отвечает параметр PDO::ERRMODE_EXCEPTION, а остальные просто для удобства/корректности.

Выполнение запроса
$sql = "INSERT INTO `events` (`title`, `discription`, `date`, `img`) VALUES (?,?,?,?)";
$stmt = $link->prepare($sql);
$stmt->execute([$title, $discription, $date, $path]);

Худший ответ:
Лучше создать класс базы данных и потом его использовать.
Инициализацию и запросы - решение FanatPHP.

Это и проще, и быстрее, и надёжнее, и правильнее.