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

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

Создаю свой компонент. Не могу понять как работает модель

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

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

Сообщений: 27


« : 07.09.2015, 19:17:30 »

Всем добрый день!

Пытаюсь сделать свой собственный компонент для Joomla и никак не могу понять как произвести вставку данных в базу.

У меня есть вид в административной панели, который выводит несколько полей и кнопку (вставить). - с этим всё ясно.
Есть javascript код, который при клике на кнопку делает итерацию всех нужных полей вида, сериализует их и отправляет через AJAX в контроллер. - с этим тоже всё ясно.

Контроллер в свою очередь должен отправить это в модель и получить ответ, что вставка данных прошла успешно.

Я не понимаю 2 вещи:

1) Как сделать вставку данных в базу?
2) Каким образом работает модель? Как к ней обратится?

Чтобы не быть голословным, я приведу более подробный пример.

У меня есть пример компонента com_lendr (Сервис по прокату книг). Я решил разобрать этот пример, так как в Joomla я новичок.

Вот например javascript функция - добавить книгу.

Код:
function addBook()
{
var bookInfo = {};
jQuery("#bookForm :input").each(function(idx,ele){
bookInfo[jQuery(ele).attr('name')] = jQuery(ele).val();
});

jQuery.ajax({
url:'index.php?option=com_lendr&controller=add&format=raw&tmpl=component',
type:'POST',
data:bookInfo,
dataType:'JSON',
success:function(data)
{
if ( data.success ){
jQuery("#book-list").append(data.html);
jQuery("#newBookModal").modal('hide');
}else{

}
}
});

}

тут всё ясно. вопросов нет.

Далее контроллер: add.php

Код:
class LendrControllersAdd extends JControllerBase
{
  public function execute()
  {
    $app      = JFactory::getApplication();
    $return   = array("success"=>false);

    $modelName  = $app->input->get('model', 'Book');
    $view       = $app->input->get('view', 'Book');
    $layout     = $app->input->get('layout', '_entry');
    $item       = $app->input->get('item', 'book');

    $modelName  = 'LendrModels'.ucwords($modelName);

   $model = new $modelName();
   if ( $row = $model->store() )
   {
   $return['success'] = true;
   $return['msg'] = JText::_('COM_LENDR_SAVE_SUCCESS');

     $return['html'] = LendrHelpersView::getHtml($view, $layout, $item, $row);
   }else{
   $return['msg'] = JText::_('COM_LENDR_SAVE_FAILURE');
   }
    
   echo json_encode($return);

  }

}


Тут я не совсем разобрался, но более-менее понятно, что он обращается к модели (вернее к одной из её функций)

Код:
public function store($data=null)
  {   
    $data = $data ? $data : JRequest::get('post');
    $row = JTable::getInstance($data['table'],'Table');

    $date = date("Y-m-d H:i:s");

     // Bind the form fields to the table
    if (!$row->bind($data))
    {
        return false;
    }

    $row->modified = $date;
    if ( !$row->created )
    {
      $row->created = $date;
    }

    // Make sure the record is valid
    if (!$row->check())
    {
        return false;
    }
 
    if (!$row->store())
    {
        return false;
    }

    return $row;

  }

Я не понимаю как работает модель, каким образом данные вставляются в базу.
Буду рад любой помощи, спасибо!
Записан
AlekVolsk
Профи
********

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

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



« Ответ #1 : 07.09.2015, 21:37:13 »

Создание компонента для Joomla 2.5/3.х
Записан
robert
Профи
********

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

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


« Ответ #2 : 07.09.2015, 22:48:10 »

1) Как сделать вставку данных в базу?
Данные ($data) задаются как аргумент, в противном случае берутся из $_POST.
Затем вызывается экземпляр объекта JTable ($row), который загружает нужную таблицу ($data['table']).
$row сначала натягивает данные на структуру таблицы (bind()), затем проверяет валидность данных (check()) и если все нормально - записывает их (store()).
Подробности смотрите в классе JTable.
2) Каким образом работает модель? Как к ней обратится?
Код
$modelName  = 'LendrModels'.ucwords($modelName);
$model = new $modelName();
 
Записан
broadcast77
Осваиваюсь на форуме
***

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

Сообщений: 27


« Ответ #3 : 08.09.2015, 00:40:03 »

Спасибо, стало яснее, но вот этот вот момент не понятен -

Цитировать
Данные ($data) задаются как аргумент, в противном случае берутся из $_POST.
Затем вызывается экземпляр объекта JTable ($row), который загружает нужную таблицу ($data['table']).

Вернее - где тут именно имя таблицы?

По идее должно идти обращение к таблице - #__lendr_books
Но оно нигде не упоминается.
Записан
robert
Профи
********

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

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


« Ответ #4 : 08.09.2015, 00:52:32 »

Вернее - где тут именно имя таблицы?
$data['table']. Скорее всего, в форме, откуда вы отправляете данные, есть скрытое поле с таким значением.
[offtop]
ТС, я сам - самоучка, и на этом форуме я задал только 1 вопрос, на который так и не получил ответа. На самом деле, все намного лучше осваивается, когда вы сами учитесь, не полагаясь на чужую помощь.
[/offtop]
Записан
broadcast77
Осваиваюсь на форуме
***

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

Сообщений: 27


« Ответ #5 : 08.09.2015, 01:04:07 »

Спасибо за помощь! На самом деле всё было гораздо хуже, а теперь намного понятнее.
Да мне нужно было всего то пара разъяснений.
Записан
zomby6888
Живу я здесь
******

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

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


« Ответ #6 : 08.09.2015, 05:36:03 »

robert, позвольте вас поправить, ну а вы конечно можете со мной поспорить, увы не мог пройти мимо и не отметить:

Цитировать
Затем вызывается экземпляр объекта JTable ($row), который загружает нужную таблицу ($data['table']).

Не объекта а класса. У объекта не может быть экземпляра, если он не является классом, а в php объекты не являются классами. К сожалению, а может быть и к радости. Ну тут я может конечно придираюсь к формулировке но:

Цитировать
$modelName  = 'LendrModels'.ucwords($modelName);
$model = new $modelName();

С Joomla же вроде работаем. Из любого места компонента можно обратится к модели:

Код
JModelLegacy::getInstance($modelName, 'LendrModels');
 

А из одноименного контроллера так вообще:

Код
$this->getModel( $modelName );
 

Цитировать
ТС, я сам - самоучка, и на этом форуме я задал только 1 вопрос, на который так и не получил ответа. На самом деле, все намного лучше осваивается, когда вы сами учитесь, не полагаясь на чужую помощь.

Ну и тут конечно тоже не согласен, считаю что нужно задавать вопросы чаще, хоть и сам грешен, гуглом избалован донельзя. Нет таких людей которые знают ответы на все свои вопросы, зато дофига таких, которые боятся или стесняются их задавать. Вопросы тем более не из разряда "Как мне сделать кнопочку чтобы все было ништяк".
Записан
robert
Профи
********

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

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


« Ответ #7 : 08.09.2015, 10:47:31 »

Не объекта а класса.
OK.
Ну тут я может конечно придираюсь к формулировке но:
С Joomla же вроде работаем.
ТС задал вопрос на конкретном примере.
Ну и тут конечно тоже не согласен, считаю что нужно задавать вопросы чаще
Здесь я останусь при своем: за время ожидания ответов можно самостоятельно решить не только один вопрос.
Записан
broadcast77
Осваиваюсь на форуме
***

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

Сообщений: 27


« Ответ #8 : 09.09.2015, 15:37:28 »

Всем добрый день! Вынужден поднять данную тему ещё раз( К сожалению мне не обойтись без вашей помощи.

Суть в чём - я просто пытаюсь понять последовательность происходящих действий. В Joomla (а вернее в моём примере) всё как то сильно разбросано по файлам и не понятно откуда что вызывается.


Вот смотрите, как я писал ранее, вначале через AJAX инициируем вызов контроллера

Код:
jQuery.ajax({
        url:'index.php?option=com_lendr&controller=add&format=raw&tmpl=component',
        type:'POST',
        data:itemInfo,
        dataType:'JSON',

Кстати не понятно - Joomla достаточно указать имя файла контроллера? Потому что насколько мне известно по всем канонам, вначале указывается имя файла, а потом имя самой функции, которую нужно вызвать через AJAX.
Ну не суть.

Далее идёт файл контроллера controllers/add.php

Код:
class LendrControllersAdd extends JControllerBase
{
  public function execute()
  {
    $app      = JFactory::getApplication();
    $return   = array("success"=>false);

    $modelName  = $app->input->get('model', 'Book');
    $view       = $app->input->get('view', 'Book');
    $layout     = $app->input->get('layout', '_entry');
    $item       = $app->input->get('item', 'book');

    $modelName  = 'LendrModels'.ucwords($modelName);

  $model = new $modelName();
    if ( $row = $model->store() )
  {
  $return['success'] = true;
  $return['msg'] = JText::_('COM_LENDR_SAVE_SUCCESS');

     $return['html'] = LendrHelpersView::getHtml($view, $layout, $item, $row);
  }else{
  $return['msg'] = JText::_('COM_LENDR_SAVE_FAILURE');
  }
   
  echo json_encode($return);

  }

}

Как подсказал ранее robert:
Цитировать
$data['table']. Скорее всего, в форме, откуда вы отправляете данные, есть скрытое поле с таким значением.

название таблицы с которой оперирует модель действительно передаётся через скрытое поле на моём виде.

Но вот что происходит дальше(в контроллере) не совсем понятно.

Например из вида в $data['table'] передаётся название таблицы "book". Хотя сама таблица в базе называется #__lender_books.

Далее есть файл модели models/book.php

Код:
class LendrModelsBook extends LendrModelsDefault
{

  /**
  * Protected fields
  **/
  var $_book_id     = null;
 
  var $_user_id     = null;
 
  var $_library_id  = null;

  var $_pagination  = null;

  var $_total       = null;

  var $_published   = 1;

  var $_waitlist    = FALSE;

  var $_wishlist    = FALSE;


  function __construct()
  {
    $app = JFactory::getApplication();
    $this->_book_id = $app->input->get('id', null);
   
    parent::__construct();       
  }
 
  /**
  * Builds the query to be used by the book model
  * @return   object  Query object
  *
  *
  */
  protected function _buildQuery()
  {
    $db = JFactory::getDBO();
    $query = $db->getQuery(TRUE);

    $query->select('b.book_id, b.user_id, b.isbn, b.title, b.author, b.summary, b.pages,
                    b.publish_date, b.lent, b.lent_date, b.due_date');
    $query->from('#__lendr_books as b');

    $query->select('w.waitlist_id, w.user_id as borrower_id');
    $query->leftjoin('#__lendr_waitlists as w on w.book_id = b.book_id AND w.fulfilled = 0');

    $query->select('l.name as borrower');
    $query->leftjoin('#__users as l on l.id = b.lent_uid');

    $query->select('u.name as waitlist_user');
    $query->leftjoin('#__users AS u on u.id = w.user_id');

    return $query;
  }

  public function getItem()
  {
    $book = parent::getItem();

    $reviewModel = new LendrModelsReview();
    $reviewModel->set('_book_id',$book->book_id);
    $book->reviews = $reviewModel->listItems();

    return $book;
  }

  /**
  * Builds the filter for the query
  * @param    object  Query object
  * @return   object  Query object
  *
  */
  protected function _buildWhere(&$query)
  {

    if(is_numeric($this->_book_id))
    {
      $query->where('b.book_id = ' . (int) $this->_book_id);
    }

    if(is_numeric($this->_user_id))
    {
      $query->where('b.user_id = ' . (int) $this->_user_id);
    }

    if(is_numeric($this->_library_id))
    {
      $query->where('b.library_id = ' . (int) $this->_library_id);
    }

    if($this->_waitlist)
    {
      $query->where('w.waitlist_id <> ""');
    }

    $query->where('b.published = ' . (int) $this->_published);

    return $query;
  }

  /**
  * Lend the book
  * @param    array   Data array of book
  * @return   object  The book object loaned
  */
  public function lend($data = null)
  {
    $data = isset($data)? $data : JRequest::get('post');

    if (isset($data['lend']) && $data['lend']==1)
    {
      $date = date("Y-m-d H:i:s");

      $data['lent'] = 1;
      $data['lent_date'] = $date;
      $data['lent_uid'] = $data['borrower_id'];

      $waitlistData = array('waitlist_id'=>$data['waitlist_id'], 'fulfilled' => 1, 'fulfilled_time' => $date, 'table' => 'Waitlist');
      $waitlistModel = new LendrModelsWaitlist();
      $waitlistModel->store($waitlistData);
    } else {
      $data['lent'] = 0;
      $data['lent_date'] = NULL;
      $data['lent_uid'] = NULL;

    }
   
    $row = parent::store($data);   
   
    return $row;

  }

  /**
  * Delete a book
  * @param int      ID of the book to delete
  * @return boolean True if successfully deleted
  */
  public function delete($id = null)
  {
    $app  = JFactory::getApplication();
    $id   = $id ? $id : $app->input->get('book_id');

    $book = JTable::getInstance('Book','Table');
    $book->load($id);

    $book->published = 0;

    if($book->store())
    {
      return true;
    } else {
      return false;
    }
  }
}


и ещё как оказалось есть файлы, как я понял, отвечающие за сами таблицы.
В данном случае файл tables/book.php
КОторый как я понял отвечает за операцию над той или иной таблицей.

Код:
class TableBook extends JTable
{                     
  /**
  * Constructor
  *
  * @param object Database connector object
  */
  function __construct( &$db ) {
    parent::__construct('#__lendr_books', 'book_id', $db);
  }
}


есть кстати ещё один файл models/default.php. Тоже не совсем понятно что он делает.

Код:
function __construct()
  {

    parent::__construct();
  }

  public function store($data=null)
  {   
    $data = $data ? $data : JRequest::get('post');
    $row = JTable::getInstance($data['table'],'Table');

    $date = date("Y-m-d H:i:s");

     // Bind the form fields to the table
    if (!$row->bind($data))
    {
        return false;
    }

    $row->modified = $date;
    if ( !$row->created )
    {
      $row->created = $date;
    }

    // Make sure the record is valid
    if (!$row->check())
    {
        return false;
    }
 
    if (!$row->store())
    {
        return false;
    }

    return $row;

  }

Я не прошу разжовывать для меня код и т.д.

Я прошу лишь помочь мне понять в какой последовательности и что вызывается. Оч рад за любую помощь, спасибо!
Записан
zomby6888
Живу я здесь
******

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

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


« Ответ #9 : 09.09.2015, 16:42:07 »

Цитировать
index.php?option=com_lendr&controller=add&format=raw&tmpl=component',

Здесь написано не по стандартам. В компонентах по умолчанию контроллер вызывается через параметр task:

index.php?option=mycomponent&task=add&format=raw&tmpl=component'

вызовет метод add(), контроллера по умолчанию:

index.php?option=mycomponent&task=mycontroller.add&format=raw&tmpl=component'

вызовет метод add контроллера mycontroller

Цитировать
Например из вида в $data['table'] передаётся название таблицы "book". Хотя сама таблица в базе называется #__lender_books.

Этот параметр используется для создания объекта класса JTable

JTable::getInstance('book','Table');

Создает экземпляр класса TableBook. Описания классов лежат в папке tables. models/default.php - тут вообще непонятно что, возможно код неполный, возможно это просто мусор. Вы понимаете что нибудь в ООП? А то мы тут может зря стараемся?
Записан
broadcast77
Осваиваюсь на форуме
***

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

Сообщений: 27


« Ответ #10 : 09.09.2015, 22:56:00 »

В ООП слава богу понимаю, просто никогда не сталкивался с API Joomla. Там что то всё запутано.
Записан
robert
Профи
********

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

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


« Ответ #11 : 09.09.2015, 23:30:34 »

Начните изучение с точки входа компонента и все будет понятно. У вас это /com_lendr/lendr.php.
Записан
broadcast77
Осваиваюсь на форуме
***

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

Сообщений: 27


« Ответ #12 : 10.09.2015, 01:10:53 »

Я так и сделал в самом начале)
Иначе бы я вообще не знал бы даже с чего начать))
Записан
broadcast77
Осваиваюсь на форуме
***

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

Сообщений: 27


« Ответ #13 : 11.09.2015, 01:07:58 »

Мне кстати так и никто не подсказал последовательность действий, которые происходят в компоненте.
Там можно как нибудь отладиться, чтобы расставить брэйк-пойнты и понять последовательно что там происходит?
Записан
Aleks.Denezh
Практически профи
*******

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

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



« Ответ #14 : 11.09.2015, 01:18:20 »

Мне кстати так и никто не подсказал последовательность действий, которые происходят в компоненте.
Там можно как нибудь отладиться, чтобы расставить брэйк-пойнты и понять последовательно что там происходит?
http://inet-reklama.com/blog/joomla/printsip-raboty-mvc-komponenta-v-joomla.html
Записан
broadcast77
Осваиваюсь на форуме
***

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

Сообщений: 27


« Ответ #15 : 12.09.2015, 00:46:05 »

Спасибо конечно, но та статья старая и для старой версии Joomla. У меня Joomla 3.2
Думаете там ничего не изменилось по сути?
Записан
robert
Профи
********

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

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


« Ответ #16 : 12.09.2015, 00:55:42 »

Спасибо конечно, но та статья старая и для старой версии Joomla. У меня Joomla 3.2
Думаете там ничего не изменилось по сути?
Smiley Интересно, вы там все поняли? Скорее всего, не все, иначе не было бы этого вопроса.
Записан
Aleks.Denezh
Практически профи
*******

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

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



« Ответ #17 : 12.09.2015, 01:22:16 »

Спасибо конечно, но та статья старая и для старой версии Joomla. У меня Joomla 3.2
Думаете там ничего не изменилось по сути?
С 1.6 ветки принцип работы MVC компонента и последовательности работы его в Joomla не меняется! Статья подходит как для Joomla 1.6, так и для 2.5.х так и для 3.х.х веток..
Записан
broadcast77
Осваиваюсь на форуме
***

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

Сообщений: 27


« Ответ #18 : 12.09.2015, 17:17:44 »

Ок. Почитал статью, очень полезно! Спасибо всем за помощь!
Не факт конечно, что больше от меня вопросов не будет, но хотя бы теперь всё более менее логично встало на свои места   Smiley
Записан
Страниц: [1]   Вверх
  Добавить закладку  |  Печать  
 
Перейти в:  

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