старые страницы переходят по редиректу нормально, а вот новые, которые я недавно добавил, глючат. Не может это быть связанно с версией 2.2.8?
Дело в том, что яндекс выдает именно ссылку с .html, и по переходу на нее попадаешь на страницу 404 и в адресной строке www.narcononmsk.ru/syin-narkoman?q=syin-narkoman.html, хотя изначально там переход www.narcononmsk.ru/syin-narkoman.html, а самой MODX задано www.narcononmsk.ru/syin-narkoman
Вот кстати заголовки: — www.narcononmsk.ru/syin-narkoman?q=syin-narkoman.html
GET /syin-narkoman?q=syin-narkoman.html HTTP/1.1 Host: www.narcononmsk.ru User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:21.0) Gecko/20100101 Firefox/21.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: ru Accept-Encoding: gzip, deflate DNT: 1 Cookie: PHPSESSID=c70e8b113ff631 Connection: keep-alive Cache-Control: max-age=0
HTTP/1.1 200 OK Server: nginx/1.1.0 Date: Mon, 10 Jun 2013 17:46:47 GMT Content-Type: text/html; charset=utf-8 Connection: keep-alive Keep-Alive: timeout=30 X-Powered-By: PHP/5.2.17 Expires: Thu, 19 Nov 1981 08:52:00 GMT Pragma: no-cache X-XFPC-Cache-Active: Yes X-XFPC-Cache: Hit Content-Encoding: gzip Vary: Accept-Encoding Content-Length: 6161
Здесь код 200 т.е. если добавить в удалялку ссылок яндекса то он ее не удалит потому что ответ сервера 200 а нужно 400 Я имею ввиду что яндекс из поиска удалит ссылки которые действительно отдают ошибку 404
Может в robots.txt прописать это: Disallow: /*.html Disallow: /*?q=* помоему так, посоветуйся еще с кем нибудь и потом здесь еще webmaster.yandex.ua/delurl.xml можно удалить ненужные ссылки
Добрый день! Возникла проблема: я переделал сайт на MODX revo и назначил новые URL, причем нет ни "/", ни ".html". Яндекс почему-то проиндексировал их с ".html", хотя в командной строке все работает нормально (сайт www.narcononmsk.ru).
Я поискал в инете и нашел рекомендацию поставить редирект
RewriteRule (.*)\.html$ $1 [R=301,L]
Но после этого почему-то получаю такой ответ (причем не на всех страницах): при наборе www.narcononmsk.ru/syin-narkoman.html
получаю в ответ 404 по адресу www.narcononmsk.ru/syin-narkoman?q=syin-narkoman.html
а если набрать www.narcononmsk.ru/syin-narkoman то все работает.
Что может быть?
Не буду сейчас расписывать про весь механизм сохранения связанных объектов, а приведу пару примеров и расскажу про тонкость, ради которой и пишется этот топик.
Возьмем два новых объекта (пользователя и его профиль), добавим профиль в пользователя, и сохраним пользователя. Результат: будет сохранен и профиль, плюс еще и в качестве internalKey будет присвоен id нового пользователя. Вот код:
$user = $modx->newObject('modUser', (array)$userdata); $profile = $modx->newObject('modUserProfile', (array)$profiledata); $user->addOne($profile); $user->save();
Отличная штука, эти связи.
Так же можно работать и с имеющимися объектами, к примеру получим профиль пользователя, изменим его, и сохраним объект самого профиля. Результат: профиль будет сохранен.
$user = $modx->getObject('modUser', $id); $profile = $user->getOne('Profile'); $profile->fromArray((array)$profiledata); $user->save();
Собственно, здесь тоже все замечательно. xPDO сам отследит, что связанный с пользователем объект профиля был изменен, и сохранит изменения профиля в базу. Но как будут обстоять дела, если будет изменен профиль во втором уровне вложенности?
Для примера возьмем профиль пользователя, создавшего документ, изменим его, и сохраним документ.
$doc = $modx->getObject('modResource', $id); $user = $doc->getOne('CreatedBy'); $profile = $user->getOne('Profile'); $profile->set('fullname', 'New name'); $doc->save();
И вот здесь как раз и есть загвоздка. Дело в том, что xPDO сохраняет объект только тогда, когда у него есть хоть одна dirty-колонка (измененная). То есть он вызывает метод xPDOObject::save(), в котором вызывается метод _saveRelatedObjects(), сохраняющий связанные объекты. А так как у нас объект пользователя не был изменен, то xPDO его не сохраняет (не вызывает метод save()), а значит и не сохраняет связанные с ним объекты. Следовательно и профиль пользователя не сохраняется.
Давайте еще раз рассмотрим последовательность действий:
  1. Мы сохраняем документ — вызываем метод $doc->save();
  2. В этом методе вызывается метод _saveRelatedObjects(), сохраняя связанные объекты. В нашем случае связанный объект ближайшего уровня — $user.
  3. Далее, каждый связанный объект проверяется на наличие измененных колонок ( if (!empty ($this->_dirty)) ), и если таковые имеются, то этот объект сохраняется (и смотрим опять все начиная с первого пункта, только уже для этого объекта).
Конечно, я считаю, что данный механизм неплохо было бы доработать, чтобы все вложенные объекты проверялись, но пока мы просто рассмотрим вариант решения этой проблемы (так как не знаю кому как, а мне вот понадобилось реализовать сохранение объекта третьего уровня только через сохранение объекта первого уровня. Дело в том, что хочется, чтобы объект сохранялся только в том случае, если сохранятся все предыдущие объекты, а проверки лишние писать не охота).
В общем, как оказалось, здесь только или через явное сохранение предшествующего объекта (почему мне такой момент не подходит, написал выше), или через маркировку предшествующего объекта, будто бы он изменен. В нашем случае код будет выглядеть так:
$doc = $modx->getObject('modResource', $id); $user = $doc->getOne('CreatedBy'); $profile = $user->getOne('Profile'); $profile->set('fullname', 'New name'); if($profile->_dirty){ $user->setDirty('id'); } $doc->save();
То есть проверяем, если колонки есть измененные в профиле, то помечаем колонку id юзера как измененную. В итоге, при сохранении документа, xPDO попытается и пользователя сохранить, и затем его профиль. Конечно это хак, но так, на заметку…
Кстати, по поводу всех этих коннекторов и т.п. В своих пользовательских коннекторах я всегда явно указываю $_SERVER['ctx'] = 'web'; С этими коннекторами всегда вопрос безопасности стоял остро и первый мой багрепорт на эту тему был еще в 2011-ом.
Но это свои пользовательские коннекторы. А что делать с системными? Ведь во-первых, в ядро лезть — это совсем не по религии, а во-вторых, при переустановке MODX-а это все затрется. На этот счет есть очень элегантное решение: можно просто переопределить класс обработки процессоров. Вот в connectors/index.php есть такая строка:
$connectorRequestClass = $modx->getOption('modConnectorRequest.class',null,'modConnectorRequest');
А значит вы можете создать свой класс, расширить им базовый modConnectorRequest, прописать его в системную настройку с именем modConnectorRequest и в своем классе уже дополнительно прописать проверки.
К примеру в базовом классе есть метод initialize:
public function initialize() { if ($this->modx && is_object($this->modx->context) && $this->modx->context instanceof modContext) { $ctx = $this->modx->context->get('key'); if (!empty($ctx) && $ctx == 'mgr') { $ml = $this->modx->getOption('manager_language',null,$this->modx->getOption('cultureKey',null,'en')); if (!empty($ml)) { $this->modx->setOption('cultureKey',$ml); } } } /* load default core cache file of lexicon strings */ $this->modx->lexicon->load('core:default'); if ($this->modx->actionMap === null || !is_array($this->modx->actionMap)) { $this->loadActionMap(); } return true; }
Собственно, у меня есть пара вопросов к этому коду, но сейчас не об этом. В общем, переопределим этот метод и пропишем явно проверку контекста:
public function initialize() { if (!$this->modx OR !is_object($this->modx->context) OR !$this->modx->context instanceof modContext OR !in_array($this->modx->context->key, array('web', 'mgr'))){ return 'Access denied'; } return parent::initialize(); }
Все. Если контекст не будет инициализирован, или он не в списке разрешенных, то шлем лесом.
Я на modxcloud.com все свои сайты держу. Во-первых, все сайты абсолютно отделены друг от друга (взломав один сайт, не залезешь ни в базу, ни в файлы другого). Во-вторых, обновление или переустановка MODX-а в два клика выполняется. В-третьих, оперируешь не полными копиями сайта, а снимками, которые не несут в себе ядро, а только пользовательские эддоны. В итоге ядро четко отделено от пользовательской части сайта, и если зараза и сидит где-то плотно, можно частями сайты перетащить на новый двиг, полностью проверив все составляющие. Vapor и packMan в помощь. А с modxSDK я вообще сейчас только в админке и программирую, так что вообще не парюсь с настройками доступов (FTP и т.п.).
То что заразу поймал раньше — исключено, просто у меня стоит пересылка любой почты с этого хостинга, видимо хацкер отправил письмо себе, чтобы проверить что у него все получилось, я как понял, сразу переименовал папку на хостинге, залил обновления и обновил все сайты. Сейчас все, проверил, вроде все нормально, обошлось.