Как стать автором
Поиск
Написать публикацию
Обновить

Комментарии 58

НЛО прилетело и опубликовало эту надпись здесь
Зенд скромнее, он не говорит, почему ты ему не нравишься и что лишнее в тебе!
НЛО прилетело и опубликовало эту надпись здесь
Желательно, чтобы это мнение хоть чуточку было обосновано. Основное приимущество зенда, что почти любой компонент можно использовать отдельно. И почти любой компонент можно заменить сторонним.
НЛО прилетело и опубликовало эту надпись здесь
Сколько раз смотрел на зенд, приходит в голову мысль, что без него можно все написать проще и логичней.
Надо было не смотреть, а писать на нем ;)
НЛО прилетело и опубликовало эту надпись здесь
Главный мусор — это Zend_Application и вся архитектура, которую он навязывает. А по — отдельности да, вполне независимые удобные либы.
никто не тянет Zend_Application, он даже не обязателен, это просто способ запустить приложение одной строкой
Это имхо и является одной из двух главных проблем фреймворка — излишне скурпулезная декомпозиция, какая-нибудь жалкая пара общих операторов — уже дополнительный базовый класс куда они вынесены, а там один класс агрегирует другой класс, оба тянут за собой цепочку наследований родительских классов и интерфейсов, в итоге каждый пук подключает 20-30 файлов с большим количеством балластного кода, на чем конкретно буксует интерпретатор. И казалось-бы — есть-же интерфейсы, можно написать реализацию самому! Но тут вылезает вторая проблема, довольно-таки известный антипаттерн — bloated interface, половина интерфейсов зенда — это хреновы миллионы однотипных методов, с псевдополиморфизмом методов (setOptions(array $options), setConfig(Zend_Config $options)), аксессорами (__get => getOption, __set => setOption) и т.д. и т.п., что выливается в человекогода их реализации.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Спасибо. Поправил
Т.н. простой пример аутентификации кроме того еще является примером объединения логики управления (контроллер) и бизнес-логики (модель), что противоречит принципу MVC. Я для себя в конце концов пришел к такому решению:
class Model_User extends Skaya_Model_Abstract implements Zend_Auth_Adapter_Interface {

	const USER_STATE_ACTIVE = 'active';
	const USER_STATE_DEACTIVE = 'deactive';

	const USER_ROLE_GUEST = 'guest';
	const USER_ROLE_USER = 'user';
	const USER_ROLE_ADMIN = 'admin';

	public function getRole() {
		if (empty($this->_data['role'])) {
			$this->_data['role'] = self::USER_ROLE_GUEST;
		}
		return $this->_data['role'];
	}

	public function authenticate() {
		/**
		 * @var Model_User $user
		 */
		$user = $this->getMapper()->getUserByEmail($this->email);
		if (is_array($user) &&
			!empty($user) &&
			!empty($this->email) && $user['email'] == $this->email &&
			$user['password'] == md5($this->password) &&
			$user['status'] == self::USER_STATE_ACTIVE
		) {
			if (empty($user['role'])) {
				$user['role'] = self::USER_ROLE_USER;
			}
			$this->populate($user);
			unset($this->password);
			$result = new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $this);
		}
		else {
			$code = Zend_Auth_Result::FAILURE;
			if (!is_array($user) ||
				empty($user) ||
				$user['username'] != $this->email
			) {
				$code = Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND;
			}
			elseif ($user['password'] != $this->password) {
				$code = Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID;
			}
			$result = new Zend_Auth_Result($code, null, array('loginFailed' => 'Incorrect Email & Password'));
		}
		return $result;
	}
}

Код контроллера:
class Admin_UsersController extends Zend_Controller_Action {

	/**
	 * @var Model_User
	 */
	protected $_user;

	public function loginAction() {
		$request = $this->getRequest();

		$loginForm = new Admin_Form_Login(array(
			'name' => 'loginForm',
			'action' => $this->_helper->url('login')
		));

		if ($request->isPost()) {
			if ($loginForm->isValid($request->getPost())) {
				$user = Service_User::create(array(
					'email' => $loginForm->email->getValue(),
					'password' => $loginForm->password->getValue()
				));
				$auth = Zend_Auth::getInstance();
				$authResult = $auth->authenticate($user);
				if ($authResult->isValid()) {
					$user->lastLoginDate = time();
					$user->save();
				}
			}
		}
		$this->view->loginForm = $loginForm->prepareDecorators();
	}

	public function logoutAction() {
		Zend_Auth::getInstance()->clearIdentity();
		$this->_redirect('/admin');
	}
}
Да, действительно происходит некоторое смешивание и это не очень хорошо. Особенно мне не нравится что в моем случае возникает дублирование кода, если вход нужно выполнять в нескольких местах (например автоматически после регистрации). Однако, для небольших проектов мне кажется это не критично.
Второй год все проекты пишу с использованием Zend. До этого пробовал разные framework'и. Zend понравился больше всего, хотя ему не хватает некоторых сторон Kohana и Yii. А в остальном — наиболее универсальный и мощный.

Спасибо за статью, до сих пор нормально не смог разобраться с acl, для меня это тёмный лес. Надеюсь, ваша статья поможет.
Данная статья не описывает в достаточном объеме Zend_Acl. Наверное мне стоит написать отдельный пост и рассмотреть какой-либо расширенный пример использования Acl.
Ок, надеюсь что это случится. Просто хочется не тупой теории и элементарных примеров, как в мануалах, где даже не описывается как потом применять заданные роли, а чего-то более серьёзного, с более-менее приличными примерами. Буду очень благодарен, да и не я только, думаю, если такой топик будет
За два года, при желании, могли бы и поискать, Acl довольно таки популярная тема, по нему уйма статей.
Второй год пишете проекты на Zend и не можете разобраться с Zend_Acl? Боюсь смотреть в ваш код.
Сам вот иногда думаю: блин, это ж по-любому проще можно сделать.
НЛО прилетело и опубликовало эту надпись здесь
ZF очень мощный и гибкий фреймворк, единственным его недостатком является высокой порог вхождения. Именно поэтому я и начал писать этот цикл, чтобы облегчить старт для тех кто только начал изучать фреймворк. Спасибо, за отзыв!
Да не сказал бы что высокий порог вхождения — он довольно прост и логичен, вполне в духе PHP.

Не сочтите за флуд, но судя по голосованию за комменты — многих читателей топика в детстве насиловали ZF`ом.

>Главный мусор — это Zend_Application и вся архитектура, которую он навязывает. А по — >отдельности да, вполне независимые удобные либы.

А обосновать? И чем кстати архитектура то плоха?
НЛО прилетело и опубликовало эту надпись здесь
Ок, давайте пруффлинк на аналогичный по потенциальной функциональности код написанный без фреймворка.

Конечно, примеры сами по себе, вырванные из контекста, выглядят как реактивный двигатель на велосипеде — но ZF великолепен в сложных проектах, это многого стоит. К тому же это один из немногих фреймворков, который чуть ли не силой приучает к написанию Хорошего кода.

И тащемта никто не мешает же под конкретные нужды расширить функциональность стандартных классов…
НЛО прилетело и опубликовало эту надпись здесь
> По текущему функционалу, без фреймворка получится десяток строк.

Ок. Ловим на слове: 10-ки строк — Acl + Auth.
НЛО прилетело и опубликовало эту надпись здесь
За 10 строк — 1$ устроит?
Но только функционал должен полностью поглощать систему контроля доступа для сайтов средней сложности.
А ловить на слове есть смысл — вы же не хотите быть голословным?
НЛО прилетело и опубликовало эту надпись здесь
Увы, но ваши комментарии абсолютно не соответствуют теме топика. Вот если бы он назывался: «Использовать ZF или нет»…
НЛО прилетело и опубликовало эту надпись здесь
Давайте посмотрим на первый ваш комментарий:
>> Вот именно поэтому мне и не нравится zend — куча лишнего кода…
НЛО прилетело и опубликовало эту надпись здесь
Не вижу причин обсуждать это в данном посте, как я уже утверждал ранее:
>> назывался: «Использовать ZF или нет»…
Наш разговор зацикливается, по-этому предлагаю завершить его
НЛО прилетело и опубликовало эту надпись здесь
Давайте не «на словах» и без лишних запросов к базе при каждом открытии любой страницы.
Жду код…
НЛО прилетело и опубликовало эту надпись здесь
Понятно :D
Да такой функционал на каком-нибудь Yii вообще сам генериться, но как было замечено ниже ZF великолепен в сложных проектах.
Такой функционал нигде не генерится, ручками надо указывать куда можно ходить а куда нельзя
простите, шаблон данного функционала))) конкретику понятное дело, что прописывает программист.
Ну не скажите. В Symfony2 такое делается парой строк в конфиге и декларативным объявлянием перед методом контроллера
/**
 * @Security("has_role('ROLE_ADMIN')")
*/
Иногда необходимо хранить в сторидже дополнительную информацию, которая может хранится в других талицах, например информацию о компании пользователя. Можно ли при стандартной аутентификации сделать запрос по нескольким таблицам? Или придется делать второй запрос и добавлять информацию в сторидж?

Для себя нашел более простой способ аутентификации — stackoverflow.com/questions/468863/zend-auth-and-acl — делаю в модели один запрос по необходимы таблицам и требуемую информацию складываю в сторидж
можно из dbadapter'а для Zend_Auth взять объект Zend_Db_Select, и с join'ом добавить таблицы, которые нужны.
конкретно метод Zend_Auth_Adapter_DbTable::getDbSelect()
Спасибо, обязательно посмотрю
что мешает расширить существующий, либо написать отдельный?
Я обычно делаю дополнительный запрос в таком случае. Вы ведь расширяете zend_auth, я правильно понял?
Получать данные можно так:
$auth->getIdentity(), там есть дополнительноя проверка на пустоту хранилища, не нужно самому вызывать hasIdentity(). Имхо, плохой тон работать напрямую с хранилищем Zend_Auth и хранить там что-то помимо ID, максимум — модель типа User иначе потом сам замахаешься выбгербать оттуда кучу данных непонятной структуры.

Брать данные из запросов, имхо, правильнее так:
$this->getRequest()->getParams(), перед этим проверив какого типа запрос: $this->getRequest()->isPost(), тогда мы можем определить открыта страница GETом или пришла форма POSTом.
А так же в случае неуспешной валидации выводить форму заново, это покажет пользователю его ошибки в форме автоматически.
отвечу своим имхо:
> $auth->getIdentity()
всегда использую
if (Zend_Auth::getInstance()->hasIdentity()) {

$user_info = Zend_Auth::getInstance()->getStorage()->read();

} else {GUEST}

> $this->getRequest()
$this->_request, $this->_request->isPost()
и по параметрам $this->_request->param1; $this->_request->param2;
в последнейм случае можно использовать поля ВНЕ зависимости от ПОСТ и/или ГЕТ. да и скобочек меньше.
1. Не понимаю зачем лезть в хранилище и вводить дополнительные проверки, если код написан за тебя. Посмотрите код методов, всё поймете.
2. Думаю, что прямое обращение к _request немного плохой тон. Если вдруг нужно обратиться к полю извне экземпляра/потомка, то доступа мы туда не получим, т.к. поле protected. Для этого и сделали getRequest(). Кстати, его код:
public function getRequest()
{
return $this->_request;
}

Так что можно написать $this->getRequest()->param1; $this->getRequest()->param2; без проблем :)
>Разместите этот код в файле application/classes/Acl.php.
Может быть это и не плохо, но насколько мне известно, расширяемые классы принято складывать в ./library/%ProjectName%

В случае с Acl, получаем (пусть название проэкта, будет My):
./library/My/Acl.php
имя класса: My_Acl
В application.ini добавляем:
autoloaderNamespaces.my = «My»
Как вариант. Мне просто удобнее, когда весь код находится в application
А по-моему в Application должно находиться только то, что привязано к текущему проекту. А расширения библиотек я как правило переношу из одного проекта в другой, с незначительными изменениями.
Вполне вероятно, что так лучше. Возьму на вооружение, спс
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации