Отсутствует связь между кастомными таблицами.

Всем доброго времени суток! Давеча столкнулся с такой проблемой.
Не работает метод getMany(). Уже не знаю что и думать. Буду очень признателен за любую помощь. Спасибо!
xml базы:
<?xml version="1.0" encoding="UTF-8"?>
<model package="geolocation" baseClass="xPDOObject" platform="mysql" defaultEngine="MyISAM" version="1.1">
	<object class="Areas" table="areas" extends="xPDOSimpleObject">
		<field key="town_fk" dbtype="int" precision="10" attributes="unsigned" phptype="integer" null="false" />
		<field key="title" dbtype="varchar" precision="255" phptype="string" null="false" />
		<field key="is_default" dbtype="enum" precision="'1','0'" phptype="string" null="false" default="0" />
		<aggregate alias="Towns" class="Towns" local="town_fk" foreign="id" cardinality="many" owner="foreign" />
		<composite alias="Streets" class="Streets" local="id" foreign="area_fk" cardinality="one" owner="owner" />
	</object>
	<object class="Regions" table="regions" extends="xPDOSimpleObject">
		<field key="title" dbtype="varchar" precision="255" phptype="string" null="false" />
		<composite alias="Towns" class="Towns" local="id" foreign="region_fk" cardinality="one" owner="owner" />
	</object>
	<object class="Streets" table="streets" extends="xPDOSimpleObject">
		<field key="area_fk" dbtype="int" precision="11" phptype="integer" null="false" />
		<field key="title" dbtype="varchar" precision="255" phptype="string" null="false" />
		<field key="adress" dbtype="varchar" precision="255" phptype="string" null="false" />
		<field key="phonenumber" dbtype="char" precision="12" phptype="string" null="false" />
		<field key="is_default" dbtype="enum" precision="'1','0'" phptype="string" null="false" default="0" />
		<field key="in_map" dbtype="text" phptype="string" null="false" />
		<aggregate alias="Areas" class="Areas" local="area_fk" foreign="id" cardinality="many" owner="foreign" />
	</object>
	<object class="Towns" table="towns" extends="xPDOSimpleObject">
		<field key="title" dbtype="char" precision="20" phptype="string" null="false" />
		<field key="region_fk" dbtype="int" precision="10" attributes="unsigned" phptype="integer" null="false" />
		<composite alias="Areas" class="Areas" local="id" foreign="town_fk" cardinality="one" owner="owner" />
		<aggregate alias="Regions" class="Regions" local="region_fk" foreign="id" cardinality="many" owner="foreign" />
	</object>
</model>

Вызов метода getMany() осуществляется в preHook'е сниппета Formit. Сниппет создает плэйсхолдер со списком «Город -> Район города».
Код сниппета:
$out = '';
            $towns = $modx->getCollection('Towns',1);
            if (!$towns) {
                $hook->addError('areas','Не удалось получить список городов');
                return false;
            }
            foreach($towns as $town){
                $areas = $town->getMany('Areas');
                if (!$areas) {
                    $hook->addError('areas','Не удалось получить список районов');
                    return false;
                }
                foreach($areas as $area){
                    $out .= '<li>'.$town->get('title').' -> '.$area->get('title').'</li>' ;  
                }
            }
            $hook->setValue('areas',$out);
В журнале MODx такая запись:
[2015-09-20 08:38:10] (ERROR @ /home/p26419/public_html/aversboden.ru/core/xpdo/om/xpdoobject.class.php: 2266) PHP warning: array_diff_key(): Argument #1 is not an array
Александр
20 сентября 2015, 08:47
modx.pro
1
1 676
0

Комментарии: 20

Сергей Шлоков
20 сентября 2015, 12:28
+1
Как минимум в схеме вижу одну повторяющуюся ошибку: owner может быть или local или foreign.
    Александр
    20 сентября 2015, 12:41
    0
    В качестве примера и образца брал видео от Ильи Уткина youtu.be/Qkspw8kXwK4?t=164. В нем owner=«owner».
    Поменял в своей таблице owner=«owner» на owner=«local»- результат аналогичный…
      Сергей Шлоков
      20 сентября 2015, 12:43
      0
      А map файлы пересоздали/изменили? MODX не работает со схемой, он работает с готовыми map файлами.
        Александр
        20 сентября 2015, 12:46
        0
        Нет. Дело в том, что я работал с дополнением UICMPGenerator. Он к сожалению сейчас отказывается нормально работать. Не могли бы вы мне подсказать как их пересоздать или где почитать литературу.
          Сергей Шлоков
          20 сентября 2015, 12:56
          0
          Вариант 1.
          Ставьте CMPGenerator. Открываете и создаете новый пакет «geolocation». Указываете таблицы, префикс, генерируете и схему и пакет, предварительно сохранив свою старую схему. Далее, в новой схеме прописываете связи aggregate и composite из своей схемы.
          Опять открываете пакет в CMPGenerator, только теперь схему генерировать не надо (ставите Нет), только пакет. Сохраняйте. Все.

          Вариант 2.
          Или вручную — найти все map-файлы и у них поправить все что нужно. Как правило, они лежать в папочке mysql.

          Первый вариант самый простой.
            Александр
            20 сентября 2015, 13:22
            0
            Спасибо за инструкцию! Решил пойти сначала 2 способом. Результата нет. Попробовал 1 способ. Повторил в точности как написано. Результата так и нет =(
              Сергей Шлоков
              20 сентября 2015, 13:26
              0
              Я надеюсь, вы пакет загружаете перед запросами. Если нет, то нужно вставить следующий код перед вызовом ваших объектов.
              $path = $modx->getOption('core_path') . 'components/geolocation/model/';
              if (!$modx->addPackage('geolocation', $path)) return '[geolocation] Пакет не найден.';
                Александр
                20 сентября 2015, 13:32
                0
                Вставил ваш код. Изменений нет.
                Использую вот такие настройки CMPgeneratora:

                Код XML-схемы:
                <?xml version="1.0" encoding="UTF-8"?>
                <model package="geolocation" baseClass="xPDOObject" platform="mysql" defaultEngine="MyISAM" version="1.1">
                	<object class="Areas" table="areas" extends="xPDOSimpleObject">
                		<field key="town_fk" dbtype="int" precision="10" attributes="unsigned" phptype="integer" null="false" />
                		<field key="title" dbtype="varchar" precision="255" phptype="string" null="false" />
                		<field key="is_default" dbtype="enum" precision="'1','0'" phptype="string" null="false" default="0" />
                		<aggregate alias="Towns" class="Towns" local="town_fk" foreign="id" cardinality="many" owner="foreign" />
                		<composite alias="Streets" class="Streets" local="id" foreign="area_fk" cardinality="one" owner="local" />
                	</object>
                	<object class="Regions" table="regions" extends="xPDOSimpleObject">
                		<field key="title" dbtype="varchar" precision="255" phptype="string" null="false" />
                		<composite alias="Towns" class="Towns" local="id" foreign="region_fk" cardinality="one" owner="local" />
                	</object>
                	<object class="Streets" table="streets" extends="xPDOSimpleObject">
                		<field key="area_fk" dbtype="int" precision="11" phptype="integer" null="false" />
                		<field key="title" dbtype="varchar" precision="255" phptype="string" null="false" />
                		<field key="adress" dbtype="varchar" precision="255" phptype="string" null="false" />
                		<field key="phonenumber" dbtype="char" precision="12" phptype="string" null="false" />
                		<field key="is_default" dbtype="enum" precision="'1','0'" phptype="string" null="false" default="0" />
                		<field key="in_map" dbtype="text" phptype="string" null="false" />
                		<aggregate alias="Areas" class="Areas" local="area_fk" foreign="id" cardinality="many" owner="foreign" />
                	</object>
                	<object class="Towns" table="towns" extends="xPDOSimpleObject">
                		<field key="title" dbtype="char" precision="20" phptype="string" null="false" />
                		<field key="region_fk" dbtype="int" precision="10" attributes="unsigned" phptype="integer" null="false" />
                		<composite alias="Areas" class="Areas" local="id" foreign="town_fk" cardinality="one" owner="local" />
                		<aggregate alias="Regions" class="Regions" local="region_fk" foreign="id" cardinality="many" owner="foreign" />
                	</object>
                </model>
                  Сергей Шлоков
                  20 сентября 2015, 13:52
                  0
                  Уже лучше. А теперь осталось разобраться вот с этим
                  $towns = $modx->getCollection('Towns',1);
                  Судя по названию переменной $towns и методу getCollection запрашивается список городов. Т.е. городов, определенных условием, указанным во втором параметре метода getCollection. И что мы так видим? Единичку. Т.е. вы получаете всего один объект. Теперь читаем что должно быть
                  type: object|array|string 
                  Desc: An xPDOCriteria object or an array.
                  Т.е. или объект xPDOCriteria или массив или строка (для where).
                  П.С.
                    Сергей Шлоков
                    20 сентября 2015, 14:04
                    0
                    Также неплохо было бы проверить, существует ли запись с id = 1
                      Александр
                      20 сентября 2015, 14:10
                      0
                      Прошу меня извинить. Данная ошибка возникла в результате пустой xml-таблицы. сейчас подправил все (можете перечитать мой предыдущий комент). И все равно та же ошибка.
                        Сергей Шлоков
                        20 сентября 2015, 14:16
                        0
                        Ну я больше не знаю чем помочь.
                        Попробуйте поэтапно.
                        1. Проверьте, если ли записи в таблице городов.
                        2. Если есть, вызов $modx->getCollection('Towns') что-нибудь возвращает?
                        3. Если да, есть ли запись с id=1
                        и т.д.
                        Александр
                        20 сентября 2015, 14:20
                        0
                        1) Записи есть
                        2) $modx->getCollection('Towns') возвращает массив обьектов Towns
                        3) Запись с id=1 есть
                        Спасибо за помощь. Буду пытаться дальше искать багу.
                        Сергей Шлоков
                        20 сентября 2015, 14:24
                        0
                        Так у вас в схеме для объекта Towns указано cardinality=«one»
                        <composite alias="Areas" class="Areas" local="id" foreign="town_fk" cardinality="one" owner="local" />
                        А вы запрашиваете getMany()
                        $areas = $town->getMany('Areas');
                        Александр
                        20 сентября 2015, 14:30
                        0
                        Это же отношение записи таблицы Towns к записям из таблицы Areas. Несколько записей Areas ссылаются на одну запись из Towns. Вроде все верно или нет?
                        Сергей Шлоков
                        20 сентября 2015, 14:33
                        0
                        Александр
                        20 сентября 2015, 14:46
                        0
                        Спасибо за мануал. Исправил. Получаю теперь сообщение:
                        Не удалось получить список районов
                        Код снипета:
                        $out = '';
                                    $towns = $modx->getCollection('Towns');
                                    if (!$towns) {
                                        $hook->addError('areas','Не удалось получить список городов');
                                        return false;
                                    }
                                    foreach($towns as $town){
                                        $areas = $town->getMany('Areas');
                                        if (!$areas) {
                                            $hook->addError('areas','Не удалось получить список районов');
                                            return false;
                                        }
                                        foreach($areas as $area){
                                            $out .= '<option value="">'.$town->get('title').' - </option>' ;  
                                        }
                                    }
                                    $hook->setValue('areas',$out);
                        Код схемы:
                        <?xml version="1.0" encoding="UTF-8"?>
                        <model package="geolocation" baseClass="xPDOObject" platform="mysql" defaultEngine="MyISAM" version="1.1">
                        	<object class="Areas" table="areas" extends="xPDOSimpleObject">
                        		<field key="town_fk" dbtype="int" precision="10" attributes="unsigned" phptype="integer" null="false" />
                        		<field key="title" dbtype="varchar" precision="255" phptype="string" null="false" />
                        		<field key="is_default" dbtype="enum" precision="'1','0'" phptype="string" null="false" default="0" />
                        		<aggregate alias="Towns" class="Towns" local="town_fk" foreign="id" cardinality="one" owner="foreign" />
                        		<composite alias="Streets" class="Streets" local="id" foreign="area_fk" cardinality="many" owner="local" />
                        	</object>
                        	<object class="Regions" table="regions" extends="xPDOSimpleObject">
                        		<field key="title" dbtype="varchar" precision="255" phptype="string" null="false" />
                        		<composite alias="Towns" class="Towns" local="id" foreign="region_fk" cardinality="many" owner="local" />
                        	</object>
                        	<object class="Streets" table="streets" extends="xPDOSimpleObject">
                        		<field key="area_fk" dbtype="int" precision="11" phptype="integer" null="false" />
                        		<field key="title" dbtype="varchar" precision="255" phptype="string" null="false" />
                        		<field key="adress" dbtype="varchar" precision="255" phptype="string" null="false" />
                        		<field key="phonenumber" dbtype="char" precision="12" phptype="string" null="false" />
                        		<field key="is_default" dbtype="enum" precision="'1','0'" phptype="string" null="false" default="0" />
                        		<field key="in_map" dbtype="text" phptype="string" null="false" />
                        		<aggregate alias="Areas" class="Areas" local="area_fk" foreign="id" cardinality="one" owner="foreign" />
                        	</object>
                        	<object class="Towns" table="towns" extends="xPDOSimpleObject">
                        		<field key="title" dbtype="char" precision="20" phptype="string" null="false" />
                        		<field key="region_fk" dbtype="int" precision="10" attributes="unsigned" phptype="integer" null="false" />
                        		<composite alias="Areas" class="Areas" local="id" foreign="town_fk" cardinality="many" owner="local" />
                        		<aggregate alias="Regions" class="Regions" local="region_fk" foreign="id" cardinality="one" owner="foreign" />
                        	</object>
                        </model>
                        Записи в таблицах есть. Метод почему то не может получить их. Но по крайней мере критическую ошибку не выдает.
                        Александр
                        20 сентября 2015, 14:50
                        0
                        Все заработало. Изменил код сниппета:
                        $towns = $modx->getCollection('Towns');
                                    if (!$towns) {
                                        $hook->addError('areas','Не удалось получить список городов');
                                        return false;
                                    }
                                    foreach($towns as $town){
                                        $areas = $town->getMany('Areas');
                                        if (!$areas) {
                                            $hook->addError('areas','Не удалось получить список районов');
                                        }
                                        foreach($areas as $area){
                                            $out .= '<option value="">'.$town->get('title').' - '.$area->get('title').'</option>' ;  
                                        }
                                    }
                                    $hook->setValue('areas',$out);
                        Убрал
                        return false;
                        Спасибо вам огромное. Только вот не могу понять почему return срабатывал...?
                        Сергей Шлоков
                        20 сентября 2015, 14:59
                        0
                        На здоровье!
                        Скорее всего, дело не в return, а в кэше. Думаю, если вернуть его обратно, то все будет работать и с ним.
                        Александр
                        20 сентября 2015, 15:02
                        0
                        Увы нет. Почистил кэш. С ретёрном не работает.
    Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
    20