Вместо этого попробуйте заменить ваш код следующим:
the_title( '<h1 class="product_title entry-title">', '</h1>' );
$terms = wp_get_post_terms( get_the_id(), 'product_cat' );
$term = reset($terms);
echo $term->name;
Это должно сработать.
Yes, I think your User class is doing too much.
Split some of the group-related functions into a Group class, and the module-related functions into a Module class. Or maybe split permissions into its own set of classes.
Its hard to tell from method names alone. One heuristic I use to break a class up is to look at the state variables. Are there pieces of state that tend to be used together? Can they be broken out into a separate class?
Будет полезно, если вы сможете описать, как ведет себя ваш объект Пользователь
, с кем все это взаимодействует, какова его среда и т. Д.
Полагаю, я мог бы поставить связанные с разрешениями методы в некотором классе разрешений [...]
Да, вы можете взглянуть на дизайн, основанный на политике.
Я также хотел бы предложить вам удалить фиксированное состояние пользователя
т.е. адрес электронной почты / имя и т. Д. И поместите его в отдельный класс.
Насколько сложно теперь добавить новые функции или сохранить существующие функции в вашем приложении? Если у вас нет проблем в этом отношении, то вы, вероятно, в порядке, сохраняя вещи такими, какие они есть (по крайней мере, на некоторое время).
Да, у вашего класса User есть некоторые перекрывающиеся обязанности, которые потенциально могут быть преобразованы в Система контроля доступа на основе ролей .
Суть в следующем: вам действительно она понадобится ?
Если у вас уже есть исполняемый код, то рефакторинг на мелкие кусочки. Если нет, я бы посмотрел на следующее:
class User {
String username
String name
String emailAddress
Boolean active
Integer permission # A bitmask of the statics in the Permission class
}
class Group {
String name
}
class UserGroupMapping {
User user
Group group
Boolean administrator
}
class Permission {
static IS_ROOT = 1
static IS_SITE_ADMIN = 2
}
class Session {
User user
Boolean logged_in
}
Остальное действительно принадлежит классу обслуживания:
class SecurityService {
статическая публичная функция hasModulePermission ($ пользователь, $ модуль, $ запись, $ разрешение) {...}
статическая публичная функция hasGroupPermission ($ пользователь, $ группа, $ разрешение) {...}
статическая публичная функция hasContentPermission ($ user, $ record, $missions) {...}
статическая публичная функция hasModulePermission ($ пользователь, $ модуль, $ запись, $ разрешение) {...}
}
Я бы разделил аспект "пользователь" и " группа «Управленческий аспект занятия».
I would at least remove the setCanLogIn($canLogIn)
function. This should really be determined internally within the class based on if the user has supplied the correct credentials and has been authenticated.
Depending on how large this project is, or whether this is part of a framework will determine if more abstraction is needed.
Это выглядит достаточно правдоподобно. Конечно, я не знаю приложения. Я думаю, что имеет смысл выделить класс Permissions.
В идеале, тогда вы должны подумать о том, что значит иметь класс Permissions - что он знает, каковы его реальные действия? Кроме того, поскольку «разрешения» множественного числа, вы можете задаться вопросом, действительно ли вы хотите набор отдельных объектов разрешений, но действительно ли они являются доступными для простого логического значения, которое может быть излишним.
Похоже, вам нужны отдельные объекты ACL и Role от объекта User.
http: //en.wikipedia .org / wiki / Role-based_access_control
Вы также можете увидеть , как это делается в ZF .
Для удобства чтения вы можете использовать __ get ()
и __ set ()
вместо:
public function setName($value) { ... }
public function setEmailAddress($value) { ... }
public function setUsername($value) { ... }
public function getName() { ... }
public function getEmailAddress() { ... }
public function getUsername() { ... }
Пока методы класса возвращают данные экземпляра или изменяют только внутреннее состояние, в классе нет ничего плохого
Но, например, если метод canLogIn () ищет какую-то внешнюю службу (репозиторий, служба членства и т. Д.), Возникает проблема простоты и тестируемости. Если это так, у вас должен быть какой-то класс обслуживания и эти методы. Например,
new SomeFactory().GetUserService().canLogIn(user);
Это не так уж плохо, но я думаю, что ваши механики разрешений могут использовать факторинг. Это тот случай, когда явно требуется агрегация, а не наследование. Если есть вероятность того, что нетривиальная контактная информация будет связана с пользователем, вы также можете выделить адрес электронной почты, возможно, в удостоверение, в которое при необходимости может быть загружена другая контактная информация.
В общем, я мог бы рекомендовать думать о своем пользователе как о центральном пункте для агрегации и составления (а не наследования) субъединиц функциональности - подхода, который позволяет достичь статуса модного слова в разработке игр под рубрикой «система сущностей».
(event.start BETWEEN week.start AND week.end)
OR
(week.start BETWEEN event.start AND event.end)
Проще говоря, либо неделя начинается во время события, либо событие начинается в течение недели.
Давайте проверьте его:
Событие начинается и заканчивается в течение недели.
Событие начинается в течение недели.
Событие начинается до недели, но заканчивается в течение недели.
Неделя начинается во время события.
Событие начинается в течение недели, но заканчивается после недели.
Событие начинается в течение недели.
Событие начинается до недели, а также заканчивается после недели.
Неделя начинается во время события.
Обратите внимание, что МЕЖДУ
в вышеприведенных выражениях используется просто для краткости.
Строгое выражение выглядит следующим образом:
(event.start >= week.start AND event.start < week.end)
OR
(week.start >= event.start AND week.start < event.end)
, при условии, что week.end
является неделей . начало + ИНТЕРВАЛ 7 ДНЯ
.
I. е. если у вас неделя начинается вс, 0:00:00
,
Интерфейс System.IEquatable используется для сравнения двух экземпляров объекта на равенство. Объекты сравниваются на основе логики, реализованной в классе. Сравнение приводит к логическому значению, указывающему, отличаются ли объекты. Это отличается от интерфейса System.IComparable, который возвращает целое число, указывающее, как отличаются значения объекта.
Интерфейс IEquatable объявляет два метода, которые должны быть переопределены. Метод Equals содержит реализацию, которая выполняет фактическое сравнение и возвращает true, если значения объекта равны, или false, если они не равны. Метод GetHashCode должен возвращать уникальное хеш-значение, которое можно использовать для уникальной идентификации идентичных объектов, которые содержат разные значения. Тип используемого алгоритма хеширования зависит от реализации.
- Вы должны реализовать IEquatable для своих объектов, чтобы обрабатывать вероятность того, что они будут храниться в массиве или универсальной коллекции.
- Если вы реализуете IEquatable, вам также следует переопределить реализации базового класса Object .Equals (Object) и GetHashCode, чтобы их поведение соответствовало поведению метода IEquatable.Equals
Рекомендации по переопределению Equals () и Operator == (Руководство по программированию в C #)
- x.Equals (x) возвращает true . [1 269] х. Equals (y) возвращает то же значение, что и y.Equals (x)
- , если (x.Equals (y) && y.Equals (z)) возвращает true, тогда x.Equals (z) возвращает true.
- Последовательные вызовы х. Equals (y) возвращает одно и то же значение, если объекты, на которые ссылаются x и y, не изменены.
- x. Equals (null) возвращает false (только для типов значений, не допускающих значения NULL). Для получения дополнительной информации см. Nullable Types (Руководство по программированию в C #) .)
- Новая реализация Equals не должна генерировать исключения.
- Рекомендуется, чтобы любой класс, который переопределяет Equals, также переопределял Object.GetHashCode.
- Рекомендуется, чтобы в дополнение к реализации Equals (объект), любой класс также реализовывал Equals (тип) для своего собственного типа, чтобы повысить производительность.
По умолчанию оператор == проверяет равенство ссылок, определяя, указывают ли две ссылки на один и тот же объект. Следовательно, ссылочные типы не должны реализовывать оператор == для получения этой функциональности. Когда тип является неизменяемым, то есть данные, содержащиеся в экземпляре, не могут быть изменены, может быть полезен оператор перегрузки == для сравнения равенства значений вместо ссылочного равенства, поскольку в качестве неизменяемых объектов они могут рассматриваться как длинные так как они имеют одинаковое значение. Не рекомендуется переопределять оператор == в неизменяемых типах.
- Перегруженный оператор == реализации не должны вызывать исключения.
- Любой тип, перегружающий оператор ==, также должен перегружать оператор! =.
- Для предопределенных типов значений Оператор равенства (==) возвращает true, если значения его операндов равны, в противном случае - false.
- Для ссылочных типов, отличных от строки, == возвращает true, если два его операнда ссылаются на один и тот же объект.
- Для строкового типа == сравнивает значения строк.
- При проверке на нулевое значение с использованием == сравнений в переопределениях вашего оператора == убедитесь, что вы используете оператор базового класса объектов. Если вы этого не сделаете, произойдет бесконечная рекурсия, приводящая к переполнению стека.
Если ваш язык программирования поддерживает перегрузку операторов и если вы решите перегрузить оператор равенства для данного типа, то Тип должен переопределить метод Equals. Такие реализации метода Equals должны возвращать те же результаты, что и оператор равенства
Следующие рекомендации предназначены для реализации типа значения :
- Рассмотрите возможность переопределения Equals для повышения производительности по сравнению с тем, который предоставляется по умолчанию реализация Equals для ValueType.
- Если вы переопределяете Equals и язык поддерживает перегрузку операторов, вы должны перегрузить оператор равенства для вашего типа значения.
Следующие рекомендации касаются реализации ссылочного типа :
- Рассмотрите возможность переопределения Equals для ссылочного типа, если семантика типа основана на том факте, что тип представляет некоторое значение (я).
- Большинство ссылочных типов не должны перегружать оператор равенства, даже если они переопределяют Equals. Однако,
.MemberOfGroup(GroupID) .AdminSite .Root .AdminGroup(GroupID)
Предлагаем заменить их функциями получения / установки разрешений, которые обрабатывают экземпляр TUserPermissions:
public function hasModulePermission($moduleId, $recordId, $permissionCode) public function hasGroupPermission($groupId, $permissionCode) public function hasContentPermission($recordId, $permissionCode) public function hasModulePermission($moduleId, $recordId, $permissionCode) public function canLogIn() public function setCanLogIn($canLogIn)
TUserPermissions будет иметь:
.ModulePermitted(ModuleID,RecordID,PermCode) .GroupPermitted(GroupID,PermCode) .ContentPermitted(RecordID,PermCode) .ModulePermitted(ModuleID,RecordID,PermCode) .CanLogIn
I would consider creating a Permissions class and making that a member of the User class.