#php #mysql #class #oop #constructor
#php #mysql #класс #ооп #конструктор
Вопрос:
Итак, вот случай:
У меня есть два класса = Пользователи и блоги
Класс Blogs расширяет класс Users
Конструкция класса Users выглядит примерно так:
public $users_id;
public $users_blogs_id;
public $users_first_name;
public $users_last_name;
/**
* Sets the object's properties using the values in the supplied array
*
* @param assoc The property values
*/
public function __construct($data=array()){
if(isset($data['users_id']))
{
$this->users_id= $data['users_id'];
}
if(isset($data['users_blogs_id']))
{
$this->users_blogs_id= $data['users_blogs_id'];
}
if(isset($data['users_first_name']))
{
$this->users_first_name = $data['users_first_name'];
}
if(isset($data['users_last_name']))
{
$this->users_last_name = $data['users_last_name'];
}
}
И конструктор класса Blogs выглядит следующим образом:
public $blogs_id;
public $blogs_title;
public $blogs_author;
/**
* Sets the object's properties using the values in the supplied array
*
* @param assoc The property values
*/
public function __construct($data=array()){
if(isset($data['blogs_id']))
{
$this->blogs_id= $data['blogs_id'];
}
if(isset($data['blogs_title']))
{
$this->blogs_title = $data['blogs_title'];
}
if(isset($data['blogs_author']))
{
$this->blogs_author = $data['blogs_author'];
}
}
Столбцы, из которых должны быть объединены таблицы, — это «users_blogs_id» из таблицы User и «blogs_id» из таблицы Blogs.
Мой оператор sql выглядит примерно так:
$sql = "SELECT * FROM users LEFT JOIN blogs ON users.users_blogs_id = blogs.blogs_id";
$data = Users::select_all($sql);
Теперь предполагается, что функция «выбрать все» создаст новый объект, который запустит конструктор и сохранит найденные значения в своих соответствующих свойствах, а затем вернет результаты обратно.
Проблема в том, что если я вызову Users Classes select, он запустит только конструктор Users и отправит мне только свойства класса Users с найденным результатом. Однако, если я вызову классы Blogs select, он вернет свойства blogs, а также свойства users, но только свойства blogs будут содержать найденные результаты, свойства users будут пустыми, поскольку конструктор blogs не включает набор кода, необходимый для установки свойств users с помощьюнайденный результат.
Things that I’ve tried:
Creating Multiple Queries
For example when I call the user select from the Users Class, I take the «users_blogs_id» columns value and then run another query that selects the blog from the Blogs Table Where «blogs_id = :users_blogs_id».
Copying part of the Blogs / Users Constructor Codes
So since part of the constructor codes are missing from the Blogs Class’s Constructor, I just copy that part of the code from the Users Class’s Constructor and paste it in the Blogs Class like this:
/**
* Sets the object's properties using the values in the supplied array
*
* @param assoc The property values
*/
public function __construct($data=array()){
if(isset($data['blogs_id']))
{
$this->blogs_id= $data['blogs_id'];
}
if(isset($data['blogs_title']))
{
$this->blogs_title = $data['blogs_title'];
}
if(isset($data['blogs_author']))
{
$this->blogs_author = $data['blogs_author'];
}
/*-----------------------From Users Class----------------------*/
if(isset($data['users_id']))
{
$this->users_id= $data['users_id'];
}
if(isset($data['users_blogs_id']))
{
$this->users_blogs_id= $data['users_blogs_id'];
}
if(isset($data['users_first_name']))
{
$this->users_first_name = $data['users_first_name'];
}
if(isset($data['users_last_name']))
{
$this->users_last_name = $data['users_last_name'];
}
}
This will set both the users class’s and blogs class’s properties with the found result from the select function but it just ends up with me repeating the codes which is something that I don’t want aswell.
Adding only the columns that are to be joined in the constructor
The columns that I wanna join in this case are the «users_blogs_id» from the Users Class with the «blogs_id» from the Blogs Class.
Since the Blogs Class is the child class, I add the «users_blogs_id» construct code from the Users Class to the Blogs Construct Code like this:
/**
* Sets the object's properties using the values in the supplied array
*
* @param assoc The property values
*/
public function __construct($data=array()){
if(isset($data['blogs_id']))
{
$this->blogs_id= $data['blogs_id'];
}
if(isset($data['blogs_title']))
{
$this->blogs_title = $data['blogs_title'];
}
if(isset($data['blogs_author']))
{
$this->blogs_author = $data['blogs_author'];
}
/*--------------------Column that I wanna join----------------------*/
if(isset($data['users_blogs_id']))
{
$this->users_blogs_id= $data['users_blogs_id'];
}
}
However this just ends up with me creating multiple sql queries which is something that I wanna avoid.
Using Traits (The wrong way)
So what I did was create a trait which has all the construct codes for all classes. Here’s an example:
trait ConstructFunctions{
public function __construct($data=array())
{
/*---------------Blogs Construct--------------------*/
if(isset($data['blogs_id']))
{
$this->blogs_id= $data['blogs_id'];
}
if(isset($data['blogs_title']))
{
$this->blogs_title = $data['blogs_title'];
}
if(isset($data['blogs_author']))
{
$this->blogs_author = $data['blogs_author'];
}
/*-----------------------Users Construct------------------------*/
if(isset($data['users_id']))
{
$this->users_id= $data['users_id'];
}
if(isset($data['users_blogs_id']))
{
$this->users_blogs_id= $data['users_blogs_id'];
}
if(isset($data['users_first_name']))
{
$this->users_first_name = $data['users_first_name'];
}
if(isset($data['users_last_name']))
{
$this->users_last_name = $data['users_last_name'];
}
}
}
Затем я просто вызываю признак, скажем, в классе Blogs следующим образом:
public $blogs_id;
public $blogs_title;
public $blogs_author;
/**
* Sets the object's properties using the values in the supplied array
*
* @param assoc The property values
*/
public function __construct($data=array()){
use ConstructFunctions;
}
Теперь этот способ сработал для меня лучше всего. Это избавило от повторения кодов и позволило мне передать один SQL-запрос. Однако проблема в том, что, по мнению моих коллег, это неправильная практика конструкторов, и они запретили мне использовать этот метод.
Моя цель
Для сохранения и получения всех значений свойств класса одним SQL-запросом с использованием объединений. Чтобы остановить повторение кодов в конструкторе или, по крайней мере, уменьшить его до некоторой степени. Чтобы не нарушать законы конструкторов.
Каждый ввод приветствуется. Спасибо. Дайте мне знать, если у вас есть какие-либо вопросы относительно моего вопроса.
Ответ №1:
Вы можете вызвать родительский конструктор :
// blog class
public function __construct($data=array())
{
/* your code to set properties in blog */
parent::__construct($data);
}
Но я бы посоветовал вам вместо этого использовать композицию вместо наследования и переосмыслить дизайн вашего класса, например, класс -> объект -> таблица :
class User // <---------------
{ // |
// some fields |
} // |
// |
class Blog // |
{ // |
// some fields |
// |
User $user; // ---------
}
Ответ №2:
Спасибо @Cid за решение моего вопроса. Я опубликую решение, которое я придумал, для всех, кому это нужно:
Класс Blogs имеет 2 простых изменения: дополнительное свойство и код для установки значения свойства
public $blogs_id;
public $blogs_title;
public $blogs_author;
//New Property
public $users;
/**
* Sets the object's properties using the values in the supplied array
*
* @param assoc The property values
*/
public function __construct($data=array()){
if(isset($data['blogs_id']))
{
$this->blogs_id= $data['blogs_id'];
}
if(isset($data['blogs_title']))
{
$this->blogs_title = $data['blogs_title'];
}
if(isset($data['blogs_author']))
{
$this->blogs_author = $data['blogs_author'];
}
//New property setting code
$this->users = new Users($data);
}
sql остается тем же, однако оператор select теперь вызывается из класса Blogs
$sql = "SELECT * FROM users LEFT JOIN blogs ON users.users_blogs_id = blogs.blogs_id";
$data = Blogs::select_all($sql);
Теперь он установит свойства класса Blogs с найденными значениями с помощью своего конструктора, а также создаст новый объект Users, который установит свойства класса Users с найденными значениями с помощью конструктора класса Users, сохранит его в свойстве «$ users», расположенном в классе Blogs, а затем отправит обратновсе блоги и свойства пользователей с соответствующими данными в переменной «$data».