суббота, 5 апреля 2008 г.

Страница новостей (продолжение)

Формируем глпавный шаблон проекта



<!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 include_http_metas() ?>

<?php include_metas() ?>



<?php include_title() ?>



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







</head>

<body>



<div id="container">




<div id="header">

<div id="banner">


&nbsp;


</div>


<div id="logo">


&nbsp;


</div>


</div>



<div id="topmenu">



&nbsp;



</div>



<div id="navigation">





Extra Content

<fieldset>


<legend>Collapsible List &mdash; Take 4</legend>


<ul>

<li>Item 1</li>




<li>Item 2</li>


<li>


Item 3


<ul>


<li>Item 3.1</li>


<li>


Item 3.2

<ul>


<li>Item 3.2.1</li>




<li>Item 3.2.2</li>


<li>Item 3.2.3</li>


</ul>


</li>

<li>Item 3.3</li>


</ul>


</li>




<li>


Item 4


<ul>


<li>Item 4.1</li>


<li>

Item 4.2


<ul>


<li>Item 4.2.1</li>


<li>Item 4.2.2</li>




</ul>


</li>


</ul>

</li>


<li>Item 5</li>


</ul>


</fieldset>



</div>



<div id="content">



Primary Content





<div id="smallFeatures">

<div id="smallFeaturesInner">




<div id="feature2" class="feature">


<div id="feature2Inner">


<h3>

Secondary title I


</h3>





<p>


Какой-то текст.


</p>

<p class="featureContinue">


<a href="#">Visit the page</a>




</p>


</div>

</div>

<!-- END feature2 -->


<div id="feature3" class="feature">


<div id="feature3Inner">


<h3>

Secondary title II


</h3>




<p>


Какой-то текст.


</p>


<p class="featureContinue">

<a href="#">Visit the page</a>


</p>


</div>

<!-- END feature3Inner -->


</div>

<!-- END feature3 -->


<div id="feature4" class="feature">




<div id="feature4Inner">


<h3>


Secondary title III

</h3>




<p>


Какой-то текст.


</p>


<p class="featureContinue">

<a href="#">Visit the page</a>


</p>


</div>

<!-- END feature4Inner -->


</div>

<!-- END feature4 -->


<div class="clearer">


</div>


</div>

<!-- END smallFeaturesInner -->




<div id="feature1">







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





<p class="featureContinue">


<?php echo link_to('back to the news list', 'public/index',

'style=display:block;float:right;') ?>


</p>





</div>

<!-- END feature1 -->


</div>

<!-- END smallFeatures -->


<div class="clearer">

</div>


</div>

<!-- END content -->



</div>



<div id="footer">

Footer<p>Force Layout:

</p>

</div>

</div>



</body>

</html>




Навигационную панель слева строим с помощью jquery

Пишем скрипт menu и подключаем его и jquery к проекту



menu


$(function(){


$('li:has(ul)')


.click(function(event){

if (this == event.target) {


if ($(this).children().is(':hidden')) {


$(this)


.css('list-style-image','url(minus.gif)')


.children().slideDown();

}


else {


$(this)


.css('list-style-image','url(plus.gif)')


.children().slideUp();


}


}

return false;


})


.css({cursor:'pointer',


'list-style-image':'url(plus.gif)'})


.children().hide();


$('li:not(:has(ul))').css({

cursor: 'default',


'list-style-image':'none'


});


});





default:


http_metas:


content-type: text/html




metas:


title: symfony project

robots: index, follow


description: symfony project


keywords: symfony, project


language: en




stylesheets: [main, art]




javascripts: [jquery, menu]




has_layout: on

layout: layout







Чтобы все это работало, добавляем нужные стили



body

{


text-align:center;


color:#333;


font-family: sans-serif;


margin:0px 0;


background-color: #FBFFC0;

}



body,td {


font-size: 10pt;


}

table {


background-color: black;


border: 1px black solid;


border-collapse: collapse;


}

th {


border: 1px outset silver;

background-color: maroon;


color: white;


}

tr {


background-color: white;


margin: 1px;


}

tr.striped {


background-color: coral;


}

td {

padding: 1px 8px;


}



#jQueryStatement {


color: maroon;

}



fieldset {width: auto;


margin-bottom: 12px;


border-color: #00457b;


background-color: #cfeace;

}



fieldset div {

margin-bottom: 6px;


font-weight: normal;

}



legend {


border: 2px ridge #00457b;


font-weight: bold;


background-color: #e36a51;


color: white;


padding: 2px 16px;

}



button {

background-color: #2a523c;


padding: 2px 16px;


color: #cfeace;


font-weight:bold;

}



a,#exampleIndex li {


color: #2a523c;

}



a:hover,#exampleIndex li:hover {


color: #ff0088;

}



#exampleIndex ul {


list-style: none;


margin: 8px;


padding: 0;

}



#exampleIndex li {


text-decoration: underline;


font-weight: bold;


cursor: pointer;


margin: 0;


padding: 0;

}



.chapterBlock {


background-color: #ddeadc;


border: 3px double #00457b;


margin: 6px 8px;


padding: 6px;

}



p{

font-size:.9em;

line-height:1.3em;

margin:20px auto;

}

#notice p{

text-align:justify !important;

}

#container{

width:100%;

margin:0 auto;

}

#container p{

text-align:right;

}

#header{

background-color: #FFA345;

width:100%;

line-height:90px;

color:#fff;

}



#header #banner {

background-color: #FFA345;

width:80%;

line-height:90px;

color:#fff;

float:left;

}

#header #logo{

background-color: #FF0045;

width:20%;

color:#fff;

float:right;

}



#header #mbanner{

background-color: #FFA345;

width:100%;

line-height:90px;

color:#fff;

float:right;

}



#content{

background-color: #00009F;

width:80%;

float:right;

color:#fff;

}



#topmenu{

background-color: #94C6FF;

width:100%;

line-height:35px;

clear:both;

}

#topmenu #calendar{

background:url(../images/top_back1.jpg) no-repeat;

width:395px;

line-height:35px;

float:left;

}



#topmenu #topm{

background:url(../images/top_back1.jpg);

width:592px;

line-height:35px;

float:right;

}

#navigation{

background-color: #C5FF8A;

width:250px;

float:left;

}





#extraContent{

display:none;

}

#footer{

background-color: #94C6FF;

width:100%;

line-height:50px;

clear:both;

}





a{

font-weight:bold;

color:#000;

cursor: pointer;

}

.article

{

color:#666;

float:left;

}



#smallFeatures

{


position: static;


border: none;


border-bottom: 1px solid #CCCCCC;


padding: 0;

}



#smallFeatures .feature

{


clear: none;


float: left;


width: 33.3%;


border-top: 0 none #FFFFFF;


padding: 0;


background-color: transparent;

}



#smallFeatures .feature h3

{


clear: none;

margin: 0 0 15px 0;


border-top: 1px solid #CCCCCC;


border-bottom: 1px solid #CCCCCC;


padding: 8px 15px;


background-color: #EEEEEE;


background-image: none;

}

#feature1{


margin: 0 15px 15px 15px;

}

#smallFeatures .feature p

{


margin: 0 15px 15px 15px;

}



#smallFeatures .featureContinue

{


border-top: 1px dashed #CCCCCC;


padding-top: 0.25em;

}







В шаблоне index для чтения новости целиком создаем ссылку read more...

<div id="main">


<h1>News and articles</h1>




<?php foreach($articles as $article): ?>







<fieldset>


<legend><?php echo $article->getCreatedAt('d/M/Y') ?></legend>

<div class="article">




<?php echo link_to(


image_tag('/uploads/'.$article->getFilePath()),


'public/article?id='.$article->getId(),


'class=image title='.$article->getTitle()

) ?>




<?php echo $article->getTeaser() ?>





<?php echo link_to('read more... ', 'public/article?id='.$article->getId(),


'style=display:block;float:right;') ?>

</div>


</fieldset>


<?php endforeach; ?>




<div id="footer">


powered by <?php echo link_to('symfony', 'http://www.symfony-project.com') ?>

</div>



</div>



И соответствующий этой ссылке action в классе publicActions

<?php



/**


* public actions.


*


* @package prod


* @subpackage public


* @author Your name here

* @version SVN: $Id: actions.class.php 2692 2006-11-15 21:03:55Z fabien $


*/

class publicActions extends sfActions

{


/**


* Executes index action


*


*/


public function executeIndex()

{


//$this->forward('default', 'module');


$c = new Criteria();


$c->addDescendingOrderByColumn(ArticlePeer::CREATED_AT);


$this->articles = ArticlePeer::doSelect($c);




}


public function executeArticle()




{


$this->article = ArticlePeer::retrieveByPk($this->getRequestParameter('id'));


$this->forward404unless($this->article);

$c = new Criteria();


$c->add(ArticlePeer::ID, $this->getRequestParameter('id'));


$this->articles = ArticlePeer::doSelect($c);





}

}



А для представления - шаблон














<h1><?php echo $article->getTitle() ?> </h1>

<fieldset>


<legend><?php echo $article->getCreatedAt('d/M/Y') ?></legend>







<p>


<?php echo link_to(


image_tag('/uploads/'.$article->getFilePath()),


'public/article?id='.$article->getId(),


'class=image title='.$article->getTitle()

) ?>




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


</p>

</fieldset>












пятница, 4 апреля 2008 г.

Создадим приложение для публикации новостей


  • Создадим приложение для публикации новостей.

    Требуется

    Авторизация

    Информация о пользователе

    Публикация анонса

    Помещение в публикацию изображения

    Просмотр публикации целиком


Установки для базы данных


   

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

 


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


author:
_attributes: { phpName: Author }
id:
first_name: varchar(30)
last_name: varchar(30)
email: varchar(75)
website: varchar(100)
birthday: date
years_experience: integer
article:
_attributes: { phpName: Article }
id:
author_id:
title: varchar(255)
teaser: longvarchar
body: longvarchar
file_path: varchar(50)
file_attachment: varchar(255)
created_at: ~
tag:
article_id: ~
name: varchar(50)
name: varchar(50)

 


Построим модель и таблицы

$symfony propel-build-all


Чистим кеш

$symfony clear-cache


Создаем приложение

$symfony init-app frontend


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

$symfony propel-init-admin frontend author Author

$symfony propel-init-admin frontend article Article


смотрим

http://localhost/frontend_dev.php/author

http://localhost/frontend_dev.php/article


Создаем автора


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

открываем generator.yml из apps/frontend/modules/article/config/


generator:
class: sfPropelAdminGenerator
param:
model_class: Article
theme: default




и добавляем следующий код:




    list:
display: [title, created_at]
object_actions:
_edit:
name: Edit article


 


чтобы выбрать картинку


    edit:
display: [file_path, title, created_at]
fields:
file_path:
type: admin_input_file_tag

 





Создаем несколько новостей


generator:
class: sfPropelAdminGenerator
param:
model_class: Article
theme: default
list:
display: [title, created_at]
object_actions:
_edit:
name: Edit article
edit:
display: [_img, file_path, title, created_at, teaser, body]
fields:
file_path:
type: admin_input_file_tag
tags_string:
name: Tags
type: input_tag

 


Для того чтобы это работало, нужно создать часть шаблона

_img.php


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


Скорректировать класс Article


Article.php

<?php


/**

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

*

*

*

* @package lib.model

*/

class Article extends BaseArticle

{

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->setArticle($this);


$tag->setName($tagName);


$tag->save();


}


}


public function deleteTags()


{


$c = new Criteria();


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


TagPeer::doDelete($c);


}


}


Скорректировать класс Tag

Tag.php


<?php


/**

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

*

*

*

* @package lib.model

*/

class Tag extends BaseTag

{

public function __toString()

{

return $this->getName();

}


}


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


<?php


/**

* public actions.

*

* @package prod

* @subpackage public

* @author Your name here

* @version SVN: $Id: actions.class.php 2692 2006-11-15 21:03:55Z fabien $

*/

class publicActions extends sfActions

{

/**

* Executes index action

*

*/

public function executeIndex()

{

//$this->forward('default', 'module');

$c = new Criteria();

$c->addDescendingOrderByColumn(ArticlePeer::CREATED_AT);

$this->articles = ArticlePeer::doSelect($c);



}



}


И соответствующий ему шаблон


<div id="main">

<h1>News and articles</h1>


<?php foreach($articles as $article): ?>




<?php echo $article->getCreatedAt('d/M/Y') ?>

<div class="article">


<?php echo link_to(

image_tag('/uploads/'.$article->getFilePath()),

'public/article?id='.$article->getId(),

'class=image title='.$article->getTitle()

) ?>


<?php echo $article->getTeaser() ?>



<?php echo link_to('read more... ', 'public/article?id='.$article->getId(),

'style=display:block;float:right;') ?>

</div>



<?php endforeach; ?>


<div id="footer">

powered by <?php echo link_to('symfony', 'http://www.symfony-project.com') ?>

</div>


</div>


Создаем стиль для этого шаблона


body

{

text-align:center;

color:#333;

font-family: sans-serif;

margin:0px 0;

background-color: #FBFFC0;

}


p{

font-size:.9em;

line-height:1.3em;

margin:20px auto;

}

#footer{

background-color: #94C6FF;

width:100%;

line-height:50px;

clear:both;

}

a{

font-weight:bold;

color:#000;

cursor: pointer;

}

.article

{

color:#666;

float:left;

}


Добавляем этот стиль



default:
http_metas:
content-type: text/html

metas:
title: symfony project
robots: index, follow
description: symfony project
keywords: symfony, project
language: en

stylesheets: [main, art]

javascripts: []

has_layout: on
layout: layout