Русскоязычный форум, посвященный фреймворку Kohana

Все о фреймворке Kohana. Обсуждение уроков, документации.
Текущее время: 29 мар 2024, 00:24

Часовой пояс: UTC + 4 часа [ Летнее время ]




Начать новую тему Ответить на тему  [ Сообщений: 38 ]  На страницу Пред.  1, 2, 3, 4  След.
Автор Сообщение
 Заголовок сообщения: Re: ORM один ко многим
СообщениеДобавлено: 11 июн 2013, 17:55 
Не в сети
Бывалый
Аватара пользователя

Зарегистрирован: 02 апр 2013, 16:26
Сообщения: 474
Откуда: Сергиев Посад
Цитата:
// И вот тут мы в цикле создаем новый пустой объект(единицу покупки) через связь в ORM!

почему ты уверен что он у тебя каждый раз новый создается? из зачем его каждый раз создавать когда можно модель просто очистить, это менее ресурсоемкий процесс

Код:
$items = $order->items;
foreach($this->cart as $k=>$c){// Это массив из объектов(продукт,материал)
   // ..
   $items->values($item)->save();
}


Цитата:
Я же писал, что все работает, за исключением одного непонятного момента..

так хрен знает чем он вызван, поэтому и нужна полная картина, мы же тут не в угадай мелодию играем..

_________________
Майкл Джордан играет в баскетбол. Чарльз Мэнсон убивает людей. Я пишу код. У каждого свой талант.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: ORM один ко многим
СообщениеДобавлено: 12 июн 2013, 00:32 
Не в сети
Бывалый
Аватара пользователя

Зарегистрирован: 02 апр 2013, 16:26
Сообщения: 474
Откуда: Сергиев Посад
запилил сегодня основу модуля корзины, кому надо могу сырую версию отдать, а через пару дней залью на гитхаб
Код:
<?php defined('SYSPATH') or die('No direct script access.');
/**
 *
 * Shopping cart
 *
 * @package   Kohana/Cart
 * @author    WinterSilence
 *
 *   $product = array(
 *               'id'      => 123, //or use sku '123ABC'
 *               'qty'     => 2,
 *               'price'   => 39.95,
 *               'name'    => 'T-Shirt',
 *               'options' => array(
 *                              array'id' => 134, 'name' => 'Size', 'value' => 'XL'),
 *                              array'id' => 34, 'name' => 'Color', 'value' => 'Red'),
 *                           ),
 *           );
 *
 *  id      - Each product in your store must have a unique identifier. Typically this will be an "sku" or other such identifier.
 *  id      - Each product in your store must have a unique identifier. Typically this will be an "sku" or other such identifier.
 *  qty     - The quantity being purchased.
 *  price   - The price of the item.
 *  name    - The name of the item.
 *  options - Any additional attributes that are needed to identify the product. These must be passed via an array.
 *
 *  Example:
 *  $cart = Cart::instance();
 *  $cart->set($id, $gty, $options);
 *  $product = $cart->get($id, $options);
 *  $all_products = $cart->get(); or use $cart->products
 *  $cart->delete($id);
 *  $cart->delete(); // delete all
 *  $name_first_product = $cart->products[0]['name'];
 *  $total_cost = $cart->total['cost'];
 *  $total_count = $cart->total['count'];
 *
 */
class Kohana_Cart
{
   // Object instance
   private static $_instance;
   
   // Configuration
   protected $_config = array();
   
   // Session object
   protected $_session;
   
   // ORM product model
   protected $_model_product;
   
   // Cart items and total cost & count
   protected $_content = array();
   
   // Private clone method
   private function __clone(){}
   
   // Private wakeup method
   private function __wakeup(){}
   
   // Protect construct method
   private function __construct($config = 'default')
   {
      // Load configuration
      $this->_config = Kohana::$config->load('cart')->get($config);
      // Load Session object
      $this->_session = Session::instance($this->_config['session_type']);
      // Grab the shopping cart array from the session table, if it exists
      if ( ! $this->_content = $this->_session->get($this->_config['session_key'], FALSE))
      {
         // No cart exists so we'll set some base values
         $this->_content = array(
            'products' => array(),
            'total'    => array('cost' => 0, 'count' => 0),
         );
      }
   }
   
   // Get instance of class
   public static function instance($config = NULL)
   {
      if (is_null(self::$_instance) OR ! empty($config))
      {
         self::$_instance = new self();
      }
      return self::$_instance;
   }
   
   /**
    * Magic Get to config & content
    *
    * $cart->config->template_short
    * $cart->content->products
    */
   public function __get($key)
   {
      if (array_search($key, array('config', 'content')) !== FALSE)
      {
         return $this->{'_'.$key};
      }
   }
   
   // Save cart content
   protected function _save()
   {
      $this->_session->set(
         $this->_config['session_key'],
         $this->_content,
         $this->_config['session_lifetime']
      );
   }
   
   // Generate complete id
   protected function _get_id($id, array $options = array())
   {
      foreach ($options as $key => $value)
      {
         $id .= '_'.$key.':'.$value;
      }
      return $id;
   }
   
   // Set new total values
   protected function _set_total()
   {
      $this->_content['total'] = array('cost' => 0, 'count' => 0);
      foreach ($this->_content['products'] as $product)
      {
         $this->_content['total']['cost']  += $product['price'] * $product['qty'];
         $this->_content['total']['count'] += $product['qty'];
      }
   }
   
   /**
    * Get product with options from database
    * TODO: add options
    */
   protected function _get_product($id, array $options = array())
   {
      // Create model only when it's needed
      if ( ! is_object($this->_model_product))
      {
         $this->_model_product = ORM::factory($this->_config['model_product']);
      }
      $this->_model_product->select(
                        array($this->_config['model_columns']['id'],    'id'),
                        array($this->_config['model_columns']['name'],  'name'),
                        array($this->_config['model_columns']['price'], 'price'),
                        array($this->_config['model_columns']['gty'],   'gty')
                     )
                     ->where($this->_config['model_columns']['id'], '=', $id)
                     ->find();
      
      if ($this->_model_product->loaded())
      {
         return Arr::extract($this->_model_product->as_array(), array_keys($this->_config['model_columns']));
      }
      else
      {
         throw new Kohana_Exception('Product with id :id not found', array(':id' => HTML::chars($id)));
         //ORM_Validation_Exception
      }
   }
   
   // Set product(s) from cart content
   public function set($id, $qty = 1, array $options = array())
   {
      $qty = max(1, (int)$qty);
      $cart_id = $this->_get_id($id, $options);
      $product = $this->_get_product($id, $options);
      if ($product['qty'] >= $qty)
      {
         if (isset($this->_content['products'][$cart_id]))
         {
            if ($product['qty'] >= ($this->_content['products'][$cart_id]['qty'] + $qty))
            {
               $this->_content['products'][$cart_id]['qty'] += $qty;
            }
            else
            {
               throw new Kohana_Exception('In stock only :qty items', array(':qty' => $product['qty']));
            }
         }
         else
         {
            $product['qty'] = $qty;
            $this->_content['products'][$cart_id] = $product;
         }
      }
      else
      {
         throw new Kohana_Exception('In stock only :qty items', array(':qty' => $product['qty']));
      }
      // Save changes
      $this->_set_total();
      $this->_save();
      return $this;
      
   }
   
   // Get product(s) from cart content
   public function get($id = NULL, array $options = array())
   {
      if (empty($id))
      {
         // Get all
         return $this->_content['products'];
      }
      else
      {
         // Get one
         $id = $this->_get_id($id, $options);
         return $this->_content['products'][$id];
      }
   }
   
   // Delete products
   public function delete($id = NULL, array $options = array())
   {
      if (empty($id))
      {
         // Delete all
         $this->_content = array(
            'products' => array(),
            'total'    => array('cost' => 0, 'count' => 0),
         );
      }
      else
      {
         // Delete item
         $id = $this->_get_id($id, $options);
         unset($this->_content['products'][$id]);
         $this->_set_total();
      }
      // Save changes
      $this->_save();
      return $this;
   }
   
}

_________________
Майкл Джордан играет в баскетбол. Чарльз Мэнсон убивает людей. Я пишу код. У каждого свой талант.


Последний раз редактировалось WinterSilence 12 июн 2013, 01:01, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: ORM один ко многим
СообщениеДобавлено: 12 июн 2013, 00:33 
Не в сети
Бывалый
Аватара пользователя

Зарегистрирован: 02 апр 2013, 16:26
Сообщения: 474
Откуда: Сергиев Посад
Код:
<?php defined('SYSPATH') or die('No direct access allowed.');
 
class Model_Product extends ORM
{
   protected $_table_name  = 'products';
   protected $_primary_key = 'id';
   protected $_db_group    = 'default';
   
   public function rules()
   {
      return array(
         'name' => array(
            array('not_empty'),
            array('min_length', array(':value', 2)),
            array('max_length', array(':value', 250)),
            array('regex', array(':value', '/^[-\pL\pN_.]++$/uD')),
         ),
         'price' => array(
            array('numeric', array(':value')),
            array('range', array(':value', 0, 1000000)),
            //array('decimal', array(':value')),
         ),
         'gty' => array(
            array('numeric', array(':value')),
            array('range', array(':value', 0, 10000)),
            //array('digit', array(':value', TRUE)),
         ),
      );
   }
   
}


Код:
<?php defined('SYSPATH') or die('No direct script access.');

return array(
   'default' => array(
      'session_lifetime' => Date::WEEK/2,
      'session_type'     => Session::$default,
      'session_key'      => 'shop_cart',
      'template_short'   => 'cart'.DIRECTORY_SEPARATOR.'short', // widget template
      'template_main'    => 'cart'.DIRECTORY_SEPARATOR.'main',  // page template
      'model_product'    => 'Product',                          // orm model, used to search products info
      'model_columns' => array(
         /**
          * id:    id or sku
          * name:  name
          * price: price
          * gty:   quantity
          */
         'id'    => 'id',
         'name'  => 'name',
         'price' => 'price',
         'gty'   => 'gty',
      ),
   ),
);

_________________
Майкл Джордан играет в баскетбол. Чарльз Мэнсон убивает людей. Я пишу код. У каждого свой талант.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: ORM один ко многим
СообщениеДобавлено: 12 июн 2013, 00:35 
Не в сети
Бывалый
Аватара пользователя

Зарегистрирован: 02 апр 2013, 16:26
Сообщения: 474
Откуда: Сергиев Посад
Код:
<?php defined('SYSPATH') or die('No direct script access.');

if ( ! Route::cache())
{
   Route::set('cart', 'cart(/<controller>(/<act>(/<id>)))(/)',
      array(
         'controller' => '(short|main)',
         'act'        => '(delete|clear|add)',
         'id'         => '[a-zA-Z0-9_\-]+',
      ))
      ->defaults(array(
         'directory'  => 'Cart',
         'controller' => 'Main',
         'action'     => 'index',
      ));
   Route::cache(Kohana::$caching);
}



Цитата:
--
-- Структура таблицы `products`
--
CREATE TABLE IF NOT EXISTS `products` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`price` float DEFAULT '0',
`gty` int(11) DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

_________________
Майкл Джордан играет в баскетбол. Чарльз Мэнсон убивает людей. Я пишу код. У каждого свой талант.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: ORM один ко многим
СообщениеДобавлено: 12 июн 2013, 00:38 
Не в сети
Бывалый
Аватара пользователя

Зарегистрирован: 02 апр 2013, 16:26
Сообщения: 474
Откуда: Сергиев Посад
view Main
Код:
<div id="cart_main">
   
   <h3><?= __('Shopping Cart'); ?></h3>
   
   <div class="clear"><?= HTML::anchor(Route::url('cart', array('act' => 'clear')), __('Clear')); ?></div>
   
   <?= Form::open(Route::url('cart')); ?>
   
   <table class="tbl">
      <tr>
         <th><?= __('Name'); ?></th>
         <th><?= __('Price'); ?></th>
         <th><?= __('Quantity'); ?></th>
         <th></th>
      </tr>
      <? foreach ($cart['products'] as $key => $product): ?>
      <tr>
         <td class="name"><?= $product['name']; ?></td>
         <td class="price"><?= $product['price']; ?></td>
         <td class="qty"><?= Form::input("cart[{$key}]", $product['qty']; ?></td>
         <td class="del"><?= HTML::anchor(Route::url('cart', array('act' => 'delete', 'id' => $key)),
                        HTML::image('media/img/delete.png', array('alt' => 'Delete'))); ?></td>
      </tr>
      <? endforeach; ?>
   </table>
   
   <div class="update"><?= Form::submit('update', __('Update')); ?></div>
   
   <div class="total">
      <div><?= __('Total cost'); ?>:<b id="cart_total_cost"><?= $cart['total']['cost']; ?></b></div>
      <div><?= __('Total count'); ?>:<b id="cart_total_count"><?= $cart['total']['count']; ?></b></div>
   </div>
   
   <div class="checkout"><?= Form::submit('checkout', __('Checkout')); ?></div>
   
   <?= Form::close(); ?>
   
</div>


view Short
Код:
<div id="cart_short">
   <div class="empty">
      <h3><?= __('Shopping Cart'); ?></h3>
      <div><?= __('Total cost'); ?>:<b id="cart_total_cost"><?= $total['cost']; ?></b></div>
      <div><?= __('Total count'); ?>:<b id="cart_total_count"><?= $total['count']; ?></b></div>
      <div><?= HTML::anchor(Route::url('cart'), __('Go to cart')); ?></div>
   </div>
</div>

_________________
Майкл Джордан играет в баскетбол. Чарльз Мэнсон убивает людей. Я пишу код. У каждого свой талант.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: ORM один ко многим
СообщениеДобавлено: 12 июн 2013, 05:48 
Не в сети
Бывалый
Аватара пользователя

Зарегистрирован: 23 июл 2012, 21:58
Сообщения: 100
Интересный подход, посмотрим.
Касаемо прошлой беседы...
Цитата:
почему ты уверен что он у тебя каждый раз новый создается?

Ну а как еще? Это же ООП.
Цитата:
из зачем его каждый раз создавать когда можно модель просто очистить, это менее ресурсоемкий процесс

Опять не верно, объект можно либо создать через new либо уничтожить через unset.
И все другие варианты ведут через эти две основные функции, поправьте если ошибаюсь.
Цитата:
так хрен знает чем он вызван

В принципе $this->pk() и есть родное, просто я ожидал более автоматический способ.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: ORM один ко многим
СообщениеДобавлено: 12 июн 2013, 09:14 
Не в сети
Бывалый
Аватара пользователя

Зарегистрирован: 02 апр 2013, 16:26
Сообщения: 474
Откуда: Сергиев Посад
ненене, девид блейн, нененене...

Если на доступных тебе примерах, то тебя мама отправила ковер выбить, а ты пошел его и на.. сжёг, потом пошел и купил новый. в итоге дома конечно лежит теперь чистый ковер и от мамы ты пилюлей не получишь, но это какой-то трешак..

Цитата:
Опять не верно, объект можно либо создать через new либо уничтожить через unset.

не верно конечно:
$fig = Fig; // при наличии у класса Fig public static function Tebe()
$fig = NULL; или $fig = 'Vam';// а так "удаляем"

хотя не понимаю почему ты решил, что тебе нужно именно новые объекты создавать всегда, ты же при каждом запросе не создаешь вначале объект через ORM::factory (ну ну я на это надеюсь), тем более мне не понятно как ты не смотрев код понял, что у тебя там постоянно новый объект создается.

_________________
Майкл Джордан играет в баскетбол. Чарльз Мэнсон убивает людей. Я пишу код. У каждого свой талант.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: ORM один ко многим
СообщениеДобавлено: 12 июн 2013, 10:16 
Не в сети
Бывалый
Аватара пользователя

Зарегистрирован: 23 июл 2012, 21:58
Сообщения: 100
Цитата:
хотя не понимаю почему ты решил, что тебе нужно именно новые объекты создавать всегда, ты же при каждом запросе не создаешь вначале объект через ORM::factory (ну ну я на это надеюсь), тем более мне не понятно как ты не смотрев код понял, что у тебя там постоянно новый объект создается.

Хорошо, может я не понимаю всей глубины происходящего и от этого не так выражаюсь..
Пойдем поэтапно, возможно так мы закончим дисскусию и получим левел ап.
Сейчас у меня так:
Код:
$order = ORM::factory('order');
$order->values($data);
try{
     $order->save();
     foreach($this->cart as $c){
           $items = $order->items;
           $item['order_id']        = $order->pk();
           $item['product_id']     = $c['p']->id;
           $item['product_price'] = $c['p']->price;
           $item['material_id']     = $c['m']->id;
           $item['material_price'] = $c['m']->price;
           $items->values($item)->save();
       }........

Все вроде бы логично и все работает.
Если я уберу, из-за чего и создалась тема...
Код:
$item['order_id']        = $order->pk();

то в таблицу orders_items в поле order_id будет пусто, значение не передается.
Напомню, связь от orders идет "один ко многим" к orders_items через поле order_id в таблице orders_items
Если я сделаю так:
Код:
$order = ORM::factory('order');
$order->values($data);
try{
     $order->save();
     $items = $order->items; //Вынес перед циклом
     foreach($this->cart as $c){
           //Вынес перед циклом
           $item['order_id']        = $order->pk();
           $item['product_id']     = $c['p']->id;
           $item['product_price'] = $c['p']->price;
           $item['material_id']     = $c['m']->id;
           $item['material_price'] = $c['m']->price;
           $items->values($item)->save();
       }........

то в таблицу orders_items будет писать только последние данные обработанные циклом.
Я просто не вижу другого выхода как поместить обращение к связи в цикле, да и логично вроде как.
Теперь про ООП, что происходит при вызове связи?
Код:
$items = $order->items;

На сколько могу судить - создается новый пустой объект, разве нет?
..а после сейва уничтожается.. предполагаю..


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: ORM один ко многим
СообщениеДобавлено: 12 июн 2013, 11:01 
Не в сети
Бывалый
Аватара пользователя

Зарегистрирован: 05 июн 2012, 03:08
Сообщения: 213
Думаю для цены нужно использовать не float, а decimal

`price` decimal(10,2) NOT NULL DEFAULT '0.00',

_________________
http://de-en.info (работает на Kohana 3.3)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: ORM один ко многим
СообщениеДобавлено: 12 июн 2013, 11:43 
Не в сети
Бывалый
Аватара пользователя

Зарегистрирован: 02 апр 2013, 16:26
Сообщения: 474
Откуда: Сергиев Посад
borodatych> по поводу вынести из цикла я погорячился, очистка данных в принципе равнозначна, но все таки давай прокачаем левел т.к. ты думаешь что при
Цитата:
$items = $order->items;

создается новый объект, а это не так - этим действием ты просто копируешь пустую(т.е. с незаполненными полями данных) модель, которая храниться в этой псевдо переменной, далее ты в эту модель передаешь данные и сохраняешь.
Цитата:
то в таблицу orders_items будет писать только последние данные обработанные циклом.

так происходит потому, что данные из модели после сохранения не удаляются т.е. на самом деле записывается первая запись, потом т.к. ты не скидываешь id в NULL остальные данные записываются в тот же кортеж(строку).
тут есть еще один подвох с использованием save, т.к. id не передается, то данные будут всегда только добавляться и никогда не обновляться.

AmberLEX> это не рабочий вариант, скорее пример. допилю до рабочей версии и скину на гит для дальнейшего развития. вообще очень странно, что такой маленький набор модулей для коханы, например аналогов этого модуля я не нашел, хотя в том же codeigniter такой класс есть в базовой сборке

_________________
Майкл Джордан играет в баскетбол. Чарльз Мэнсон убивает людей. Я пишу код. У каждого свой талант.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 38 ]  На страницу Пред.  1, 2, 3, 4  След.

Часовой пояс: UTC + 4 часа [ Летнее время ]


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 13


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Все о фреймворке Kohana  | 
Powered by phpBB® Forum Software © phpBB Group