Я создал этот класс, который выбирает все данные поста из базы данных.
class Post {
private $id;
protected $conn;
public $data;
function __construct(\mysqli $conn) {
$this->conn = $conn;
}
public function getId() {
return $this->id;
}
public function getConnection() {
return $this->conn;
}
public function getPost() {
$query1 = $this->getConnection()->query("SELECT * FROM posts WHERE id=" . $this->id);
if ($query1->num_rows == 1) {
$this->data = $query1->fetch_object();
return $this->data;
}
}
public function setId($id) {
$this->id = (int)$id;
}
}
Наряду с постом, мне также нужно получить все данные пользователя, создавшего пост. У меня есть три способа сделать это:
1) Вызовом класса User внутри класса Post.
public function getPost() {
$query1 = $this->getConnection()->query("SELECT * FROM posts WHERE id=" . $this->id);
if ($query1->num_rows == 1) {
$this->data = $query1->fetch_object();
// Initiating User class
$user = new User($this->getConnection());
$user->setUserId($this->data->user_id);
$this->data->user = $user->getUserInfo();
return $this->data;
}
}
2) Расширяя класс Post классом User.
class Post extends User {
....
Затем вызов методов из класса User
public function getPost() {
$query1 = $this->getConnection()->query("SELECT * FROM posts WHERE id=" . $this->id);
if ($query1->num_rows == 1) {
$this->data = $query1->fetch_object();
// Calling methods from the User class
$this->setUserId($this->data->user_id);
$this->data->user = $this->getUserInfo();
return $this->data;
}
}
3) Создавая черту User и используя ее в классе Post.
class Post {
use UserTrait;
....
Затем вызов методов из черты пользователя
public function getPost() {
$query1 = $this->getConnection()->query("SELECT * FROM posts WHERE id=" . $this->id);
if ($query1->num_rows == 1) {
$this->data = $query1->fetch_object();
// Calling methods from the User trait
$this->setUserId($this->data->user_id);
$this->data->user = $this->getUserInfo();
return $this->data;
}
}
Между этими тремя, какой из них является лучшим подходом с точки зрения внедрения зависимостей, производительности и чистоты кода?
Этот вопрос может оказаться в аду, потому что вы запрашиваете мнение, но я добавлю два цента.
Вы в основном строите свой собственный базовый ORM. В той ORM вы имеете дело с сущностями. Разные сущности должны обрабатываться разными классами (моделями), и между базовой таблицей БД и моделью должна быть эквивалентность 1: 1.
Есть отношения между вашими сущностями. У сущности Yous Post есть автор, который должен быть экземпляром сущности User. Однако вы бы не сказали, что связь между таблицей записей и таблицей пользователей означает, что они могут быть представлены одной и той же Моделью или разными разновидностями родительской Модели.
Если бы вы использовали полный ORM (Doctrine, Propel, RedbeanPHP), вы увидите, что такое отношение, как автор сообщения, означает, что при использовании таких методов, как getById()
(в твоем случае getPost()
) по умолчанию извлеченная сущность Post будет обрабатывать каждую зависимую сущность.
В вашем случае вместо того, чтобы иметь $this->data->user_id
ORM предложит вам вложенный $this->data->user
объект, чтобы вам не пришлось иметь дело с этим самостоятельно.
Итак, если вы считаете, что слишком рано использовать ORM, первый подход легче поддерживать и переносить, когда придет время.
Несвязанное мнение
На данный момент, чтобы получить информацию о посте, вам нужно сделать
$post = new Post($conn);
$post->setId($postid);
$postdata = $post->getPost();
Если вы изменили конструктор и добавили метод getById (),
function __construct(\mysqli $conn) {
$this->conn = $conn;
return $this;
}
public function getById($id) {
$this->setId($id);
return $this->getPost();
}
вместо этого вы можете получить данные поста в одну строку
$postdata=(new Post($conn))->getById($postid);
Все зависит от того, что вы собираетесь продолжать делать. С расширенным классом было бы лучше иметь дело, если вы собираетесь использовать постоянные методы других классов. Если вам нужна только часть другого класса, просто вызовите класс и его метод.
ВНИМАНИЕ: расширенный класс ведет себя как один класс. Здесь может быть много коллизий, если у вас одинаковые имена методов и функций.
Я думаю, что это зависит от других аспектов вашего кода. Лично я бы просто расширил класс User, так как не думаю, что использование черт необходимо в данном конкретном случае.
Здесь есть полезная статья об использовании черт в PHP —
Использование черт в PHP 5.4