za4me
@za4me
Человек

Правильно ли реализовал подключение к БД?

Добрый день, делаю тестовый сайт на php с использованием mvc, по этому топику. Но в нем не реализовано подключение к бд.

Каким образом я реализовал:

В core/model.php, создал метод db содержащий подключение к БД.
class Model
	{
		static function db()
		{
			define('HOST', 'localhost');
			define('USER', 'blog');
			define('PASS', '12345');
			define('DB', 'blog');

			$db = new mysqli(HOST, USER, PASS, DB);
			if ($db->connect_errno) {
				echo "Не удалось подключиться к MySQL: {$db->connect_error}";
			}
			return $db;
		}

		public function get_data()
		{}
	}

Далее в классе наследнике составляю запрос
class Model_Portfolio extends Model
	{
		public function get_data()
		{
			$link = self::db();
			$query = "SELECT * FROM blog ORDER BY id DESC";
			$result = $link->query($query);
			while ($row = $result->fetch_assoc()) {
				$articles[] = $row;
			}
			$link->close();
			return $articles;
		}
	}

В контроллере соединяю модель и шаблон
class Controller_Portfolio extends Controller
	{
		function __construct()
		{
			$this->model = new Model_Portfolio;
			$this->view = new View;
		}

		function action_index()
		{
			$data = $this->model->get_data();
			$this->view->generate('portfolio_view.php', 'template_view.php', $data);
		}
	}


Ну, а на странице вывожу его простым циклом.

Насколько правилен такой подход, и/или как его улучшить, может быть я что-то упустил?
Всем спасибо за советы.
  • Вопрос задан
  • 542 просмотра
Пригласить эксперта
Ответы на вопрос 2
@xfg
echo "Не удалось подключиться к MySQL: {$db->connect_error}";

В таких случаях нужно кидать эксепшн. Нет подключения к бд - нет смысла выполнять программу, нужно умирать. А если есть смысл, то тогда отлавливать брошенный эксепшн на других уровнях и как-то обрабатывать эту ситуацию.

Зашивать подключение в модель - плохо. Лучше для этого создать отдельный класс Connection. Вместо mysqli лучше использовать PDO, не завязываться на конкретную базу.

Вместо сырых SQL запросов лучше взять готовый DAO класс или написать свой, чтобы не зависеть от синтаксиса SQL запросов конкретной базы.

Закрывать соединение с бд в модели - плохо. Закрывать соединение с бд лучше на уровне приложения, после того, как отработал экшен контроллера.

Вообще стоило бы почитать про GRASP и SOLID. Наследование не всегда хорошо, иногда лучше использовать композицию и зависеть от абстракций, а не от конкретных реализаций. Тогда будет возможность полиморфно заменять одну реализацию на другую, не ломая OCP из SOLID.

Посмотрите лучше любой популярный фреймворк, чтобы понять как и что примерно работает.
Ответ написан
@kirill_danshin
PHP/Go разработчик, системный администратор
Я бы порекомендовал не хранить данные для подключения к базе в константах. Я бы написал это так:

class Model
  {
    private static $db_creds = [
        'user' => 'blog',
        'host' => 'localhost',
        'pass' => '12345',
        'db'    => 'blog'
    ];

    static function db()
    {
      // закешируем соединение, зачем каждый вызов создавать новое?
      static $db;
      if (is_null($db)) {
          $db = new mysqli(
              self::$db_creds['host'], 
              self::$db_creds['user'], 
              self::$db_creds['pass'], 
              self::$db_creds['db']
          );
          if ($db->connect_errno) {
              echo "Не удалось подключиться к MySQL: {$db->connect_error}";
              // в следующий вызов попробуем еще раз
              $db = null;
          }
      }
      return $db;
    }

    public function get_data()
    {}
  }


И посоветовал бы использовать исключения для обработки ошибок. Их не нужно показывать пользователю, лучше их обработать, например, показать закешированную версию, перенаправить на другую страницу, показать красивое уведомление о 500 и т.д.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы