Symfony
Published: 13:21, Thursday 14 July 2011
Notes
What's this? See my article about Notes.
View as plain text file.
startup:
install php and mysql
download and run http://sf-to.org/1.4/check.php
uses /etc/php5/cli/php.ini
installed additionally php5-mysql php5-xsl php-apc
set short_open_tag to off in php.ini
run check.php via server (not only cli)
firefox tries to download it! but renamed it's ok
uses /etc/php5/apache2/php.ini
changed short_open_tag to Off
jobeet:
not under web root
symfony/jobeet/lib/vendor
choose wget from http://www.symfony-project.org/installation
tar zxpf file
mv symfony-1.4.0 symfony
rm symfony-1.4.0.tgz
or install from subversion
run symfony: php lib/vendor/symfony/data/bin
generate:project jobeet
generate:app frontend
prevents xss and csrf attacks
change permissions
chmod 777 cache log (the only dirs symfony writes in)
should be ignored by svn or hg:
.hgignore
syntax: glob
cache/**
log/**
web server config
add website www.jobeet.com.localhost as defined in newsite
to /etc/apache2/sites-available
and link to it in sites-enabled
www.jobeet.com.localhost/frontend_def.php
stories in day 1
data model/relational model:
config/doctrine/schema.yml
doctrine
Table:
actAs: { Timestampable: ~ }
columns:
col:
type: string(255)/boolean/timestamp/integer/float/decimal/array/object/blob/clob/time/date/enum/gzip
notnull: true
unique: true
primary: true
default
relations:
OtherTable
class: Table
refClass: Table
onDelete: CASCADE/SET NULL/RESTRICT
local: col
foreign: col
foreignAlias: Alias
database/mysql setup:
mysqladmin -uroot -p create jobeet
configure:database "mysql:host=localhost;dbname=jobeet" root password
better: config/databases.yml (check access mode)
doctrine:build --model
doctrine:build --sql generates statements in data/sql/schema.sql
doctrine:insert-sql
doctrine:build --model generates classes for table records in lib/model/doctrine
doctrine:build --all --no-confirmation
fixture file in data/fixtures/categories.yml
wget two pictures
load data: doctrine:data-load
all together: doctrine:build --all --and-load [--no-confirmation]
database/mysql update:
generate basic module:
doctrine:generate-module --with-show --non-verbose-templates frontend job jobeetjob
creates apps/frontend/modules/job
actions/actions.class.php
index: displays records
show: displays fields of a record
new: form for creation
create
edit: form to edit
update
delete
templates
module is available in www.jobeet.com.localhost/frontend_dev.php/job
jobeet after dbsetup:
change layout
wget images stylesheets favicon (cool!)
add use_stylesheet for indexSuccess and showSuccess
changed indexSuccess.php showSuccess.php and actions.class.php
(renamed jobeet_job to job) ?
changed routing.yml to module job
changed link for jobeet logo in layout
changed mapping for single job
slugify
change executeShow: get object from route
removed default routes
change query: list only active jobs
added expired job to fixture (removed expires_at from other two, to see them)
added setting in app.yml
refactoring
query from control to model (getActiveJobs)
sort by expires_at
get in categories
limiting results
securing expired jobs
add category page
name sluggable
create partial
create pager, some refactoring (get query)
start testing slugify
doctrine tests
functional test
created own functional class JobeetTestFunctional
expired jobs are not listed
@
fixture
data/fixtures/table.yml
Table:
entryname:
col: value
model classes (3 x table):
TableElement (customizable)
BaseTableElement (rewritten by docttrine:build --model)
TableElementTable (class for the table itself - returns collections)
model view controller/mvc:
decorator design pattern: layout + slots + template
layout
apps/frontend/templates/layout.php
html page with inline php
controller
actions
methods of Actions classes (one per module)
executeACTION
work with model: Doctrine_Core::getTable(name)
actions:
index: returns Doctrine_Collection
public function executeActionName(sfWebRequest $request)
show: returns one element
API/documentation:
classes:
sfAction
sfWebRequest
getMethod getUri getReferer getHost getLanguages getCharsets isXmlHttpRequest getHttpHeader getCookie isSecure getFiles getGetParameter getPostParameter getUrlParameter getRemoteAddress
response
sfWebResponse
setCookie setStatusCode setHttpHeader setContentType addVaryHttpHeader addCacheControlHttpHeader setContent send
symfony variables:
$sf_contents: html generated by action
data manipulation:
$job = new JobeetJob();
$job->setPosition('Web developer');
$job->save();
echo $job->getPosition();
$job->delete();
linking:
$job->setCategory(new JobeetCategory());
data types:
initial data: needed for the app to work
test data
user data
help: help command
environments:
different exception handling
development: web developers, logs all, no cache
test: automatical test
staging: customer
production: end users
repository:
with svn:
svnadmin create repo
basic dir structure: svn mkdir -m "created default directory structure" http://svn.example.com/jobeet/trunk http://svn.example.com/jobeet/tags http://svn.example.com/jobeet/branches
checkout trunk: svn co http://svn.example.com/jobeet/trunk .
remove cach and log content: rm -rf cache/* log/*
permissions: chmod 777 cache/ log/
ignore list
svn propedit svn:ignore cache
*
same for log dir
commit: svn import -m "made the initial import" . http://svn.example.com/jobeet/trunk
with hg: ??
directory structure:
main
apps: applications
cache: cache
config: configuration
lib: libraries and classes
log: log files
plugins: plugins
test
web: web root
created applications:
config
app.yml: application specific setings
all: { var: val }
sfConfig::get('app_var')
lib
modules (mvc)
templates
helper functions:
include_STH prints
get_STH returns
include_stylesheets()
user_stylesheet(STRING)
url_for
generates nice URL
for an element: module, action, id
url_for('job/show?id='.$job->getId())
url_for('@default?module=job&action=show&id='.$job->getId())
url_for(array('var' => 'val'...))
url_for(array('sf_route' => ROUTENAME, 'sf_subject' => SUBJ))
if routing has been done with sfDoctrineRoute
or url_for(ROUTNAME, SUBJ)
link_to()
generateUrl
in layout: include_slot('NAME')
forwarding
round trip (no url change)
forward404Unless(BOOL): if BOOL=true goes on normally
forward404If
forward404
forward('default', '404')
redirecting: to another url
slots:
include in layout/template with include_slot('NAME', DEVAULT_VALUE)
or if (!include_slot(NAME)): block endif
define at beginning of template
slot(NAME, sprintf(PATTERN, VARS...))
or slot(NAME) codeblock end_slot()
css/stylesheets:
what to include: use_stylesheet(), or view.yml
view:
configures default settings of templates
works per module:
apps/frontend/config/view.yml
apps/frontend/modules/module/config/view.yml
format:
default:
http_metas:
content-type: text/html
metas:
#title
symfony project
#description
symfony project
#keywords
symfony, project
#language
en
#robots: index, follow
stylesheets: [main.css, print.css: { media: print }]
javascripts: []
has_layout
true
layout: layout
all:
templatename:
configuration files:
default: in framework
global: cofig/app.yml
local for an app: apps/APP/config/app.yml
local for module: apps/APP/modules/MOD/config
sfConfig::get('app_VAR')
routing
url and uri management
better remove default routing
internal: MOD/ACTION?id=ID
external: MOD/ACTION/id/ID
mapping
apps/frontend/config/routing.yml first matching wins
ROUTENAME:
url: PATTERN
class
ROUTECLASS
* matches a collection of var/val pairs
param: PARAMS
requirements:
match: pattern (eg id: \d+)
change mapping: change also url_for where needed
route object/class:
sfRoute
sfRequestRoute
restrict request method:
class: sfRequestRoute
requirements:
sf_method: [get]
sfDoctrineRoute
optimized for doctrine objects
options
{model: TABLECLASS, type: object/list }
method_for_query: method in the element model to retrieve
simplifies url_for
sfDoctrineRoutecollection:
options: { model: JobeetJob } no url, nothing else
generates routes for each action!
get object from route
$this->getRoute()->getObject();
forwards to 404 if not found. change behavior with allow_empty
list routes: app:routes frontend [routename]
http methods
symfony supports DELETE and PUT
in form hidden sf_method=put
method can be given as a parameter to helpers
cache:
cache:clear
slugify/nicer urls:
Jobeet::slugify(TEXT){
not needed if "Sluggable": write functions getCOLSlug
in routing use parameter /:COL_slug/...
doctrine behavior
Sluggable enable in model
actAs:
Sluggable:
fields: [name]
query:
$q = Doctrine_Query::create()
->from(TABLE)
->where(args..)
->leftJoin()
->limit
$result = $q->execute();
you can see query at log/frontend_dev.log or in the toolbar
serialization
override save method in the model class
public function save(Doctrine_Connection $conn = null)
is new: isNew()
new feature/module:
first url and rule
generate:module frontend MOD
doctrine:generate-module makes much more
create some actions
update the model
write some templates
templates:
partial: _NAME
include_partial('mod/name', array('var' => val))
paginate:
in execute
sfDoctrinePager instead of the collection
new sfDoctrinePager(ElementClass, limit)
setQuery() setPage(page, default) init()
getResults() getNbResults haveToPaginate getLinks getPage getPreviousPage getNextPage getLastPage
implements iterator and countable
automated testing:
unit tests: test/unit
functional tests: test/functional
launch/run test: directly via php or test:unit name
add tests whenever you find a bug, then for new features
lime testing framework
require_once dirname(__FILE__).'/../bootstrap/unit.php';
$t = new lime_test(1);
methods
ok is isnt like unlike is_deeply
fail pass skip todo comment
coverage
test:coverage path/to/test path/to/class
needs php5-xdebug
on new feature: write test with descripton, then implement
doctrine tests:
configure:database --name=doctrine --class=sfDoctrineDatabase --env=test "mysql:host=localhost;dbname=jobeet_test" root password
updates config/databases.yml
mysqladmin -uroot -ppasswor create jobeet_test
doctrine:insert-sql --env=test
test data
Doctrine_Core::loadData(sfConfig::('sf_test_dir').'/fixtures');
test/fixtures
fist create test/bootstrap then test/unit/model/JobeetJobTest.php
run all unit tests: test:unit
dubious: script ended before eof
functional testing:
special browser
sfBrowser
get post call back forward reload click select deselect restart
setHttpHeader setAuth setCookie removeCookie clearCookies followRedirect
sfTestFunctional: takes sfBrowser as constructor
file: test/functional/frontend/MODActionsTest.php
fluent interface
$browser = new sfTestfunctional(new sfBrowser());
tester block (more than one method):
$b->with('request')->begin()->...->end();
request tester methods: isParameter isFormat isMethod hasCookie isCookie
response tester methods: checkElement (css) checkForm debug matches isHeader isStatuscode isRedirected isValid (xml)
running functional tests
directly with php or
php symfony test:functional frontend categoryActions
load data
Doctrine_Core::loadData(sfConfig::get('sf_test_dir').'/fixtures');
here db has already been init by bootstrapping
create new functional class: in lib/test
debugging: debug method halts script exec
run test: test:functional frontend
test all: test:all --only-failed
Write a Comment
* These fields are mandatory.