0 Пользователей и 1 Гость просматривают эту тему.
  • 18 Ответов
  • 1594 Просмотров
*

broadcast77

  • Осваиваюсь на форуме
  • 27
  • 0 / 0
Всем добрый день!

Пытаюсь сделать свой собственный компонент для 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;

  }

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

robert

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

broadcast77

  • Осваиваюсь на форуме
  • 27
  • 0 / 0
Спасибо, стало яснее, но вот этот вот момент не понятен -

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

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

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

robert

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

broadcast77

  • Осваиваюсь на форуме
  • 27
  • 0 / 0
Спасибо за помощь! На самом деле всё было гораздо хуже, а теперь намного понятнее.
Да мне нужно было всего то пара разъяснений.
*

zomby6888

  • Завсегдатай
  • 1473
  • 171 / 3
robert, позвольте вас поправить, ну а вы конечно можете со мной поспорить, увы не мог пройти мимо и не отметить:

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

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

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

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

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

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

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

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

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

robert

  • Живу я здесь
  • 4974
  • 457 / 20
Не объекта а класса.
OK.
Ну тут я может конечно придираюсь к формулировке но:
С Joomla же вроде работаем.
ТС задал вопрос на конкретном примере.
Ну и тут конечно тоже не согласен, считаю что нужно задавать вопросы чаще
Здесь я останусь при своем: за время ожидания ответов можно самостоятельно решить не только один вопрос.
Не будь паразитом, сделай что-нибудь самостоятельно!
*

broadcast77

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

Суть в чём - я просто пытаюсь понять последовательность происходящих действий. В 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

  • Завсегдатай
  • 1473
  • 171 / 3
Цитировать
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 - тут вообще непонятно что, возможно код неполный, возможно это просто мусор. Вы понимаете что нибудь в ООП? А то мы тут может зря стараемся?
интернет-блог: http://websiteprog.ru
*

broadcast77

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

robert

  • Живу я здесь
  • 4974
  • 457 / 20
Начните изучение с точки входа компонента и все будет понятно. У вас это /com_lendr/lendr.php.
Не будь паразитом, сделай что-нибудь самостоятельно!
*

broadcast77

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

broadcast77

  • Осваиваюсь на форуме
  • 27
  • 0 / 0
Мне кстати так и никто не подсказал последовательность действий, которые происходят в компоненте.
Там можно как нибудь отладиться, чтобы расставить брэйк-пойнты и понять последовательно что там происходит?
*

Aleks.Denezh

  • Живу я здесь
  • 3406
  • 428 / 4
Мне кстати так и никто не подсказал последовательность действий, которые происходят в компоненте.
Там можно как нибудь отладиться, чтобы расставить брэйк-пойнты и понять последовательно что там происходит?
http://ссылка вырезана, так как домен распространяет вирусы/blog/joomla/printsip-raboty-mvc-komponenta-v-joomla.html
*

broadcast77

  • Осваиваюсь на форуме
  • 27
  • 0 / 0
Спасибо конечно, но та статья старая и для старой версии Joomla. У меня Joomla 3.2
Думаете там ничего не изменилось по сути?
*

robert

  • Живу я здесь
  • 4974
  • 457 / 20
Спасибо конечно, но та статья старая и для старой версии Joomla. У меня Joomla 3.2
Думаете там ничего не изменилось по сути?
^-^ Интересно, вы там все поняли? Скорее всего, не все, иначе не было бы этого вопроса.
Не будь паразитом, сделай что-нибудь самостоятельно!
*

Aleks.Denezh

  • Живу я здесь
  • 3406
  • 428 / 4
Спасибо конечно, но та статья старая и для старой версии Joomla. У меня Joomla 3.2
Думаете там ничего не изменилось по сути?
С 1.6 ветки принцип работы MVC компонента и последовательности работы его в Joomla не меняется! Статья подходит как для Joomla 1.6, так и для 2.5.х так и для 3.х.х веток..
*

broadcast77

  • Осваиваюсь на форуме
  • 27
  • 0 / 0
Ок. Почитал статью, очень полезно! Спасибо всем за помощь!
Не факт конечно, что больше от меня вопросов не будет, но хотя бы теперь всё более менее логично встало на свои места   ^-^
Чтобы оставить сообщение,
Вам необходимо Войти или Зарегистрироваться
 

Модель для представления, которое показывает списки данных разных типов

Автор borro

Ответов: 27
Просмотров: 895
Последний ответ 06.05.2020, 11:57:12
от Septdir
Не работает setState

Автор platonische

Ответов: 29
Просмотров: 696
Последний ответ 25.03.2019, 17:57:13
от robert
Не могу найти, где то подключается mootools

Автор Kasyanov

Ответов: 11
Просмотров: 934
Последний ответ 20.08.2018, 01:08:11
от Kasyanov
Не могу записать SQL в терминах db query-&amp;gt;

Автор tm2010

Ответов: 2
Просмотров: 580
Последний ответ 16.04.2018, 18:00:30
от robert
Добавить функцию в модель FRONT END

Автор platonische

Ответов: 6
Просмотров: 739
Последний ответ 27.11.2017, 12:29:05
от platonische