Гуру, я не знаю что такое MVC в PHP, хоть и считаю себя опытным программистом. Объясните наконец!

Активист

Активист
Команда форума
> MVC это способ выделения слоев приложения
Что такое способ?))) Какой способ? Причем здесь способ. Причем здесь слои?
Слой - это слой, а алогоритм это алгоритм. SSL слой, HTTP слой.

> выделения слоев приложения
Есть такое понятние - детализация объекта, скорее это, чем MVC.

Что под MVC в моем понимание:

PHP:
<?php
class controller {
	/**
	 * Enter description here ...
	 * @var int
	 */
	private $currentSize = null;
	/**
	 * Enter description here ...
	 * @var model
	 */
	private $model;

	/**
	 * Enter description here ...
	 * @var view
	 */
	private $view;
	
	protected $store = "html";
	
	/** 
	 * Enter description here ...
	 * @return bool
	 */
	public function interation() {
		$socketID = curl_init("http://informer.gismeteo.ru/xml/30710_1.xml");
			
		curl_setopt($socketID, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($socketID, CURLOPT_HEADER, 0);
		curl_setopt($socketID, CURLOPT_COOKIE, 0);
		curl_setopt($socketID, CURLOPT_TIMEOUT, 3);
			
		$siteContent = curl_exec($socketID);
		curl_close($socketID);
		
		if ($siteContent !== false) {
			if ($this->currentSize !== strlen($siteContent)) {
				// data change
				if ($this->model()->parce($siteContent)) {
					$this->view()->render($this->model);
					return true;
				} 
				$this->currentSize =  strlen($siteContent);
			}
		}
		
		return false;
	}
	
	/**
	 * 
	 * Enter description here ...
	 * @return model
	 */
	public function model() {
		if (!$this->model instanceof model) {
			$this->model = new model();
		}
		
		return $this->model;
	}
	
	/**
	 * Enter description here ...
	 * @return iView 
	 */
	public function view() {
		switch ($this->store) {
			case "html": return new view_html();
			case "php": return new view_php();
		}
	}
}

class model {
	/**
	 * 
	 * Enter description here ...
	 * @var array
	 */
	public $data = array();
	
	public function parce($siteContent) {
		$xml_parser = xml_parser_create();
			
		xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 0);
		xml_parser_set_option($xml_parser, XML_OPTION_SKIP_WHITE, 1);
		xml_parser_set_option($xml_parser, XML_OPTION_SKIP_TAGSTART, 0);
		xml_parse_into_struct($xml_parser, $siteContent, $infoWeather, $index);
			
		// Today
		$data	= array();
		$day	= 0;
		$weekDaysArray	= array("empty", "ВС", "ПН", "ВТ", "СР", "ЧТ", "ПТ", "СБ");
		$todsDaysArray	= array("ночь", "утро", "день", "вечер");
			
		while ($day < 4) {
			$fIndex = $index['FORECAST'][$day * 2];
			$tIndex	= $index['TEMPERATURE'][$day];
			$pIndex	= $index['PHENOMENA'][$day];
				
			$weekDay  = $infoWeather[$fIndex]['attributes']['weekday'];
			$todIndex = $infoWeather[$fIndex]['attributes']['tod'];
				
			$data[$day]['date'] 		= (strlen($infoWeather[$fIndex]['attributes']['day']) == 1 ? 0 : "").$infoWeather[$fIndex]['attributes']['day'].".".(strlen($infoWeather[$fIndex]['attributes']['month']) == 1 ? 0 : "").$infoWeather[$fIndex]['attributes']['month'];
			$data[$day]['weekday']		= $weekDaysArray[$weekDay];
			$data[$day]['temperature']	= $infoWeather[$tIndex]['attributes']['max']." / ".$infoWeather[$tIndex]['attributes']['min'];
			$data[$day]['tod']			= $todsDaysArray[$todIndex];
			$data[$day]['phenomena']	= $infoWeather[$pIndex]['attributes']['precipitation'];
				
			$day++;
		}
	
		$this->data = $data;
		return true;
	}
}

interface iView {
	public function render(model $mode);
}

class view_php implements iView{
	public function render(model $model) {
		return file_put_contents("serialized.cache", serialize($model->data));
		
	}
}

class view_html implements iView{
	public function render(model $model) {
		$html = "<table>";
		foreach ($model->data as $day) {
			$html .= "<tr><td>{$day['date']}</td><td>{$day['weekday']}</td><td>{$day['temperature']}</td><td>{$day['tod']}</td><td>{$day['phenomena']}</td>";
		}
		$html .= "</table>";
		return file_put_contents("html.cache", $html);
	}	
}


$controller = new controller(); 
while (true) {
	$controller->interation();
	sleep(10);
}

?>
 

symfo

Новичок
Мне кажется, что спор идет о том, как назвать инструмент, вместо того, чтоб обсудить как им лучше пользоваться :).
Но прочитал всю тему с интересом.
Меня несколько удивляет, что вроде бы опытные люди, а говорят странные вещи про MVC, что его чуть ли не существует в Web и в PHP в частвности.
MVC - это просто слой абстракции, способ упорядочить разработку приложения и его представление в уме программиста. Все остальное - это уже дело инструментов и техники.
И совсем не обязательно юзать именно MVC, можно разработать и использовать свой слой абстракции. Например, можно представить себе несложное приложение, условно изобразив в уме все его объекты и взаимосвязи в виде четырехмерной модели. Т.е. 3 измерения описывают "пространственную архитектуру" (объекты со всеми взаимосвязями), а четвертое - это изменение состояний системы во времени. И "понаблюдать" за ней. Тогда можно выделить различные слои абстракции, и не факт, что это будет MVC. Но какое-то разделение будет все равно. Причем даже в MVC, порой, можно каждый из компонентов (M, V, C) разделить еще на более мелкие абстракции, и так до того момента, когда подобное деление начинает терять смысл и только усложняет разработку, т.е. найти золотую середину.
Зачем пытаться натянуть абстракцию, касающуюся одного языка на другой? MVC в C++ !== MVC в PHP, и это нормально. Но и там и там она возможна и она есть. Убедиться в этом можно плотно поработав с полноценным MVC-фреймворком, таким как Yii или symfony.

Что касается требования знаний MVC при приеме на работу, так зачастую они вполне обоснованы. Т.к. скорее всего придется работать с MVC фреймворком. И тут дело не в дани моде, а в способе организации коллективной разработки. Грамотно организованная MVC платформа в этом очень помогает, т.к. позволяет очень гибко разделять работу между разработчиками.

В соседней теме я описал структуру каталогов симфони. Тут хотелось бы дополнить ее конкретным примером использования, показать реализацию MVC средствами симфони.
 

symfo

Новичок
Пришлось разделить на несколько постов :).

Model
PHP:
// lib/model/doctrine/base/BaseContainer.class.php
abstract class BaseContainer extends sfDoctrineRecord
{
    public function setTableDefinition()
    {
        $this->setTableName('container');
        $this->hasColumn('id', 'integer', 11, array(
             'type'          => 'integer',
             'primary'       => true,
             'unsigned'      => true,
             'autoincrement' => true,
             'length'        => 11,
             ));
        $this->hasColumn('name', 'string', 128, array(
             'type'    => 'string',
             'notnull' => true,
             'length'  => 128,
             ));
        $this->hasColumn('keywords', 'string', 250, array(
             'type'    => 'string',
             'notnull' => true,
             'length'  => 250,
             ));
        $this->hasColumn('comment', 'string', 1000, array(
             'type'   => 'string',
             'length' => 1000,
             ));
        $this->hasColumn('user_id', 'integer', 8, array(
             'type'     => 'integer',
             'unsigned' => true,
             'notnull'  => true,
             'length'   => 8,
             ));
        $this->hasColumn('is_shared', 'boolean', null, array(
             'type'    => 'boolean',
             'notnull' => true,
             'default' => 1,
             ));
        $this->hasColumn('created_at', 'timestamp', null, array(
             'type'    => 'timestamp',
             'notnull' => true,
             ));
        $this->hasColumn('updated_at', 'timestamp', null, array(
             'type'    => 'timestamp',
             'notnull' => true,
             ));


        $this->index('idx_name', array(
             'fields' => array(
              0 => 'name',
             ),
             ));
        $this->index('idx_user', array(
             'fields' => 
             array(
              0 => 'user_id',
             ),
             ));
        $this->index('idx_shared', array(
             'fields' => 
             array(
              0 => 'is_shared',
             ),
             ));
        $this->option('charset', 'utf8');
        $this->option('collate', 'utf8_general_ci');
    }

    public function setUp()
    {
        parent::setUp();
        $this->hasOne('User', array(
             'local'    => 'user_id',
             'foreign'  => 'id',
             'onDelete' => 'cascade'));

        $timestampable0 = new Doctrine_Template_Timestampable();
        $this->actAs($timestampable0);
    }
}


// lib/model/doctrine/Container.class.php
class Container extends BaseContainer
{
  public function save(Doctrine_Connection $conn = null)
  {
    if($this->isNew() && !$this->user_id)
    {
      $this->setUserId(sfContext::getInstance()->getUser()->getAttribute('user_id'));
    }
    parent::save($conn);
  }
}


// lib/form/doctrine/BaseContainerForm.class.php
abstract class BaseContainerForm extends BaseFormDoctrine
{
  public function setup()
  {
    $this->setWidgets(array(
      'id'         => new sfWidgetFormInputHidden(),
      'name'       => new sfWidgetFormInputText(),
      'keywords'   => new sfWidgetFormInputText(),
      'comment'    => new sfWidgetFormTextarea(),
      'is_shared'  => new sfWidgetFormInputCheckbox(),
    ));

    $this->setValidators(array(
      'id'         => new sfValidatorChoice(array('choices' => array($this->getObject()->get('id')), 'empty_value' => $this->getObject()->get('id'), 'required' => false)),
      'name'       => new sfValidatorString(array('max_length' => 128)),
      'keywords'   => new sfValidatorString(array('max_length' => 250, 'required' => false)),
      'comment'    => new sfValidatorString(array('max_length' => 1000, 'required' => false)),
      'is_shared'  => new sfValidatorBoolean(array('required' => false)),
    ));

    $this->widgetSchema->setLabels(array(
      'is_shared'   => 'Share',
      'keywords'    => 'Search keywords',
    ));

    $this->widgetSchema->setNameFormat('container[%s]');
    $this->errorSchema = new sfValidatorErrorSchema($this->validatorSchema);
    $this->setupInheritance();
    parent::setup();
  }

  public function getModelName()
  {
    return 'Container';
  }
}

// lib/filter/doctrine/base/BaseContainerFormFilter.class.php
abstract class BaseContainerFormFilter extends BaseFormFilterDoctrine
{
  public function setup()
  {
    $this->setWidgets(array(
      'name'       => new sfWidgetFormFilterInput(array('with_empty' => false)),
      'keywords'   => new sfWidgetFormFilterInput(),
      'comment'    => new sfWidgetFormFilterInput(),
      'user_id'    => new sfWidgetFormDoctrineChoice(array('model' => $this->getRelatedModelName('User'), 'add_empty' => true)),
      'is_shared'  => new sfWidgetFormChoice(array('choices' => array('' => 'yes or no', 1 => 'yes', 0 => 'no'))),
      'created_at' => new sfWidgetFormFilterDate(array('from_date' => new sfWidgetFormDate(), 'to_date' => new sfWidgetFormDate(), 'with_empty' => false)),
      'updated_at' => new sfWidgetFormFilterDate(array('from_date' => new sfWidgetFormDate(), 'to_date' => new sfWidgetFormDate(), 'with_empty' => false)),
    ));

    $this->setValidators(array(
      'name'       => new sfValidatorPass(array('required' => false)),
      'keywords'   => new sfValidatorPass(array('required' => false)),
      'comment'    => new sfValidatorPass(array('required' => false)),
      'user_id'    => new sfValidatorDoctrineChoice(array('required' => false, 'model' => $this->getRelatedModelName('User'), 'column' => 'id')),
      'is_shared'  => new sfValidatorChoice(array('required' => false, 'choices' => array('', 1, 0))),
      'created_at' => new sfValidatorDateRange(array('required' => false, 'from_date' => new sfValidatorDateTime(array('required' => false, 'datetime_output' => 'Y-m-d 00:00:00')), 'to_date' => new sfValidatorDateTime(array('required' => false, 'datetime_output' => 'Y-m-d 23:59:59')))),
      'updated_at' => new sfValidatorDateRange(array('required' => false, 'from_date' => new sfValidatorDateTime(array('required' => false, 'datetime_output' => 'Y-m-d 00:00:00')), 'to_date' => new sfValidatorDateTime(array('required' => false, 'datetime_output' => 'Y-m-d 23:59:59')))),
    ));

    $this->widgetSchema->setNameFormat('container_filters[%s]');
    $this->errorSchema = new sfValidatorErrorSchema($this->validatorSchema);
    $this->setupInheritance();
    parent::setup();
  }

  public function getModelName()
  {
    return 'Container';
  }

  public function getFields()
  {
    return array(
      'id'         => 'Number',
      'name'       => 'Text',
      'keywords'   => 'Text',
      'comment'    => 'Text',
      'user_id'    => 'ForeignKey',
      'is_shared'  => 'Boolean',
      'created_at' => 'Date',
      'updated_at' => 'Date',
    );
  }
}
View
PHP:
// apps/myapp/module/container/templates/formSuccess.php
<form action="<?php echo url_for('container/'.($form->getObject()->isNew() ? 'create' : 'update').(!$form->getObject()->isNew() ? '?id='.$form->getObject()->getId() : '')) ?>" method="post" <?php $form->isMultipart() and print 'enctype="multipart/form-data" ' ?>>
<?php if (!$form->getObject()->isNew()): ?>
<input type="hidden" name="sf_method" value="put" />
<?php endif; ?>
  <table>
    <tfoot>
      <tr>
        <td colspan="2">
          <input type="submit" value="Save" />
        </td>
      </tr>
    </tfoot>
    <tbody>
      <?php echo $form ?>
    </tbody>
  </table>
</form>


// apps/myapp/module/container/templates/extendedShowSuccess.php
<table>
 <thead><th>Name</th><th>Keywords</th><th>Comment</th><th>Shared</th></thead>
 <tbody>
  <tr>
   <td><?php echo $container->name ?></td>
   <td><?php echo $container->keywords ?></td>
   <td><?php echo $container->comments ?></td>
   <td><?php echo ($container->is_shared == true ? 'Y' : 'N') ?></td>
  </tr>
 </tbody>
</table>
 

symfo

Новичок
Controller
PHP:
// apps/myapp/module/container/actions/actions.class.php
class containerActions extends sfActions
{
  public function executeShow(sfWebRequest $request)
  {
    $this->forward404Unless($request->getParameter('id') || $this->container = Doctrine_Core::getTable('Container')->find(array($request->getParameter('id')));
    $this->setTemplate('extendedShow');
  }

  public function executeNew(sfWebRequest $request)
  {
    $this->form = new ContainerForm();
  }

  public function executeCreate(sfWebRequest $request)
  {
    $this->forward404Unless($request->isMethod(sfRequest::POST));
    $this->form = new ContainerForm();
    $this->processForm($request, $this->form);
    $this->setTemplate('form');
  }

  public function executeEdit(sfWebRequest $request)
  {
    $this->forward404Unless($container = Doctrine::getTable('Container')->find(array($request->getParameter('id'))));
    $this->form = new ContainerForm($container);
    $this->setTemplate('form');
  }

  public function executeUpdate(sfWebRequest $request)
  {
    $this->forward404Unless($request->isMethod(sfRequest::POST) || $request->isMethod(sfRequest::PUT));
    $this->forward404Unless($container = Doctrine::getTable('Container')->find(array($request->getParameter('id'))));
    $this->form = new ContainerForm($container);
    $this->processForm($request, $this->form);
    $this->setTemplate('form');
  }

  protected function processForm(sfWebRequest $request, sfForm $form)
  {
    $form->bind($request->getParameter($form->getName()), $request->getFiles($form->getName()));
    if ($form->isValid())
    {
      $container = $form->save();

      $this->redirect('container/edit?id='.$container->getId());
    }
  }
}

// FRONT CONTROLLER
// web/index.php
require_once(dirname(__FILE__).'/../config/ProjectConfiguration.class.php');
$configuration = ProjectConfiguration::getApplicationConfiguration('myapp', 'dev', true);
sfContext::createInstance($configuration)->dispatch();
С первого взгляда кажется несколько громоздко, но вся прелесть в том, что все это сгенерировано автоматически по одному единственному файлу схемы. И работать с этим кодом очень быстро и удобно :).

config/doctrine/schema.yml
Код:
Container:
  connection: doctrine
  tableName: nutrient
  columns:
    id:
      type: integer(11)
      fixed: false
      unsigned: true
      primary: true
      autoincrement: true
    name:
      type: string(128)
      fixed: false
      unsigned: false
      primary: false
      notnull: true
      autoincrement: false
    comment:
      type: string(255)
      fixed: false
      unsigned: false
      primary: false
      notnull: false
      autoincrement: false
    user_id:
      type: integer(8)
      fixed: false
      unsigned: true
      primary: false
      notnull: true
      autoincrement: false
    is_shared:
      type: integer(1)
      fixed: false
      unsigned: false
      primary: false
      default: '1'
      notnull: true
      autoincrement: false
    created_at:
      type: timestamp(25)
      fixed: false
      unsigned: false
      primary: false
      notnull: true
      autoincrement: false
    updated_at:
      type: timestamp(25)
      fixed: false
      unsigned: false
      primary: false
      notnull: true
      autoincrement: false
  relations:
    User:
      local: user_id
      foreign: id
      type: one

User:
  connection: doctrine
  tableName: user
  columns:
    id:
      type: integer(8)
      fixed: false
      unsigned: true
      primary: true
      autoincrement: true
    name:
      type: string(50)
      fixed: false
      unsigned: false
      primary: false
      notnull: true
      autoincrement: false
    password:
      type: string(32)
      fixed: false
      unsigned: false
      primary: false
      notnull: true
      autoincrement: false
    salt:
      type: integer(4)
      fixed: false
      unsigned: false
      primary: false
      notnull: true
      autoincrement: false
    credentials:
      type: string()
      fixed: false
      unsigned: false
      primary: false
      notnull: true
      autoincrement: false
    is_active:
      type: integer(1)
      fixed: false
      unsigned: false
      primary: false
      default: '0'
      notnull: false
      autoincrement: false
    verification_code:
      type: string(32)
      fixed: true
      unsigned: false
      primary: false
      notnull: false
      autoincrement: false
    email:
      type: string(255)
      fixed: false
      unsigned: false
      primary: false
      notnull: true
      autoincrement: false
    created_at:
      type: timestamp(25)
      fixed: false
      unsigned: false
      primary: false
      notnull: true
      autoincrement: false
    updated_at:
      type: timestamp(25)
      fixed: false
      unsigned: false
      primary: false
      notnull: true
      autoincrement: false
  relations:
    Nutrient:
      local: id
      foreign: user_id
      type: many
Можно просто написать файл схемы, сгенерировать по нему SQL, создать БД с таблицами (или наоборот - создать БД и сгенерировать по ней файл схемы, что и сделано в данном случае), сгенерировать все файлы модели, формы, фильтры, модули со всеми экшенами и шаблонами, использовав для этого всего пару команд.
Руками были чуть поправлены лишь файлы шаблона и пару строк контроллера (для кастомного шаблона extendedShowSuccess).
 

Alien85

I like my cat
интересная реализация, но этот код капля в море.

Получается, вместо php кода нужно писать схемы, на основании которых, создается код? а потом править и тестировать созданный код?

Кстати, во View вы реально используете html код вместе со вставками php без шаблонизатора?
 

symfo

Новичок
интересная реализация, но этот код капля в море.
Ну не выкладывать же мне целый проект :). Просто реально работающий пример модуля.

Получается, вместо php кода нужно писать схемы, на основании которых, создается код? а потом править и тестировать созданный код?
Необязательно. Я часто вручную дописываю новые объекты модели, формы и т.д. Это совсем не сложно. Просто если речь идет о крупном проекте, то гораздо удобнее изначально продумать модель данных, написать схему и сгенерировать каркас (работающий!), а далее уже на его основе строить приложение. Можно использовать визуальный UML-билдер, а затем сгенерировать модель и все остальное. Или визуальный SQL-билдер, с плагином для генерации схемы симфони.

Кстати, во View вы реально используете html код вместе со вставками php без шаблонизатора?
А чем это плохо? Неудобство для дизайнера? Мне это неважно, т.к. с некоторых пор работаю самостоятельно. И шаблонизатор мне попросту не нужен. Хотя я мог бы прикрутить тот же твиг, но мне он как собаке пятая лапа :).
 

Adelf

Administrator
Команда форума
Получается, вместо php кода нужно писать схемы, на основании которых, создается код? а потом править и тестировать созданный код?
Нормальная практика работы с нормальной ORM.

Кстати, во View вы реально используете html код вместе со вставками php без шаблонизатора?
Стандартная практика.

symfo
Очень за тебя рад. Если бы ты еще что-то новое по теме высказал - то было бы прекрасно :)
 
  • Like
Реакции: craz

symfo

Новичок
Adelf, я не против :). Наоборот, конструктивное продолжение темы вижу скорее в обсуждении различных вариантов реализации MVC, возможно поиск других вариантов организации проектирования.
 

craz

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

symfo

Новичок
craz, а я люблю изобретать, пусть это иногда будут велосипеды, но они будут лучше аналогов :). Причем некоторые изобретения аж бегом растягиваются по сети.
Тем более я больше не работаю на "дядю" и не делаю проекты на заказ, могу себе позволить изобретательство :).
 

Alien85

I like my cat
я ничего не имею против, просто спросил. Спасибо за разъяснения.

craz, твои возгласы похожи на крики из толпы.
 

craz

Нестандартное звание
craz, а я люблю изобретать, пусть это иногда будут велосипеды, но они будут лучше аналогов :). Причем некоторые изобретения аж бегом растягиваются по сети.
Тем более я больше не работаю на "дядю" и не делаю проекты на заказ, могу себе позволить изобретательство :).
букву я применительно к себе лучше писать Я, тогда есть шанс поднять планку самооценки еще выше, это я к чему - без пруфлинков на >Причем некоторые изобретения аж бегом растягиваются по сети. ваше сообщение читается как бахвальство
 

craz

Нестандартное звание
я ничего не имею против, просто спросил. Спасибо за разъяснения.

craz, твои возгласы похожи на крики из толпы.
а ты похож на толпу) на толпу тех которые пишут что-то пипец невразумительное создавая свои велосипеды для каждого проекта, на которые потом без слез не взглянешь - много времени тратишь на форум уже бы успел написать новую парадигму
 

symfo

Новичок
букву я применительно к себе лучше писать Я, тогда есть шанс поднять планку самооценки еще выше
С самооценкой у меня все нормально и Фримана я тоже смотрел ;).
это я к чему - без пруфлинков на >Причем некоторые изобретения аж бегом растягиваются по сети. ваше сообщение читается как бахвальство
Пруфлинк на маркет.яндекс дать? :D Или на кучу инет магазинов-каталогов, использующих мои решения (не программирование, а способ организации работы некоторых вещей)? Доказать свое авторство я все равно не смогу, а без этого мои слова с пруфлинками будет выглядеть похуже бахвальства. А решения эти настолько распространенные, что стали по сути стандартными, так что без доказательств авторства обязательно найдутся те, кто захочет полить меня грязью и обвинить во лжи или скорее в недосмотре, что это было и раньше... на кой хрен это мне надо? Я просто знаю, что до моей реализации так не делал никто, по крайней мере ни у одного ресурса по теме я подобного решения не видел, хотя перекопал за те несколько лет далеко не одну тысячу магазинов и каталогов, выискивая хорошие идеи и придумывая то, чего не хватает. Хотя ничего сверхъестественного и не придумал, просто сделал то, что мне показалось очевидным, но видимо было не очевидно другим в тот момент. Быть может не я один все это придумал, и не у меня некоторые идеи зацепили, но я знаю, что применять я их начал первым. Тут уже фиг что выяснишь-докажешь наверняка. Да и лично мне не нужно это, себе я уже давно доказал, что умею придумывать новое и полезное, а доказывать это другим не вижу смысла.
Мне не жалко, что кто-то что-то у меня заимствовал, я так же заимствую идеи у других. Даже для яндекса не жалко :D, спасибо хоть магазин мой после этого сами, без запроса, добавили в свой каталог :).
 

Adelf

Administrator
Команда форума
symfo
Надеюсь ты понимаешь, что ы таком же стиле тут может высказаться абсолютно любой.. при желании конечно. Ну и если воспитание позволит :)
 

akd

dive now, work later
Команда форума
symfo, ну вот меня ты заинтриговал :) расскажи мне какие решения ты придумал, обещаю не ржать и грязью не поливать :)
 

symfo

Новичок
Я это говорил в контексте того, что изобретать велосипеды, порой бывает достаточно продуктивным занятием, по крайней мере лично для меня. Вот и все. А хвастаться чем-то я не собирался. Иначе говорил бы конкретно и давал бы ссылки.
А то, что каждый так может говорить - так это личное дело каждого, как и верить или нет.
И может все таки вернемся к обсуждению темы? А то оффтоп попер. :)
 

С.

Продвинутый новичок
Если избавиться от типичнейших ошибок в представлениях об MVC, то многое встанет на место.

-- Контроллер не может оперировать "новостями" или тому подобными вещами. Ему знать не положено об их существовавнии, это задача Модели. Контроллер оперирует исключительно "системный" или абстрактными понятиями как "страница" или "блок". Контроллер можно механически перенести из одного пректа в другой без переделки. Если при этом вам приходится вносить изменения в логику контроллера, то вы делаете что-то не то.

-- ШаблонИЗАТОР это не View!!! Шаблон(ы) -- View, шаблонизатор это часть контроллера.

-- Все что не View и не Контроллер это Модель.
 

rvolt

Новичок
-- ШаблонИЗАТОР это не View!!! Шаблон(ы) -- View, шаблонизатор это часть контроллера.
Разве к View не относится весь код, который отвечает непосредственно за построение представления? В том числе и код, который предварительно подготавливает данные, получаемые от модели для отображения в шаблоне (например, нестандартный колоночный вывод, линеаризация иерархии для вывода без рекурсивных вызовов)? Более того, в одном приложении могут использоваться несколько шаблонизаторов - резонно их отделять от совсем других задач, которые выполняет контроллер.

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

В задачи контроллера входит: обработка поступившего пользовательского запроса и выполнение требуемого действия, проверка прав доступа пользователя к странице, обработка исключительных ситуаций с последующим роутингом на страницу ошибок и т.д.

http://msdn.microsoft.com/en-us/library/ff649643.aspx
Я так понимаю, что автора дискуссии смутит следующее:
Controller. The controller interprets the mouse and keyboard inputs from the user, informing the model and/or the view to change as appropriate.
Но нажатие на ссылку в окне браузера с последующим переходом на другую страницу или Ajax-загрузкой HTML-блока - это и есть тот user input, о котором говорится во многих источниках. Только вся разница в том, что среда представления живет в другом адресном пространстве на машине клиента, но генерируется на стороне сервера.

Сам паттерн MVC уже давно перестал быть чисто SmalTalk-ким паттерном и был обобщен и урезан до того минимума, который позволит использоать его независимо от языка и стека используемых технологий.
 
  • Like
Реакции: craz
Сверху