Показаны сообщения с ярлыком MySQL. Показать все сообщения
Показаны сообщения с ярлыком MySQL. Показать все сообщения

воскресенье, 13 апреля 2008 г.

Вопросы и ответы

propel:

  _attributes:   { noXsd: false, defaultIdMethod: none, package: lib.model }

 

  ask_question:

    _attributes: { phpName: Question, idMethod: native }

    id:          { type: integer, required: true, primaryKey: true, autoIncrement: true }

    user_id:     { type: integer, foreignTable: ask_user, foreignReference: id }

    title:       { type: longvarchar }

    body:        { type: longvarchar }

    created_at:  ~

    updated_at:  ~

 

  ask_answer:

    _attributes: { phpName: Answer, idMethod: native }

    id:          { type: integer, required: true, primaryKey: true, autoIncrement: true }

    question_id: { type: integer, foreignTable: ask_question, foreignReference: id }

    user_id:     { type: integer, foreignTable: ask_user, foreignReference: id }

    body:        { type: longvarchar }

    created_at:  ~

 

  ask_user:

    _attributes: { phpName: User, idMethod: native }

    id:          { type: integer, required: true, primaryKey: true, autoIncrement: true }

    nickname:    { type: varchar(50), required: true, index: true }

    first_name:  varchar(100)

    last_name:   varchar(100)

    created_at:  ~

 

  ask_interest:

    _attributes: { phpName: Interest, idMethod: native }

    question_id: { type: integer, foreignTable: ask_question, foreignReference: id, primaryKey: true }

    user_id:     { type: integer, foreignTable: ask_user, foreignReference: id, primaryKey: true }

    created_at:  ~

 

  ask_relevancy:

    _attributes: { phpName: Relevancy, idMethod: native }

    answer_id:   { type: integer, foreignTable: ask_answer, foreignReference: id, primaryKey: true }

    user_id:     { type: integer, foreignTable: ask_user, foreignReference: id, primaryKey: true }

    score:       { type: integer }

    created_at:  ~

 

symfony propel-build-model 

symfony propel-build-sql 

mysql -u youruser -p prod < data/sql/lib.model.schema.sql 

symfony propel-insert-sql 

symfony propel-generate-crud frontend question Question 

symfony cc frontend config 

http://prod/question 

 


Шаблон

В apps/frontend/templates/layout.php) меняем:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

<head>

<?php echo include_http_metas() ?>

<?php echo include_metas() ?>

<?php echo include_title() ?>

<link rel="shortcut icon" href="/favicon.ico" />

</head>

<body>

  <div id="header">

    <ul>

      <li><?php echo link_to('about', '@homepage') ?></li>

    </ul>

    <h1><?php echo link_to(image_tag('prod_logo.gif', 'alt=prod'), '@homepage') ?></h1>

  </div>

  <div id="content">

    <div id="content_main">

      <?php echo $sf_data->getRaw('sf_content') ?>

      <div class="verticalalign"></div>

    </div>

    <div id="content_bar">

      <!-- Nothing for the moment -->

      <div class="verticalalign"></div>

    </div>

  </div>

</body>

</html>

Добавим стили в frontend/config/view.yml:

stylesheets:    [main, layout]

Переопределим default homepage


prod/apps/frontend/config/routing.yml:


homepage:

  url:   /

  param: { module: question, action: list }

Определим данные для теста


Создать prod/data/fixtures/

Создать test_data.yml:


User:

  anonymous:

    nickname:   anonymous

    first_name: Anonymous

    last_name:  Coward

  fabien:

    nickname:   fabpot

    first_name: Fabien

    last_name:  Potencier

  francois:

    nickname:   francoisz

    first_name: François

    last_name:  Zaninotto

Question:

  q1:

    title: What shall I do tonight with my girlfriend?

    user_id: fabien

    body:  |

      We shall meet in front of the Dunkin'Donuts before dinner, 

      and I haven't the slightest idea of what I can do with her. 

      She's not interested in programming, space opera movies nor insects.

      She's kinda cute, so I really need to find something 

      that will keep her to my side for another evening.

  q2:

    title: What can I offer to my step mother?

    user_id: anonymous

    body:  |

      My stepmother has everything a stepmother is usually offered

      (watch, vacuum cleaner, earrings, del.icio.us account). 

      Her birthday comes next week, I am broke, and I know that 

      if I don't offer her something sweet, my girlfriend 

      won't look at me in the eyes for another month.

  q3:

    title: How can I generate traffic to my blog?

    user_id: francois

    body:  |

      I have a very swell blog that talks 

      about my class and mates and pets and favorite movies.

Interest:

  i1: { user_id: fabien, question_id: q1 }

  i2: { user_id: francois, question_id: q1 }

  i3: { user_id: francois, question_id: q2 }

  i4: { user_id: fabien, question_id: q2 }

Batch skeleton


Создать файл load_data.php в prod/batch/:


<?php 

define('SF_ROOT_DIR',    realpath(dirname(__FILE__).'/..'));

define('SF_APP',         'frontend');

define('SF_ENVIRONMENT', 'dev');

define('SF_DEBUG',       true);

require_once(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'apps'.DIRECTORY_SEPARATOR.SF_APP.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php');

// initialize database manager 

$databaseManager = new sfDatabaseManager();

$databaseManager->initialize();

?> 

Импорт данных 

Добавить код до конца?> в prod/batch/load_data.php :


$data = new sfPropelData();

$data->loadData(sfConfig::get('sf_data_dir').DIRECTORY_SEPARATOR.'fixtures');

$ cd /home/sfprojects/prod/batch

$ php load_data.php

Проверяем:


http://prod/frontend_dev.php

Доступ к данным


Метод executeList() в prod/apps/frontend/modules/question/actions/action.class.php и шаблон

prod/apps/frontend/modules/question/templates/listSuccess.php:

actions.class.php:


public function executeList ()

{ 

  $this->questions = QuestionPeer::doSelect(new Criteria());

} 

listSuccess.php:

...

<?php foreach ($questions as $question): ?>

<tr>

    <td><?php echo link_to($question->getId(), 'question/show?id='.$question->getId()) ?></td>

    <td><?php echo $question->getTitle() ?></td>

    <td><?php echo $question->getBody() ?></td>

    <td><?php echo $question->getCreatedAt() ?></td>

    <td><?php echo $question->getUpdatedAt() ?></td>

  </tr>

<?php endforeach; ?>

Изменим шаблон  question/list

В файле listSuccess.php из prod/apps/frontend/modules/question/templates/ изменим:


<?php use_helper('Text') ?>

<h1>popular questions</h1> 

<?php foreach($questions as $question): ?>

  <div class="question">

    <div class="interested_block">

      <div class="interested_mark" id="mark_<?php echo $question->getId() ?>">

        <?php echo count($question->getInterests()) ?>

      </div>

    </div>

    <h2><?php echo link_to($question->getTitle(), 'question/show?id='.$question->getId()) ?></h2>

    <div class="question_body">

      <?php echo truncate_text($question->getBody(), 200) ?>

    </div>

  </div>

<?php endforeach; ?>

http://prod/frontend_dev.php/

Просмотр


http://prod/frontend_dev.php/question/show/id/2

prod/apps/frontend/modules/question/actions/actions.class.php :


public function executeShow()

 {

   $this->question = QuestionPeer::retrieveByPk($this->getRequestParameter('id'));

   $this->forward404Unless($this->question);

 }

Модификация showSuccess.php 

frontend/modules/question/templates/showSuccess.php:


<?php use_helper('Date') ?>

<div class="interested_block">

  <div class="interested_mark" id="mark_<?php echo $question->getId() ?>">

    <?php echo count($question->getInterests()) ?>

  </div>

</div>

<h2><?php echo $question->getTitle() ?></h2>

<div class="question_body">

  <?php echo $question->getBody() ?>

</div>

<div id="answers">

<?php foreach ($question->getAnswers() as $answer): ?>

  <div class="answer">

    posted by <?php echo $answer->getUser()->getFirstName().' '.$answer->getUser()->getLastName() ?> 

    on <?php echo format_date($answer->getCreatedAt(), 'p') ?>

    <div>

      <?php echo $answer->getBody() ?>

    </div>

  </div>

<?php endforeach; ?>

</div>

Добавим данные answer и relevancy  в data/fixtures/test_data.yml:

Answer:

  a1_q1:

    question_id: q1

    user_id:     francois

    body:        |

      You can try to read her poetry. Chicks love that kind of things.

  a2_q1:

    question_id: q1

    user_id:     fabien

    body:        |

      Don't bring her to a donuts shop. Ever. Girls don't like to be

      seen eating with their fingers - although it's nice. 

  a3_q2:

    question_id: q2

    user_id:     fabien

    body:        |

      The answer is in the question: buy her a step, so she can 

      get some exercise and be grateful for the weight she will

      lose.

  a4_q3:

    question_id: q3

    user_id:     fabien

    body:        |

Модификация модели

prod/lib/model/User.php:


public function __toString()

{ 

  return $this->getFirstName().' '.$this->getLastName();

} 

prod/apps/frontend/modules/question/templates/showSuccess.php 

posted by <?php echo $answer->getUser() ?> 

файл  showSuccess.php:

<div class="interested_block">

  <div class="interested_mark" id="mark_<?php echo $question->getId() ?>">

    <?php echo count($question->getInterests()) ?>

  </div>

</div>

создадим _interested_user.php файл в prod/apps/frontend/modules/question/templates/:

<div class="interested_mark" id="mark_<?php echo $question->getId() ?>">

  <?php echo count($question->getInterests()) ?>

</div>

Изменим код в  listSuccess.php и showSuccess.php) на:

<div class="interested_block">

  <?php include_partial('interested_user', array('question' => $question)) ?>

</div>

Добавим поле User 
$ symfony propel-build-ысруьф
$ symfony propel-сщтмуке-ньд-ысруьф

В prod/config/schema.xml добавим ask_question :


<column name="interested_users" type="integer" default="0" /> 


propel:
_attributes:
defaultIdMethod: native
noxsd: true
ask_question:
_attributes:
phpName: Question
id:
type: integer
required: true
primaryKey: true
autoIncrement: true
user_id:
type: integer
foreignTable: ask_user
foreignReference: id
title:
type: longvarchar
body:
type: longvarchar
created_at:
type: timestamp
updated_at:
type: timestamp
interested_users:
type: integer
default: 0
stripped_title:
type: varchar
size: 255
_uniques:
unique_stripped_title:
- stripped_title
ask_answer:
_attributes:
phpName: Answer
id:
type: integer
required: true
primaryKey: true
autoIncrement: true
question_id:
type: integer
foreignTable: ask_question
foreignReference: id
user_id:
type: integer
foreignTable: ask_user
foreignReference: id
body:
type: longvarchar
created_at:
type: timestamp
relevancy_up:
type: integer
default: 0
relevancy_down:
type: integer
default: 0
ask_user:
_attributes:
phpName: User
id:
type: integer
required: true
primaryKey: true
autoIncrement: true
nickname:
type: varchar
size: 50
first_name:
type: varchar
size: 100
last_name:
type: varchar
size: 100
created_at:
type: timestamp
ask_interest:
_attributes:
phpName: Interest
question_id:
type: integer
primaryKey: true
foreignTable: ask_question
foreignReference: id
user_id:
type: integer
primaryKey: true
foreignTable: ask_user
foreignReference: id
created_at:
type: timestamp
ask_relevancy:
_attributes:
phpName: Relevancy
answer_id:
type: integer
primaryKey: true
foreignTable: ask_answer
foreignReference: id
user_id:
type: integer
primaryKey: true
foreignTable: ask_user
foreignReference: id
score:
type: integer
created_at:
type: timestamp


Перестроим модель:

$ symfony propel-build-model

$ symfony propel-build-sql

$ mysql -u youruser -p prod < data/sql/lib.model.schema.sql

$ php batch/load_data.php

$ mysql -u youruser -p prod -e "alter table ask_question add interested_users int default '0'"

Модифицируем метод save() объекта Interest


prod/lib/model/Interest.php:


public function save($con = null)

{  

    $ret = parent::save($con);

    // update interested_users in question table

    $question = $this->getQuestion();

    $interested_users = $question->getInterestedUsers();

    $question->setInterestedUsers($interested_users + 1);

    $question->save($con);

    return $ret;

} 

Для зашиты от обновления при транзакциях:

public function save($con = null)

{ 

  $con = Propel::getConnection();

  try

  {

    $con->begin();

    $ret = parent::save($con);

    // update interested_users in question table

    $question = $this->getQuestion();

    $interested_users = $question->getInterestedUsers();

    $question->setInterestedUsers($interested_users + 1);

    $question->save($con);

    $con->commit();

    return $ret;

  }

  catch (Exception $e)

  {

    $con->rollback();

    throw $e;

  }

} 

изменим template

в _interested_user.php заменим:


<?php echo count($question->getInterests()) ?>

на

<?php echo $question->getInterestedUsers() ?>

.


  • Добавим answer в schema.xml


<column name="relevancy_up" type="integer" default="0" /> 

<column name="relevancy_down" type="integer" default="0" /> 

Перестроим модель 

$ symfony propel-build-model

$ symfony propel-build-sql

$ mysql -u youruser -p prod < data/sql/lib.model.schema.sql


  • Заменим метод->save()в классе Relevancy в lib/model/Relevancy.php


public function save($con = null)

{

  $con = Propel::getConnection();

  try

  {

    $con->begin();

    $ret = parent::save();

    // update relevancy in answer table

    $answer = $this->getAnswer();

    if ($this->getScore() == 1)

    {

      $answer->setRelevancyUp($answer->getRelevancyUp() + 1);

    }

    else

    {

      $answer->setRelevancyDown($answer->getRelevancyDown() + 1);

    }

    $answer->save($con);

    $con->commit();

    return $ret;

  }

  catch (Exception $e)

  {

    $con->rollback();

    throw $e;

  }

}

Добавим Answer class в  модель:

public function getRelevancyUpPercent()

{

  $total = $this->getRelevancyUp() + $this->getRelevancyDown();

  return $total ? sprintf('%.0f', $this->getRelevancyUp() * 100 / $total) : 0;

}

public function getRelevancyDownPercent()

{

  $total = $this->getRelevancyUp() + $this->getRelevancyDown();

  return $total ? sprintf('%.0f', $this->getRelevancyDown() * 100 / $total) : 0;

}

Изменим question/templates/showSuccess.php на:

<div id="answers">

<?php foreach ($question->getAnswers() as $answer): ?>

  <div class="answer">

    <?php echo $answer->getRelevancyUpPercent() ?>% UP <?php echo $answer->getRelevancyDownPercent() ?> % DOWN

    posted by <?php echo $answer->getUser()->getFirstName().' '.$answer->getUser()->getLastName() ?> 

    on <?php echo format_date($answer->getCreatedAt(), 'p') ?>

    <div>

      <?php echo $answer->getBody() ?>

    </div>

  </div>

<?php endforeach; ?>

</div>

Добавим данные для тестирования в fixtures

Relevancy:

  rel1:

    answer_id: a1_q1

    user_id:   fabien

    score:     1

  rel2:

    answer_id: a1_q1

    user_id:   francois

    score:     -1

Альтернативная версия заголовка


в schema.xml добавим:


<column name="stripped_title" type="varchar" size="255" /> 

<unique name="unique_stripped_title"> 

  <unique-column name="stripped_title" />

</unique> 

Перестроим модель:

$ symfony propel-build-model

$ symfony propel-build-sql

$ mysql -u youruser -p prod < data/sql/lib.model.schema.sql

Custom class


создаем myTools.class.php в prod/lib/:


<?php 

class myTools

{ 

  public static function stripText($text)

  {

    $text = strtolower($text);

    // strip all non word chars

    $text = preg_replace('/\W/', ' ', $text);

    // replace all white space sections with a dash

    $text = preg_replace('/\ +/', '-', $text);

    // trim dashes

    $text = preg_replace('/\-$/', '', $text);

    $text = preg_replace('/^\-/', '', $text);

    return $text;

  }

} 

в prod/lib/model/Question.php добавим:

public function setTitle($v)

{ 

  parent::setTitle($v);

  $this->setStrippedTitle(myTools::stripText($v));

} 

Перегружаем изменения:

$ symfony cc

$ php batch/load_data.php

Меняем ссылки на действия show


в listSuccess.php строку


<h2><?php echo link_to($question->getTitle(), 'question/show?id='.$question->getId()) ?></h2>

Меняем на

<h2><?php echo link_to($question->getTitle(), 'question/show?stripped_title='.$question->getStrippedTitle()) ?></h2>

в actions.class.php:

public function executeShow()

{ 

  $c = new Criteria();

  $c->add(QuestionPeer::STRIPPED_TITLE, $this->getRequestParameter('stripped_title'));

  $this->question = QuestionPeer::doSelectOne($c);

  $this->forward404Unless($this->question);

} 

http://prod/frontend_dev.php/

Меняем routing правила


routing.yml в prod/apps/frontend/config/:


question:

  url:   /question/:stripped_title

  param: { module: question, action: show }

http://prod/frontend_dev.php/question/what-shall-i-do-tonight-with-my-girlfriend

суббота, 15 марта 2008 г.

Создание фотоальбома

Создание фотоальбома


Спроектируем 3 таблицы



propel:

photo:

id: ~

file_path: varchar(50)

description: longvarchar

created_at: ~

tag:

photo_id: ~

name: varchar(50)

photocomment:

photo_id: ~

author: varchar(50)

body: varchar(50)

created_at: ~

Построим их


$symfony propel-build-all


Чистим кеш


$symfony clear-cache


Генерируем панель админа


$symfony propel-init-admin frontend photo Photo


смотрим


http://localhost/prod_dev.php/photo.


Редактируем представление


открываем generator.yml из apps/prod/modules/photo/config/ и добавляем следующий код:



generator:

class: sfPropelAdminGenerator

param:

model_class: Photo

theme: default

list:

display: [file_path, description, created_at]

object_actions:

_edit:

name: Edit picture properties


Для создания возможности выбора файла и навигащии по системе, модифицируем generator.yml:



generator:

class: sfPropelAdminGenerator

param:

model_class: Photo

theme: default

list:

display: [file_path, description, created_at]

object_actions:

_edit:

name: Edit picture properties

edit:

display: [file_path, description]

fields:

file_path:

type: admin_input_file_tag


Создаем механизм обработкм для выбранного файла. Вначале модифицируем схему, добавляя колонку _photo:



generator:

class: sfPropelAdminGenerator

param:

model_class: Photo

theme: default

list:

display: [_photo, description, created_at]

object_actions:

_edit:

name: Edit picture properties

edit:

display: [_photo, file_path, description]

fields:

file_path:

type: admin_input_file_tag


Создаем _photo.php в /apps/prod/modules/photo/templates следующего содержания:


<?php echo image_tag('/uploads/'.$photo->getFilePath()) ?>


Модифицируем модель


выполнив команду propel-build-all, мы генерирум два файла вкаталоге lib/model/ - Photo.php и PhotoPeer.php.Содержимое lib/model/Photo.php:


<?php

/**

* Subclass for representing a row from the 'photo' table.

*

*

*

* @package lib.model

*/

class Photo extends BasePhoto

{

}


Нам необходимо иметь возможность добавлять файлы и удалять файлы. Для этого модифицируем Photo class:


// in lib/model/Photo.php

class Photo extends BasePhoto

{

public function getTagsString()

{

$tags = array [9]();

foreach ($this->getTags() as $tag)

{

$tags[] = $tag->__toString();

}

return implode(' ', $tags);

}


public function setTagsString($tagPhrase)

{

// remove old tags

$this->deleteTags();


// set new tags

$tagNames = explode(' ', $tagPhrase);

foreach($tagNames as $tagName)

{

$tag = new Tag();

$tag->setPhoto($this);

$tag->setName($tagName);

$tag->save();

}

}


public function deleteTags()

{

$c = new Criteria();

$c->add(TagPeer::PHOTO_ID, $this->getId());

TagPeer::doDelete($c);

}

}


Здесь мы использовали метод __toString из класса Tag , который следут модифицировать:


// in lib/model/Tag.php

class Tag extends BaseTag

{

public function __toString()

{

return $this->getName();

}

}


Модифицируем модель :


// apps/prod/modules/photo/config/generator.yml

generator:

class: sfPropelAdminGenerator

param:

model_class: Photo

theme: default

list:

display: [_photo, description, tags_string, created_at]

object_actions:

_edit:

name: Edit picture properties

edit:

display: [_photo, file_path, description, tags_string]

fields:

file_path:

type: admin_input_file_tag

tags_string:

name: Tags

type: input_tag


 


понедельник, 25 февраля 2008 г.

Строим Blog на Symfony

Имеем:

  1. установленный XAMPP на Windows в каталоге C;\xampp;
  2. развернут framework Symfony;
  3. Apache22 поднят на localhost:80;
  4. пользователем MySQL5 является root с паролем 123;
  5. в php поднят PEAR.

Хотим:
  1. Создать проект на Symfony;
  2. Создать приложение Blog в проекте.


Дальше идет вольный пересказ наставления, взятого с symfony-project.org.

Создаём проект prod

Создаём каталог С:\xampp\htdocs\prod

  1. cd С:\xampp\htdocs\prod
  2. С:\xampp\htdocs\prod> symfony init-project prod

Создаём приложение blog
  • С:\xampp\htdocs\prod> symfony init-app blog

Проектируем базу данных prod, содержащую две таблицы post и comment

  • Редактируем файл С:\xampp\htdocs\prod\config\schema.yml:


propel:
post:
id: ~
title: varchar(255)
excerpt: longvarchar
body: longvarchar
created_at: ~
comment:
id: ~
post_id: ~
author: varchar(255)
email: varchar(255)
body: longvarchar
created_at: ~

Генерим модель, т.е. class Post и class Comment, которые появятся в E:\xampp\htdocs\prod\lib\model

  • С:\xampp\htdocs\prod> symfony propel-build-model

Генерим базу данных

  • С:\xampp\htdocs\prod> symfony propel-build-sql

Получаем скрипт E:\xampp\htdocs\prod\data\sql\lib.model.schema.sql

SET FOREIGN_KEY_CHECKS = 0;

#-----------------------------------------------------------------------------
#-- post
#-----------------------------------------------------------------------------

DROP TABLE IF EXISTS `post`;


CREATE TABLE `post`
(
`id` INTEGER NOT NULL AUTO_INCREMENT,
`title` VARCHAR(255),
`excerpt` TEXT,
`body` TEXT,
`created_at` DATETIME,
PRIMARY KEY (`id`)
)Type=MyISAM;

#-----------------------------------------------------------------------------
#-- comment
#-----------------------------------------------------------------------------

DROP TABLE IF EXISTS `comment`;


CREATE TABLE `comment`
(
`id` INTEGER NOT NULL AUTO_INCREMENT,
`post_id` INTEGER,
`author` VARCHAR(255),
`email` VARCHAR(255),
`body` TEXT,
`created_at` DATETIME,
PRIMARY KEY (`id`),
INDEX `comment_FI_1` (`post_id`),
CONSTRAINT `comment_FK_1`
FOREIGN KEY (`post_id`)
REFERENCES `post` (`id`)
)Type=MyISAM;

# This restores the fkey checks, after having unset them earlier
SET FOREIGN_KEY_CHECKS = 1;

Создаем базу данных prod

  • http://localhost/phpmyadmin/

Редактируем права доступа к базе
  • c:\xampp\htdocs\prod\config\databases.yml


all:
propel:
class: sfPropelDatabase
param:
dsn: mysql://root:123@localhost/prod



  • c:\xampp\htdocs\prod\config\propel.ini


propel.targetPackage = lib.model
propel.packageObjectModel = true
propel.project = prod
propel.database = mysql
propel.database.createUrl = mysql://root:123@localhost/
propel.database.url = mysql://root:123@localhost/prod



  • Наполняем базу данных

С:\xampp\htdocs\prod> symfony propel-insert-sql

Создаем виртуальный хост для проекта

  • С:\xampp\apache\conf\extra\httpd-vhosts.conf

<Directory "c:/xampp/php/pear/data/symfony/web/sf">
Allow from All
</directory>

<virtualhost>
DocumentRoot "c:/xampp/htdocs/prod/web"
DirectoryIndex index.php
Alias /sf "c:/xampp/php/pear/data/symfony/web/sf"

<directory>
AllowOverride All
Order deny,allow
Allow from all
</directory>
</virtualhost>

  • С:\xampp\apache\conf\httpd.conf
Listen 89

  • Прегружаем httpd

  • Создаем приложения
  1. c:\xampp\htdocs\prod> symfony propel-generate-crud blog post Post
  2. c:\xampp\htdocs\prod> symfony propel-generate-crud blog comment Comment
  3. c:\xampp\htdocs\prod> symfony clear-cache

  • Проверяем работу

  1. http://localhost:89/blog_dev.php/post

  2. http://localhost:89/blog_dev.php/comment