Форум русской поддержки Joomla!® CMS
07.12.2016, 01:49:09 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
   
   Начало   Поиск Joomla 3.0 FAQ Joomla 2.5 FAQ Joomla 1.5 FAQ Правила форума Новости Joomla Реклама Войти Регистрация Помощь  
Страниц: [1] 2  Все   Вниз
  Добавить закладку  |  Печать  
Автор

Передача данных от контроллера компонента в модель

 (Прочитано 791 раз)
0 Пользователей и 1 Гость смотрят эту тему.
tm2010
Осваиваюсь на форуме
***

Репутация: +0/-0
Offline Offline

Сообщений: 33


« : 16.09.2015, 21:05:32 »

Полуабсолютный ноль в php ( имею опыт только в C++ плюс простейшие програмки на php без классового понимания языка)
Уверен, что моя проблема в классовом понимании php, но ответа найти не могу.
Пробую писать компонент, Прочитал курс г-на Рекуна Helloworld его и банально пытаюсь модифицировать под свои нужды
в default view который отображает записи таблицы вставил кнопку, по которой хочу отобразить другую таблицу с теми же id что и в основной таблице
Соответственно в контроллере имею этот id который выбрал пользователь и нажал на кнопку которую обрабатывает конроллер
Показать текстовый блок

В модели вроде бы все как бы даже работает
и id сохраняется в функции saveitem() в переменную $currentId, обьявленную в классе, но почемуто  переменная в которой сохраняю функцию, недоступна в другой фунции - getListQuery, вернее равна null
Я понимаю что я где-то морожу глупость, но уверен виной - мое знание phpб ну либо глобальное непонимание MVC (наплодил объектов)
не дайте умереть дураком
Показать текстовый блок
подскажите, что я делаю не так ?
Записан
zomby6888
Живу я здесь
******

Репутация: +168/-3
Offline Offline

Пол: Мужской
Сообщений: 1538


« Ответ #1 : 16.09.2015, 21:20:41 »

А с чего вы взяли что метод getListQuery вызывается после вашего saveItem() и на том же объекте? Он вызывается в методе getItems() вообще-то, вы же от jmodelList наследуетесь. Получить переменную можно в самом методе из запроса или через состояние модели перед вызовом getItems на том же объекте .
« Последнее редактирование: 16.09.2015, 21:35:28 от zomby6888 » Записан
tm2010
Осваиваюсь на форуме
***

Репутация: +0/-0
Offline Offline

Сообщений: 33


« Ответ #2 : 16.09.2015, 21:58:14 »

Спасибо за ответ
Я в Eclipseе ставлю брэйкпоинты, сначала выполняется saveItem()
кто вызывает getListQuery, я честно не очень понимаю, но он идет после saveItem()
если я правильно объявил и работаю с  $currentId ? то у меня подозрение что существует 2 объекта JmodelList  в одном из которых
эта переменная не сохранена, такое может быть?
я в принципе нашел вариант       
               $app = JFactory::getApplication();
      $currentId = $app->getUserState('selectedId');
а в контроллере соответственно setUserState .. вы  о нем говорите ? это через состояние модели ?
но всетаки хотелось понять почему через устанавливаемую в классе переменную не работает.

Записан
Aleks.Denezh
Практически профи
*******

Репутация: +372/-4
Offline Offline

Пол: Мужской
Сообщений: 2762



« Ответ #3 : 16.09.2015, 22:04:04 »

подскажите, что я делаю не так ?
Все делаете не так! Банально не понимаете последовательности работы приложения увы!
У вас после
model->saveItem($pks[0]); // взять только один и сохранить его в модели
идет:
 $this->setRedirect(JRoute::_('index.php?option=com_rentflat&view=events', false));
Тоесть перенаправление на новую страницу!
У вас текущее приложение уходит в небытие и идет переход на страницу  index.php?option=com_rentflat&view=events в вид  events  компонента com_rentflat
В котором этот вид и запрашивает getListQuery
Вы идете не по тому пути немножко!
Записан
zomby6888
Живу я здесь
******

Репутация: +168/-3
Offline Offline

Пол: Мужской
Сообщений: 1538


« Ответ #4 : 16.09.2015, 22:27:21 »

Из контроллера передать состояние в модель геморно, потому что надо переопределить метод display().  Это я считаю недоработкой фреймворка. Проще всего передать переменную в модель перед вызовом getItems() в прослойке вида (RentFlatViewEvents класс возможно в вашем случае):
Код
...
$model = $this->getModel();
$model->setState('currentId', 1);
$this->items = $this->get('Items');
...
 
Затем в getListQuery модели получить его:
Код
...
$currentId = $this->getState('currentId');
...
 

Еще проще взять из запроса. RentFlatControllerEvents наследуется от JСontrollerForm и вообще по идее не должен работать с моделью списка, тем более у вас там вообще редирект как уже вам написали.
Записан
robert
Профи
********

Репутация: +344/-11
Offline Offline

Пол: Мужской
Сообщений: 3586


« Ответ #5 : 16.09.2015, 22:31:58 »

если я правильно объявил и работаю с  $currentId ?
почему через устанавливаемую в классе переменную не работает.
$this->currentId. Пример:
Показать текстовый блок
Записан
tm2010
Осваиваюсь на форуме
***

Репутация: +0/-0
Offline Offline

Сообщений: 33


« Ответ #6 : 16.09.2015, 23:07:48 »

Все делаете не так! Банально не понимаете последовательности работы приложения увы!
У вас после
model->saveItem($pks[0]); // взять только один и сохранить его в модели
идет:
 $this->setRedirect(JRoute::_('index.php?option=com_rentflat&view=events', false));
Тоесть перенаправление на новую страницу!
У вас текущее приложение уходит в небытие и идет переход на страницу  index.php?option=com_rentflat&view=events в вид  events  компонента com_rentflat
В котором этот вид и запрашивает getListQuery
Вы идете не по тому пути немножко!
собственно я так и планировал, открыть экран, в заголовке гдето id первой таблице, с ее именем, и список подчиненных рекордов events с которыми буду выполнять какието действия. Единственное, чего не учитываю, наверное вы правы, как вернуться обратно к первой таблице. я думал возврат будет через меню.
подскажите как грамотно это сделать с тем чтобы вернуться к текущему приложению?
Записан
tm2010
Осваиваюсь на форуме
***

Репутация: +0/-0
Offline Offline

Сообщений: 33


« Ответ #7 : 16.09.2015, 23:10:41 »

$this->currentId. Пример:
Показать текстовый блок
пробовал и с this->. поведение такое же
Записан
tm2010
Осваиваюсь на форуме
***

Репутация: +0/-0
Offline Offline

Сообщений: 33


« Ответ #8 : 16.09.2015, 23:25:03 »

Из контроллера передать состояние в модель геморно, потому что надо переопределить метод display().  Это я считаю недоработкой фреймворка. Проще всего передать переменную в модель перед вызовом getItems() в прослойке вида (RentFlatViewEvents класс возможно в вашем случае):
Код
...
$model = $this->getModel();
$model->setState('currentId', 1);
$this->items = $this->get('Items');
...
 
Затем в getListQuery модели получить его:
Код
...
$currentId = $this->getState('currentId');
...
 

Еще проще взять из запроса. RentFlatControllerEvents наследуется от JСontrollerForm и вообще по идее не должен работать с моделью списка, тем более у вас там вообще редирект как уже вам написали.
спасибо, только у меня нет понимания как в этом  view получить id  выбранного рекорда, тот что у Вас равен единице, а в конроллере я просто раскопал, как он извлекается
я об этом -$pks = $input->post->get('cid', array(), 'array');
извините за тупость, но реально крыша  дымиться, первое время я просто хотел все бросить в виду полного непонимания ... да и сейчас вижу недалеко продвинулся.
Записан
robert
Профи
********

Репутация: +344/-11
Offline Offline

Пол: Мужской
Сообщений: 3586


« Ответ #9 : 16.09.2015, 23:29:12 »

Мой предыдущий пост не имеет прямого отношения к вашей задаче, я только хотел указать на ваше неправильное оперирование свойствами класса.
По вашей задаче zomby6888 уже написал в своем последнем посте. Перед перенаправлением сохраните $currentId в сессии или передавайте ее в $_REQUEST.
P.S.
Код
$pks = $input->post->get('cid', array(), 'array');
$model = $this->getModel();
$model->setState('currentId', $pks[0]);
$this->items = $this->get('Items');
 
Записан
tm2010
Осваиваюсь на форуме
***

Репутация: +0/-0
Offline Offline

Сообщений: 33


« Ответ #10 : 17.09.2015, 21:16:09 »

Спасибо всем большое.
я возможно или мне кажется начинаю понимать свою ошибку
Подтвердите пожалуйста что я правильно понимаю, или не понимаю ничего
Контроллер должен как то запустить view моей вторичной таблицы передав туда id (вопрос как )
view совершенно естественным образом ( тоесть без моего участия, внутри кода самой Joomla ) должен поднять модель events и (породить его из класса) и вызвать метод  getListQuery в модели, которая создается во view.
я же кодом  в контролере
$model = $this->getModel()
создаю обьект и сохраняя в нем id в в конечном счете получаю два обьекта, этот, и тот который порождается во view соответственно имею то что имею, в одном объекте id сохранен, в другом нет.

Если я думаю хоть немного  в правильном направлении(не уверен)  , то подскажите пожалуйста - как грамотно передавать выбранный пользователем id во view ? а оттуда в модель
с помощью тогоже $model->setState('currentId', $pks[0]);?
И надо ли его вообще передавать во view, поскольку он используется в выборке базы данных? Ну если только показать id родительского рекорда
и если я правильно думаю то в контроллере к модели его передавать нельзя поскольку $model = $this->getModel() породит ненужный объект?
Понимаю, сумбурно написал, но если есть  возможность ткнуть где я ошибаюсь, прокоментируйте мой опус.Спасибо
Записан
zomby6888
Живу я здесь
******

Репутация: +168/-3
Offline Offline

Пол: Мужской
Сообщений: 1538


« Ответ #11 : 17.09.2015, 22:12:56 »

Попробую внести ясность. Контороллер, модель и представление (на самом деле нифига не представление но я не буду усложнять, буду называть его просто view в дальнейшем) это все классы которые составляют MVC модель Joomla. Если в запросе не прописан какой то специфический контроллер то приложение создает экземпляр/объект контроллера по умолчанию и если в запросе не указана никакая другая задача то вызывается метод display() этого контроллера.

Что дальше контроллер разруливает в этом методе:

В этом методе контроллер создает (без вашего участия, если кончено вы его не перезагрузили/переопределили) экземпляр модели и экземпляр view (имя модели и view берется на основе наименования класса контроллера если вы их явно не указали в запросе или конструкторе). Затем он устанавливает экземпляр модели в определенное свойство полученного объекта view, чтобы методы view имели доступ к этому объекту модели. Затем контролер вызывает метод display() экземпляра view (не путать с методом display контроллера который я сейчас описываю). И вот там уже, в большинстве случаев и вызывается метод getItems() модели который в свою очередь вызывает метод  getListQuery для получения данных списка. Ну и там уже рендерится шаблон в который передаются данные списка.

Поэтому чтобы передать переменную в модель вы должны в этом методе получить экземпляр этой модели. Собственно это и делает метод getModel, возвращает модель которую контроллер установил для этого view в своем методе display. На сам деле там вроде даже массив этих моделей хранится но уж не буду усложнять.

Ну и вы на самом деле можете переопределить метод display, и установить переменную для модели в нем непосредственно. Это будет даже правильнее с точки зрения стандартов MVC, потому что по идее получать переменные из запроса должен контроллер в таких моделях. Но это не совсем удобно, чуть больше писанины будет надо каждый раз копировать содержимое метода.

P.S Это вот так вот вкратце, поправьте меня если где ошибся, за подробностями конечно надо лезть в литературу или исходники
Записан
robert
Профи
********

Репутация: +344/-11
Offline Offline

Пол: Мужской
Сообщений: 3586


« Ответ #12 : 17.09.2015, 22:52:09 »

del
« Последнее редактирование: 18.09.2015, 00:05:51 от robert » Записан
zomby6888
Живу я здесь
******

Репутация: +168/-3
Offline Offline

Пол: Мужской
Сообщений: 1538


« Ответ #13 : 17.09.2015, 23:17:47 »

только что проверил,  $this->get('Items') не создает новый экземпляр а возвращает тот что уже контроллер установил для view в свойстве $this->_defaultModel, и вызывает на нем соответствующий метод

Вобще там берется модель из свойства $this->_defaultModel. Там еще кстатии есть массив моделей в который можно другие модели устанавливать и если передать вторым парметром имя модели $this->get('Items', 'modelname')   то будет вызван метод getItems на экземпляре модели из этого массива
« Последнее редактирование: 17.09.2015, 23:27:13 от zomby6888 » Записан
robert
Профи
********

Репутация: +344/-11
Offline Offline

Пол: Мужской
Сообщений: 3586


« Ответ #14 : 17.09.2015, 23:24:39 »

Хм, тогда почему до сих пор ТС не может решить свою задачу? Или он просто хочет пообщаться?
« Последнее редактирование: 17.09.2015, 23:35:08 от robert » Записан
zomby6888
Живу я здесь
******

Репутация: +168/-3
Offline Offline

Пол: Мужской
Сообщений: 1538


« Ответ #15 : 17.09.2015, 23:33:42 »

Видимо пытается понять как работает MVC  Smiley
Записан
robert
Профи
********

Репутация: +344/-11
Offline Offline

Пол: Мужской
Сообщений: 3586


« Ответ #16 : 17.09.2015, 23:35:19 »

Проверил в своем компоненте: в аналогичной ситуации $this->get('Items') выдает null.
Записан
zomby6888
Живу я здесь
******

Репутация: +168/-3
Offline Offline

Пол: Мужской
Сообщений: 1538


« Ответ #17 : 17.09.2015, 23:43:01 »

Ну у меня разве что установлен $this->defaut_view для контроллера по умолчанию. Да ксатии, точняк я сейчас вспомнил что нужно установить это свойство контроллеру, иначе иначе он не установит модель по умолчанию для вьюхи. Тоже кстатии косяк фреймворка, он мог бы и на основе запроса устанавливать модель по умолчанию для view. Тоесть у меня в контролере прописано: protected $default_view = 'categories'; ( view='categories' у меня)

А хотя нет там косяка я сейчас внимательнее посмотрел, просто если view не указан в запросе его необходимо установить как свойство для контроллера по умолчанию



« Последнее редактирование: 18.09.2015, 00:16:59 от zomby6888 » Записан
robert
Профи
********

Репутация: +344/-11
Offline Offline

Пол: Мужской
Сообщений: 3586


« Ответ #18 : 18.09.2015, 00:07:33 »

Был не прав: в контроллере в методе $view->setModel() поставил второй аргумент=true и $this->get('Items') заработал.
Записан
zomby6888
Живу я здесь
******

Репутация: +168/-3
Offline Offline

Пол: Мужской
Сообщений: 1538


« Ответ #19 : 18.09.2015, 00:20:43 »

Ну да этот параметр он как раз и устанавливает экземпляр модели как модель по умолчанию для view
Записан
Aleks.Denezh
Практически профи
*******

Репутация: +372/-4
Offline Offline

Пол: Мужской
Сообщений: 2762



« Ответ #20 : 18.09.2015, 00:31:00 »

тут я писал как работает MVC и порядок работы! почитайте!
Записан
zomby6888
Живу я здесь
******

Репутация: +168/-3
Offline Offline

Пол: Мужской
Сообщений: 1538


« Ответ #21 : 18.09.2015, 01:01:38 »

Кстатии код в этой статье код:
Код
class blogController extends JController
{
   function display( $cachable = true )
   {
       $this->default_view = 'category';
       parent::display( $cachable );
   }
}
 
Можно заменить на:
Код
class blogController extends JController
{
   protected $default_view = 'category';
}
 

Правда они могут потом конструктор переписать, и присвоить туда что нибудь, даже если свойство определено
« Последнее редактирование: 18.09.2015, 01:07:22 от zomby6888 » Записан
tm2010
Осваиваюсь на форуме
***

Репутация: +0/-0
Offline Offline

Сообщений: 33


« Ответ #22 : 18.09.2015, 16:27:12 »

Рад что мой глупый пост стал предметом обсуждения, деталей и ньюансов которого я все равно глубоко не понял
Тем не менее у себя в коде я вижу что ни черта у меня не работает так как я бы хотел
c подачи zomby6888
в контроллере Events добавил  $this->items = $this->get('Items');
в результате он возвращает null
Показать текстовый блок
конкретно в кишочках Joomla в файле object.php идет сразу возврат
public function get($property, $default = null)
   {
      if (isset($this->$property))
      {
         return $this->$property;
      }

      return $default;
   }

а в модели

Показать текстовый блок
в трассировке в Eclipseе вижу  конструтор __construct($config = array())
вызывается два раза, первый до функции showevents в контроллере
а второй, когда фунция уже выполнилась
getListQuery() не вызывается, если закоментирована во view
Показать текстовый блок
и вызывается если она там есть, но в ней $currentId=-1
 мне кажется у меня два объекта model
в конце концов бог с ним с моим кодом, если он нарушает концепции MVC
подскажите как правильно решать мою задачу
имеется view list какой то таблицы записей
я хочу по custom кнопке ( это контроллер, как я понял без вариантов) и отмеченном рекорде этой таблицы
иметь выборку записей(модель и view)  другой таблицы в котором будут только рекорды у которых какое то поле будет равным id отмеченного рекорда $query->where($db->quoteName('Flat_id'). ' LIKE '. '$currentId');

как такое решать  грамотно, что бы не иметь геморроя с передачей id в модель?


Или это неправильно, по кнопке получать view list рекордов ?

Записан
robert
Профи
********

Репутация: +344/-11
Offline Offline

Пол: Мужской
Сообщений: 3586


« Ответ #23 : 18.09.2015, 17:16:47 »

Неправильно.
В controller
Показать текстовый блок
В view
Показать текстовый блок
В model
Показать текстовый блок

P.S. showevents() в контроллере - лишняя, уже существует функция по-умолчанию JControllerLegacy->display().
« Последнее редактирование: 18.09.2015, 17:24:38 от robert » Записан
b2z
Support Team
*****

Репутация: +710/-0
Offline Offline

Пол: Мужской
Сообщений: 7533


Разраблю понемногу


« Ответ #24 : 18.09.2015, 17:27:51 »

Как передать данные из контроллера в модель
Записан
Aleks.Denezh
Практически профи
*******

Репутация: +372/-4
Offline Offline

Пол: Мужской
Сообщений: 2762



« Ответ #25 : 18.09.2015, 17:46:16 »

robert а зачем это извращение:
Код
class RentFlatControllerEvents extends JControllerForm
{
 
public function showevents()
  {
     // Redirect to the list screen.
     $this->setRedirect(JRoute::_('index.php?option=com_rentflat&view=events', false));
  }
 
}
это же масло масляное, зачем делать задачу на переход в стандартный таск display()?!
Записан
robert
Профи
********

Репутация: +344/-11
Offline Offline

Пол: Мужской
Сообщений: 3586


« Ответ #26 : 18.09.2015, 17:50:58 »

Ну, я просто взял код ТС, думая, что так будет легче объяснять. Потом уже дописал
P.S. showevents() в контроллере - лишняя, уже существует функция по-умолчанию JControllerLegacy->display().
Записан
Aleks.Denezh
Практически профи
*******

Репутация: +372/-4
Offline Offline

Пол: Мужской
Сообщений: 2762



« Ответ #27 : 18.09.2015, 17:52:06 »

public function showevents(){
    // Get the input
   $input = JFactory::getApplication()->input;
   $pks = $input->post->get('cid', array(), 'array'); // взять array выбранных пользователем id
   
   // Sanitize the input
   JArrayHelper::toInteger($pks);
   // Get the model
   $model = $this->getModel();
   $model->setState('currentId', $pks[0]);
        $this->items = $this->get('Items');   /// null
   // Redirect to the list screen.
   $this->setRedirect(JRoute::_('index.php?option=com_rentflat&view=events', false));
}
Ещё раз по этому коду (кстати у вас нет банального понимания как работает PHP)!
Объясню на пальцах!
вы выполняете код в методе showevents() и он выполняется, но когда доходит до строки $this->setRedirect(JRoute::_('index.php?option=com_rentflat&view=events', false));
у вас идет перенаправление в index.php?option=com_rentflat&view=events!
То есть то что вы делали все это время, ИСЧЕЗАЕТ! открывается новый экземпляр сайта! Все равно что вы закроете текущий сайт и откроете страницу index.php?option=com_rentflat&view=events!
У вас все передалось и в модель и в контроллер, но на текущей странице! Но как только доходит до строки $this->setRedirect(JRoute::_('index.php?option=com_rentflat&view=events', false)), у вас открывается другая страница, идет новая инициалициализация сайта, запуск компонента com_rentflat и вывод вида events, ваш метод showevents уже не работает, и уже установленных переменных нету!
Записан
Aleks.Denezh
Практически профи
*******

Репутация: +372/-4
Offline Offline

Пол: Мужской
Сообщений: 2762



« Ответ #28 : 18.09.2015, 18:01:38 »

Лично мне больше нравится такой способ:
Модель:
Показать текстовый блок
Вид:
Показать текстовый блок
Записан
tm2010
Осваиваюсь на форуме
***

Репутация: +0/-0
Offline Offline

Сообщений: 33


« Ответ #29 : 18.09.2015, 18:05:49 »

Ещё раз по этому коду (кстати у вас нет банального понимания как работает PHP)!
Объясню на пальцах!
вы выполняете код в методе showevents() и он выполняется, но когда доходит до строки $this->setRedirect(JRoute::_('index.php?option=com_rentflat&view=events', false));
у вас идет перенаправление в index.php?option=com_rentflat&view=events!
То есть то что вы делали все это время, ИСЧЕЗАЕТ! открывается новый экземпляр сайта! Все равно что вы закроете текущий сайт и откроете страницу index.php?option=com_rentflat&view=events!
У вас все передалось и в модель и в контроллер, но на текущей странице! Но как только доходит до строки $this->setRedirect(JRoute::_('index.php?option=com_rentflat&view=events', false)), у вас открывается другая страница, идет новая инициалициализация сайта, запуск компонента com_rentflat и вывод вида events, ваш метод showevents уже не работает, и уже установленных переменных нету!
Замечательно, это не секрет что я в php слабее крысы
код спер из какогото компонента, который по кнопке загружает файл, видимо там оправдано, потомучто  моменту редиректа, задание выполнено
но если я убираю редирект, то я вижу голую страницу с URL http://localhost/administrator/index.php?option=com_rentflat&view=rentflats и никакого view=events
вы подскажите как правильно  решить мою задачу
что туда поставить ? если я его убираю
Записан
Страниц: [1] 2  Все   Вверх
  Добавить закладку  |  Печать  
 
Перейти в:  

Powered by SMF 1.1.21 | SMF © 2006, Simple Machines

Joomlaforum.ru is not affiliated with or endorsed by the Joomla! Project or Open Source Matters.
The Joomla! name and logo is used under a limited license granted by Open Source Matters
the trademark holder in the United States and other countries.

LiveInternet