… дальше остается только решить проблему возросшего количества уровней абстракции. Которую мы решим введением еще одного уровня абстракции. Whait… oh, shi…
Допустим у нас есть объект — курсор из субд. Но мы хотим расширить его, для возвращения объектов. Добавить метод next_object(), который будет использовать метод getNext()
Проблема:
Мы не можем заставить модель возвращать объекты другого типа.
Решение 1: сделать итератор на этот курсор(который тоже является итератором). Сделать много магии для методов и свойств и получить новый итератор с нужным нам свойством.
Решение 2: Для PHP 5.4.0, использовать анонимные функции. О нём я и расскажу:
Внутри мапера, в методе findWhere($where) сделаем добавление анонимной функции в курсор, с передачей колбека и самого курсора
/** * @return MongoCursor */ public function findWhere($where) { $collection=$this->collection->find($where); $callback=$this; $collection->next_object=function() use ($collection, $callback) { $data=$collection->getNext(); $obj=$callback->create_object($data); return ($obj); }; return ($collection); }
Теперь, по идее можно обращаться к $collection->next_object() и получать объект, созданный мапером. Но к сожалению это не работает, т.к. PHP попробует выполнить user_func_array и не найдёт метод. Для этого присваиваем свойство переменной, значение которого является анонимной функцией и выполняем, через $func():
public function findOneWhere($where) { $collection=$this->findWhere($where); $func=$collection->next_object; return ($func()); }
Кривенько, но работает.
Читаю книжку по руби и потихоньку делаю домашние задания.
На первой неделе узнал синтаксис руби, работу с объектами, методами, переопределение методов, регулярки, работу со строками, массивами. Научился запускать руби программы =)
Материал достаточно тяжёлый.
Руби зохавал часов 9 моего времени на этой неделе.
За домашку срезают баллы на 50%, если прощёлкал дедлайн:
Питон же, простой как 3 копейки (пока) =)
Осилил unit 1 , unit 2. Сложность — школьный уровень(первые 2 занятия)
Питон отнял 3 часа на этой неделе.
работа со строками, процедуры, рекурсии. Как результат — научились добывать из html кода ссылки =)
Удачного дня!
Первый уровень — фасад, которому передаются команды(понятные пользователю. например: удали запись №10) на выполнение
Второй уровень — уровень модели предметной области(он содержит фасады и сервисы отражающие сущности предметной области. например: публикация, комментарий, страница, пользователь).
Третий уровень — месиво из разных паттернов, для предоставления информации и выполнения операций. Обычно в этом уровне ацкий ад, который приходится часто рефакторить.
Фреймворк CodeIgniter из коробки позволяет расположить контроллеры только в одноуровневой папке: dir/file/class/params
Порой случается нужно сделать dir многоуровневой, например: admin/panel/sites/user/add
При попытке обратиться к странице получим ошибку, файл контроллера не найден.
Решение (для CI 2.0, 2.1):
Создать файл /application/core/MY_Router.php
Скопировать в него:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * MY_Router Class * * An extension to the core router class to allow controllers to be in multi-level directories. * * @package Router * @version 1.0 * @author Damien K. * @copyright Copyright (c) 2010, Ollie Rattue * @license http://www.opensource.org/licenses/mit-license.php * @link https://github.com/ollierattue/codeigniter-multi-level-controller-extension */ class MY_Router extends CI_Router { // -------------------------------------------------------------------- /** * OVERRIDE * * Validates the supplied segments. Attempts to determine the path to * the controller. * * @access private * @param array * @return array */ function _validate_request($segments) { if (count($segments) == 0) { return $segments; } // Does the requested controller exist in the root folder? if (file_exists(APPPATH.'controllers/'.$segments[0].EXT)) { return $segments; } // Is the controller in a sub-folder? if (is_dir(APPPATH.'controllers/'.$segments[0])) { // @edit: Support multi-level sub-folders $dir = ''; do { if (strlen($dir) > 0) { $dir .= '/'; } $dir .= $segments[0]; $segments = array_slice($segments, 1); } while (count($segments) > 0 && is_dir(APPPATH.'controllers/'.$dir.'/'.$segments[0])); // Set the directory and remove it from the segment array $this->set_directory($dir); // @edit: END // @edit: If no controller found, use 'default_controller' as defined in 'config/routes.php' if (count($segments) > 0 && ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].EXT)) { array_unshift($segments, $this->default_controller); } // @edit: END if (count($segments) > 0) { // Does the requested controller exist in the sub-folder? if (!file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].EXT)) { // show_404($this->fetch_directory().$segments[0]); // @edit: Fix a "bug" where show_404 is called before all the core classes are loaded $this->directory = ''; // @edit: END } } else { // Is the method being specified in the route? if (strpos($this->default_controller, '/') !== FALSE) { $x = explode('/', $this->default_controller); $this->set_class($x[0]); $this->set_method($x[1]); } else { $this->set_class($this->default_controller); $this->set_method('index'); } // Does the default controller exist in the sub-folder? if (!file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller.EXT)) { $this->directory = ''; return array(); } } return $segments; } // If we've gotten this far it means that the URI does not correlate to a valid // controller class. We will now see if there is an override if (!empty($this->routes['404_override'])) { $x = explode('/', $this->routes['404_override']); $this->set_class($x[0]); $this->set_method(isset($x[1]) ? $x[1] : 'index'); return $x; } // Nothing else to do at this point but show a 404 show_404($segments[0]); } // -------------------------------------------------------------------- /** * OVERRIDE * * Set the directory name * * @access public * @param string * @return void */ function set_directory($dir) { $this->directory = str_replace(array('.'), '', $dir).'/'; // @edit: Preserve '/' } // -------------------------------------------------------------------- }
Благодарность https://github.com/ollierattue/codeigniter-multi-level-controller-extension
такая штука работает.
апдейтим не константой, а значением из другой таблицы, сопоставляя ID
UPDATE a SET field1=b.field1 FROM b WHERE b.feld2=a.field2
Многобуков. Всё под катом.
Мой проект. win2win.
Вам: удобный движок для управления рекламой всех своих сайтов из одного места. с суппортом и помощью.
Мне: Формирую детальный каталог по рекламодателям и предлагаю регистрацию по реф ссылкам.
Описание:
плюсы:
минусы:
Причина создания: устал возиться с openx. Сложно, избыточно, медленно.
Версия стабильна, имеется инсталлятор, приглашаю начать использовать в бетта режиме http://iako.ru
Предложите решение в комментах.
Задача: хранить Игроков
Варианты решения 3 штуки(смотри картинки снизу. Слева объектная структура данных, справа способ хранения):
1. В одной таблице
2. Разделять по типам игроков и хранить в «типизированных» таблицах
3. Смешанный стиль — одинаковую информацию в главной таблице и типизированную информацию в типизированных таблицах
