У меня есть объект CRUD, и у меня есть два объекта, admin и post, которые расширяют объект CRUD. Я собираюсь проводить валидацию как на передней, так и на задней стороне, когда закончу, но в настоящее время я работаю над проверками серверной части. У объекта CRUD есть глобальные методы создания, обновления и проверки. Объект Post отлично переопределяет метод проверки и работает. Администратор переопределяет метод проверки и, похоже, не вызывает ни родителя, ни ребенка.
Пример ниже:
<?php
class CRUD {
protected function validate(){
$this->errors =[]
//no error checking here, but when I put any error checking here it doesnt
//fire on admin either.
return $this->errors;
}
public function create(){
$this->validate();
if (!empty($this->errors){return false}
//query which works on all classes.
}
}
class Admin extends CRUD{
protected function validate(){
$this->errors = [];
//a bunch of error checking functions that work for post class
return $this->errors;
}
public function create(){
$this->hashpassword(); //just sets $this->password to a hash
return parent::create();
}
}
class Post extends CRUD {
protected function validate() {
$this->errors =[];
//a bunch of functioning validations
return $this->errors;
}
}
?>
Независимо от того, запускаю ли я функцию как есть, я закомментирую функцию override create()
и использую унаследованную версию, которая не хеширует пароль, или я пытаюсь поместить функции проверки в родительский класс, ничто не заполняет $this->errors
для администратора. Он отлично работает для почтового класса. У меня вопрос: почему метод проверки не работает с классом Admin?
** Редактировать, копировать и вставлять фактические классы ** Класс CRUD:
<?php
class DatabaseObject {
static protected $db;
static protected $table_name;
static protected $db_columns = [];
public $errors = [];
public static function set_db($db){
self::$db = $db;
}
static public function find_by_sql($sql){
$result = self::$db->query($sql);
if (!$result) {
exit("Database Query Failed");
}
//convert results into objects
$object_array=[];
while($record = $result->fetch_assoc()){
$object_array[] = static::instantiate($record);
}
$result->free();
return $object_array;
}
static public function find_all(){
$sql = "SELECT * FROM " . static::$table_name;
return static::find_by_sql($sql);
}
static public function find_by_id($id){
$sql = "SELECT * FROM " . static::$table_name;
$sql .= " WHERE id='" . self::$db->escape_string($id) . "'";
$object_array = static::find_by_sql($sql);
if (!$object_array){
return false;
}
return array_shift($object_array);
}
static protected function instantiate($record){
$object = new static;
//could assign things by hand but its faster and easier to do it dunamically
//plus it's reusable.
foreach($record as $property => $value){
if (property_exists($object, $property)){
$object->$property = $value;
}
}
return $object;
}
protected function validate() {
$this->errors = [];
$this->errors[] = "bar";
return $this->errors;
}
protected function create(){
$this->validate();
if (!empty($errors))
{return false;}
$attributes = $this->sanitize_attributes();
$sql = "INSERT INTO " . static::$table_name . " (";
$sql .= join(',', array_keys($attributes));
$sql .= ") VALUES ('";
$sql .= join("', '", array_values($attributes));
$sql .= "')";
$result = self::$db->query($sql);
if ($result){
$this->id = static::$db->insert_id;
}
return $result;
}
//attributes are the properties which have the db columns excluding id
protected function update(){
$this->validate();
if (!empty($errors)){return false;}
$attributes = $this->sanitize_attributes();
$attribute_pairs = [];
foreach($attributes as $key => $value) {
$attribute_pairs[] = "{$key}='{$value}'";
}
$sql = "UPDATE " . self::$db->escape_string(static::$table_name) . " SET ";
$sql .= join(', ', $attribute_pairs);
$sql .= " WHERE id='" . self::$db->escape_string($this->id) . "' ";
$sql .= "LIMIT 1";
$result = self::$db->query($sql);
return $result;
}
public function save(){
if (isset($this->id)){
return $this->update();
} else {
return $this->create();
}
}
public function merge_attributes($args){
foreach($args as $key => $value) {
if (property_exists($this, $key) && !is_null($value)){
$this->$key = $value;
}
}
}
public function attributes() {
$attributes = [];
foreach(static::$db_columns as $column) {
if ($column == 'id'){ continue; }
$attributes[$column] = $this->$column;
}
return $attributes;
}
protected function sanitize_attributes() {
$attributes = $this->attributes();
$sanitized =[];
foreach($attributes as $key => $value){
$sanitized[$key] = self::$db->escape_string($value);
}
return $sanitized;
}
public function delete(){
$sql = "DELETE FROM " . self::$db->escape_string(static::$table_name) . " ";
$sql .= "WHERE id='";
$sql .= self::$db->escape_string($this->id);
$sql .= "' LIMIT 1";
$result = self::$db->query($sql);
return $result;
//after deleting the instance is still around
//which is useful so you can say $this->poop was deleted
//but we cant call CRUD functions
}
}
?>
Класс администратора:
<?php
class Admin extends DatabaseObject {
static protected $table_name = 'admins';
static protected $db_columns = ['id', 'first_name', 'last_name', 'email', 'username', 'hashed_password'];
public $id;
public $first_name;
public $last_name;
public $email;
public $username;
public $password;
public $confirm_password;
protected $hashed_password;
protected $password_required = true;
public function __construct($args = []){
$this->first_name = $args['first_name'] ?? '';
$this->last_name = $args['last_name'] ?? '';
$this->email = $args['email'] ?? '';
$this->username = $args['username'] ?? '';
$this->password = $args['password'] ?? '';
$this->confirm_password = $args['confirm_password'] ?? '';
}
public function label() {
return $this->username . " Name: " . $this->first_name . " " . $this->last_name;
}
private function hash_password(){
$this->hashed_password = password_hash($this->password, PASSWORD_BCRYPT);
}
protected function validate() {
$this->errors = parent::validate();
$this->errors[] = "foo";
if (is_blank($this->first_name)) {
$this->errors[] = "First name cannot be blank.";
} elseif (!has_length($this->first_name, array('min' => 2, 'max' => 255))) {
$this->errors[] = "First name must be between 2 and 255 characters.";
}
if (is_blank($this->last_name)) {
$this->errors[] = "Last name cannot be blank.";
} elseif (!has_length($this->last_name, array('min' => 2, 'max' => 255))) {
$this->errors[] = "Last name must be between 2 and 255 characters.";
}
if (is_blank($this->email)) {
$this->errors[] = "Email cannot be blank.";
} elseif (!has_length($this->email, array('max' => 255))) {
$this->errors[] = "Last name must be less than 255 characters.";
} elseif (!has_valid_email_format($this->email)) {
$this->errors[] = "Email must be a valid format.";
}
if (is_blank($this->username)) {
$this->errors[] = "Username cannot be blank.";
} elseif (!has_length($this->username, array('min' => 8, 'max' => 255))) {
$this->errors[] = "Username must be between 8 and 255 characters.";
}
if (is_blank($this->password)) {
$this->errors[] = "Password cannot be blank.";
} elseif (!has_length($this->password, array('min' => 12))) {
$this->errors[] = "Password must contain 12 or more characters";
} elseif (!preg_match('/[A-Z]/', $this->password)) {
$this->errors[] = "Password must contain at least 1 uppercase letter";
} elseif (!preg_match('/[a-z]/', $this->password)) {
$this->errors[] = "Password must contain at least 1 lowercase letter";
} elseif (!preg_match('/[0-9]/', $this->password)) {
$this->errors[] = "Password must contain at least 1 number";
} elseif (!preg_match('/[^A-Za-z0-9\s]/', $this->password)) {
$this->errors[] = "Password must contain at least 1 symbol";
}
if (is_blank($this->confirm_password)) {
$this->errors[] = "Confirm password cannot be blank.";
} elseif ($this->password !== $this->confirm_password) {
$this->errors[] = "Password and confirm password must match.";
}
return $this->errors;
}
protected function create() {
$this->hash_password();
$result = parent::create();
return $result;
}
protected function update(){
if ($this->password != ''){
$this->hash_password();
} else {
$this->password_required = false;
}
$result = parent::update();
return $result;
}
}
?>
Извините за это, я отредактировал, чтобы включить отступы, и я забыл напечатать, что я расширил CRUD.
protected function validate()
возвращает ничего такого в Admin
.
Мне снова очень жаль. Я напечатал это вместо того, чтобы скопировать вставку, и я двигался так быстро, что забыл вставить ответ.
Пожалуйста, проверьте свой код дважды и укажите код, как вы проверяете, что ничего не возвращается. Люди здесь 24/7.
Снова извините. Я просто был в бешенстве и сбит с толку. Я не хотел копировать и вставлять весь свой код, потому что многие из них неуместны. Я должен был быть более осторожным. Я прошу прощения.
Прежде чем вы сможете установить ошибки $ this->, вам необходимо добавить ошибки как свойство в класс CRUD или Admin.
В противном случае будет создано общедоступное свойство.
Разве общественная собственность не была бы именно тем, что я хочу? Я добавил общедоступные ошибки $ = []; в CRUD, но он все еще не работает.
Если вы хотите, чтобы был вызван родительский метод validate
, вы должны включить parent::validate();
в свой код. Судя по предоставленному вами коду, ваш класс Admin будет выглядеть примерно так:
class Admin extends CRUD{
protected function validate(){
$this->errors = parent::validate();
//a bunch of error checking functions that work for post class
return $this->errors;
}
public function create(){
$this->hashpassword(); //just sets $this->password to a hash
return parent::create();
}
}
Причина, по которой вы назначаете результат parent::validate()
$this->errors
, заключается в том, что метод проверки сбрасывает массив $this->errors
, тем самым удаляя все ошибки.
родительский create () вызывает $ this-> validate (); вам нужно вызывать родителя каждый раз, когда вы переопределяете ребенка?
Разве я не хочу, чтобы проверка ошибок в админке начиналась пустой, чтобы сообщалось только об ошибках администратора?
Да, вам нужно делать это каждый раз, если вы хотите вызвать родителя из переопределенного метода. Вот как работает наследование, оно переопределяет метод, поэтому вы можете (потенциально) изменить функциональность, не вызывая родительский метод.
Да, вы можете начать с пустого. Однако в вашем коде, когда вы вызываете родительскую реализацию validate
, она снова сбрасывает массив errors
, тем самым удаляя ошибки, которые вы установили ранее. Когда вы называете это так, вы предотвращаете это.
Я добавил это в функцию проверки, и она все еще проходит мои проверки.
В этом есть смысл, но когда я запускаю create () в Admin, будь то унаследованное создание или переопределение, которое я написал, он передает все проверки от родителя и потомка. Когда я запускаю create () из сообщения, он отлично работает.
Мне нужно больше контекста, чтобы дать вам ответ на этот вопрос. Может, что-то не так в самой валидации? Что происходит, когда вы намеренно добавляете ошибку, она все равно проходит?
Я специально добавил $ this-> errors [] = "foo"; для родительской проверки и $ this-> errors [] = "bar" для проверки администратором, и они не прошли и не остановили добавление записи в базу данных.
Кроме того, я добавил div на страницу шоу и добавил текст, чтобы убедиться, что это не проблема кеширования. И я добавил родительскую проверку к сообщению, и foo проходит как ошибка и останавливает добавление записи в базу данных.
Мне нужно увидеть больше кода, чтобы ответить на вашу проблему.
Могу ли я скопировать и вставить сюда админку и объект crud, или это уже слишком?
Я регистрирую учетную запись сейчас. Я также вставил классы CRUD и Admin в свой исходный пост.
Вы знаете о отступ?