Niedokończone projekty
Po przeczytaniu notki Setha Godina jakoś mnie tknęło.
Nie dalej jak rok temu miałem zawsze na tapecie jakiś projekt. Większość kończyła się wraz z początkowym zapałem tworzenia czegoś nowego. Jednak zawsze przez pierwsze kilka tygodni to było coś, co wyzwalało dodatkową energię. Przy tych okazjach prawie zawsze pojawiało się coś nowego do nauczenia.
Jednak niedawno zamykałem sprawę “mgr” i postanowiłem się takimi rzeczami nie rozpraszać. No i jakoś to nierozpraszanie poszło mi tak dobrze, że teraz, trzy miesiące po obronie nie robię nic “na boku”. Jednak myślę, że warto to zmienić.
Możliwe, że takie słomiane projekty są dla programisty tym, czym szkice dla malarza i eseje dla pisarza – ostrzeniem piły.
Skróć swoje listingi
Pewnie w niemal każdym swoim widoku index.ctp masz fragment kodu podobny do tego:
<?php
$i = 0;
foreach ($tracks as $track):
$class = null;
if ($i++ % 2 == 0) {
$class = ' class="altrow"';
}
?>
<tr<?php echo $class;?>>
<td>
<?php echo $track['Track']['id']; ?>
</td>
<td>
<?php echo $track['Track']['name']; ?>
</td>
<td>
<?php echo $track['Car']['name']; ?>
</td>
<td>
<?php echo $track['Track']['begin']; ?>
</td>
<td>
<?php echo $track['Track']['end']; ?>
</td>
<td>
<?php echo $track['Track']['length']; ?>
</td>
<td class="actions">
<?php echo $html->link(
__('Edycja', true),
array(
'action' => 'edit',
$track['Track']['id'] ,
$track['Car']['id']
)
);
?>
</td>
</tr>
<?php endforeach; ?>
</table>
Chce Ci się pisać ten kod kilkadziesiąt razy w jednym projekcie? Mnie też nie. Dlatego napisałem prosty element, który to trochę automatyzuje (nazwałem go “list”):
// app/views/elements/list.ctp
<?php
$i = 0;
foreach($elements as $key => $element):
$class = null;
if ($i++ % 2 == 0) {
$class = ' class="altrow"';
}
?>
<tr <?php echo $class?>>
<?php foreach($fields as $path): ?>
<td>
<?php echo Set::classicExtract($element, $path) ?>
</td>
<?php endforeach; ?>
<?php if(isset($links)): ?>
<td>
<?php foreach($links as $name => $url): ?>
<?php
if(!is_array($url["params"])) {
$url["params"] = array($url["params"]);
}
foreach($url["params"] as $key => $path){
$url[$key] = Set::classicExtract(
$element,
$path
);
}
unset($url["params"]);
?>
<?php echo $html->link($name, $url)?>
<?php endforeach; ?>
</td>
<?php endif; ?>
</tr>
<?php endforeach; ?>
Jego użycie jest dość proste. Dla przykładu wygenerujemy ten sam “output” dla pierwszego listingu z tego postu:
echo $this->renderElement(
"list",
array(
"elements" => $tracks,
"fields" => array(
"Track.name", "Car.name", "Track.begin",
"Track.end", "Track.length"
),
"links"=> array(
"edycja" => array(
"controller"=> "tracks", "action"=> "edit",
"params" => array(
"Track.id", "Car.id"
)
)
)
)
)
Opiszę poszczególne parametry przekazywane do tego elementu:
- “elements” – kolekcja (w tym wypadku tablica) elementów zwrócona na przykład przez $this->Track->find(“all”)
- “fields” – pola, które mają się pojawić w komórkach tabeli
- “links” – tu definiujemy jakie linki mają się pojawić w ostatniej kolumnie (zazwyczaj tam znajdują się “opcje”). Indeksy kolejnych elementów to nazwy linków (tutaj “edycja”).
- “controller” i “action” są identycznie używane jak w metodzie HtmlHelper::link()
- “params” jest dość ciekawy. Jeśli chcemy w wygenerowanym linku mieć jeden parametr (najczęściej id), robimy to tak:
"edycja" => array( "controller"=> "cars", "action"=> "edit", "params"=>"Car.id" ),gdy parametrów ma być więcej – ścieżki do nich przekazujemy w tablicy (tak jak w przykładzie):
"edycja" => array( "controller"=> "tracks", "action"=> "edit", "params" => array( "Track.id", "Car.id" ) )Można także używać parametrów typu “named”, wystarczy podać dodatkowo indeksy:
"edycja" => array( "controller"=> "tracks", "action"=> "edit", "params" => array( "parametr_1"=> "Track.id", "parametr_2"=> "Car.id" ) )
Zachęcam do korzystania z tego elementu i zgłaszania wszelkich niedociągnięć
cakephp {n}
Jeśli zastanawiasz się dlaczego do czego służy znacznik {n} czasem przekazywany w parametrach funkcji – służę pomocą.
Otóż jest on używany w meotdzie Set::extract() (1.1) lub Set::classicExtract() i oznacza “iteruj po kolejnych elementach”.
Możesz się tą metodą pobawić samodzielnie, załóżmy taką tablicę:
$a = array(
array("X" => "ala"),
array("X" => "ma"),
array("X" => "kota"),
);
innymi słowy:
Array
(
[0] => Array
(
[X] => ala
)
[1] => Array
(
[X] => ma
)
[2] => Array
(
[X] => kota
)
)
I chcesz zwykłą listę, to możesz skorzystać z Set::classicExtract():
Set::classicExtract($a, "{n}.X")
i w efekcie masz:
Array
(
[0] => ala
[1] => ma
[2] => kota
)
Dokładnie tak działał stary (1.1) Model::generatelist().
Inne ciekawe zastosowanie klasy Set znajdziesz w moim starszym poście.