CakePHP project építés 8. rész

cakephpA főbb koncepciók megismerése után igazából már mindent megismertünk ami a projectépítéshez általánosságban szükséges. Pár apróbb finomítást még végrehajtunk, aztán kiállíthatunk magunknak egy alapfokú cakePHP programozási bizonyítványt.

Design

Eleve megvolt az oldal design terve ami így nézett ki:
tulasi.hu design terv
Ezt a megfelelő css-sel, képekkel és a default.thml file módosításával lehet alkalmazni.
Az új /view/layouts/default.thml fileunk így fog kinézni:

<!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" lang="hu" xml:lang="hu">
<head>
<?php print $html->charset('utf-8')?>
<title><?php print $title_for_layout?></title>
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
<?php print $html->css('cake.generic')?>
<?php print $html->css('tulasi')?>
</head>
<body>
<div id="teljeslap">
    <div id="fejlec">
      <ul>
        <?php if($session->read('User')){ ?>
        <li>Be vagy jelentkezve: <?php print $session->read('User')?> néven</li>
        <li><?php print $html->link('Kilépek', '/users/kilep')?></li>
        <?php }?>
      </ul>
    </div>

  <div id="tartalom">
    <?php print $content_for_layout?>
  </div>

  <div id="panel">
    <h3>Menü</h3>
    <ul>
      <li><?php print $html->link('Főoldal','/'); ?></li>
      <li><?php print $html->link('Admin felület','/users/belep/'); ?></li>
      <li><?php print $html->link('Magunkról','/pages/magunkrol'); ?></li>
      <li><?php print $html->link('Filozófiánk','/pages/filozofiank'); ?></li>
      <li><?php print $html->link('Kapcsolat','/pages/kapcsolat'); ?></li>
      <?php if($session->read('User')){ ?>
      <li><?php print $html->link('Termékcsoportok','/termekcsoportok/'); ?></li>
      <li><?php print $html->link('Termékeink','/termekek/'); ?></li>
    </ul>
    <?php }?>
  </div>

  <div id="lablec">
    <p>
      Ahimsa Kozmetikai Kft.
      1028 Budapest, Kossuth Lajos utca 47.
      telefon / fax : +36 1 275 7798
      mobil: +36 20 4727 114
      e-mail :  <a href="mailto:tulasi@tulasi.hu">tulasi@tulasi.hu</a>
    </p>
  </div>

</div>
</body>
</html>

A szükséges képek és css file letölthető innen. A miértekről és hogyanokról nem fogok írni itt, mert egyrészről már megírtam itt, másrészről pedig semmiféle cakePHP specifikus részlete sincs.

Ok, akkor ha designunkat aktiváltuk (és akkor is ha nem 🙂 ), léphetünk tovább.

CakePHP Ajax helper

Hát biztos lehet Ajax nélkül is weblapot csinálni, de előbb-utóbb úgyis szeretnénk a Cake Ajax támogató rétegével is megismerkedni, szóval itt a legjobb alkalom.

A helper becsatolása

Először is meg kell nyitnunk a /app/app_controller.php filet és a $helpers tömbbe be kell tennünk az ajaxot is.


var $helpers = array('html','javascript','form','ajax');

Az igény

Azt szeretnénk, hogy legyen a menüben egy Termékeink link, amire ha a user rákattint, akkor a menüben alatta megjelennek a termékcsoportok nevei. Ha valamelyik termékcsoport névre kattintunk, akkor a tartalom részen jelenjen meg a kiválasztott termékcsoport termékeinek a listája.

Alap átalakítások

Eljött az ideje, hogy szomrú búcsút vegyünk a termékcsoportok controllerjében a scaffoldtól. Azért kényszerülünk erre, mert jelen pillanatban minden termékcsoportbeli függvény végrehajtása előtt a beforeFilter miatt végre fog hajtódni az ellenőrzés, hogy bejelentkezett adminisztrátottól van-e szó vagy sem. Ez nekünk most már nem lesz jó, mert minden usernek hozzá kell férnie a termékcsoportok neveihez ahhoz, hogy a menüben meg tudjanak jelenni. Az előző részekben leírt módon a kedvenc bake script segítségével hozzuk létre a termékek controller és view filejait az alap függvényekre (index, hozzaad, mutat, szerkeszt). Minden magyarázat nélkül segítségként itt a kimenet:

rrd-mac:~/Sites/tulasi/cake/scripts rrd$ php bake_hu.php -app /Users/rrd/Sites/tulasi/app/

 ___  __  _  _  ___  __  _  _  __      __   __  _  _  ___ 
|    |__| |_/  |__  |__] |__| |__]    |__] |__| |_/  |__ 
|___ |  | | \_ |___ |    |  | |       |__] |  | | \_ |___ 
---------------------------------------------------------------



Baking...
---------------------------------------------------------------
Name: app
Path: /Users/rrd/Sites/tulasi/app
---------------------------------------------------------------
[M]odel
[C]ontroller
[V]iew

What would you like to Bake? (M/V/C) 
> c
---------------------------------------------------------------
Controller Bake:
---------------------------------------------------------------
Possible Controllers based on your current database:
1. CakeSessions
2. Termekek
3. Termekcsoportok
4. Users

Enter a number from the list above, or type in the name of another controller.  
> 3

Would you like bake to build your controller interactively?
Warning: Choosing no will overwrite  controller if it exist. (y/n) 
[y] > 

Would you like to use scaffolding? (y/n) 
[y] > n

Would you like to include some basic class methods (index(), hozzaad(), mutat(), szerkeszt())? (y/n) 
[n] > y

Would you like to create the methods for admin routing? (y/n) 
[n] > n

Would you like this controller to use other models besides 'Termekcsoport'? (y/n) 
[n] > 

Would you like this controller to use other helpers besides HtmlHelper and FormHelper? (y/n) 
[n] > n

Would you like this controller to use any components? (y/n) 
[n] > 

Would you like to use Sessions? (y/n) 
[y] > 

---------------------------------------------------------------
The following controller will be created:
---------------------------------------------------------------
Controller Name:        Termekcsoportok
---------------------------------------------------------------

Look okay? (y/n) 
[y] > 

Creating file /Users/rrd/Sites/tulasi/app/controllers/termekcsoportok_controller.php
File exists, overwrite? /Users/rrd/Sites/tulasi/app/controllers/termekcsoportok_controller.php (y/n/q):y
Wrote/Users/rrd/Sites/tulasi/app/controllers/termekcsoportok_controller.php

Cake test suite not installed.  Do you want to bake unit test files anyway? (y/n) 
[y] > n
rrd-mac:~/Sites/tulasi/cake/scripts rrd$ php bake_hu.php -app /Users/rrd/Sites/tulasi/app/

 ___  __  _  _  ___  __  _  _  __      __   __  _  _  ___ 
|    |__| |_/  |__  |__] |__| |__]    |__] |__| |_/  |__ 
|___ |  | | \_ |___ |    |  | |       |__] |  | | \_ |___ 
---------------------------------------------------------------



Baking...
---------------------------------------------------------------
Name: app
Path: /Users/rrd/Sites/tulasi/app
---------------------------------------------------------------
[M]odel
[C]ontroller
[V]iew

What would you like to Bake? (M/V/C) 
> v
---------------------------------------------------------------
Mutat Bake:
---------------------------------------------------------------
Possible Controllers based on your current database:
1. CakeSessions
2. Termekek
3. Termekcsoportok
4. Users

Enter a number from the list above, or type in the name of another controller.  
> 3

Would you like bake to build your views interactively?
Warning: Choosing no will overwrite  views if it exist. (y/n) 
[y] > 

Would you like to create some scaffolded views (index, hozzaad, mutat, edit) for this controller?
NOTE: Before doing so, you'll need to create your controller and model classes (including associated models). (y/n) 
[n] > y

Would you like to create the views for admin routing? (y/n) 
[n] > 

Creating file /Users/rrd/Sites/tulasi/app/views/termekcsoportok/index.thtml
Wrote/Users/rrd/Sites/tulasi/app/views/termekcsoportok/index.thtml

Creating file /Users/rrd/Sites/tulasi/app/views/termekcsoportok/mutat.thtml
Wrote/Users/rrd/Sites/tulasi/app/views/termekcsoportok/mutat.thtml

Creating file /Users/rrd/Sites/tulasi/app/views/termekcsoportok/hozzaad.thtml
Wrote/Users/rrd/Sites/tulasi/app/views/termekcsoportok/hozzaad.thtml

Creating file /Users/rrd/Sites/tulasi/app/views/termekcsoportok/szerkeszt.thtml
Wrote/Users/rrd/Sites/tulasi/app/views/termekcsoportok/szerkeszt.thtml
---------------------------------------------------------------

Mutat Scaffolding Complete.

A /app/controllers/termekcsoportok_controller.php fileból vegyük ki a $helpers tömböt, mivel itt felesleges, az app_controller.php fileban már megadtuk. Az index(), mutat(), hozzaad(), szerkeszt() és torol() metódusokat továbbra sem szeretnénk be nem jelentkezett userek számára elérhetővé tenni, ezért mindegyik függvény elejére be kell tennünk az ellenőrző függvényünk hívását. Tehát pl az index függvényünk így fog kinézni:

function index() {
  $this->userEllenorzo();
  $this->Termekcsoport->recursive = 0;
  $this->set('termekcsoportok', $this->Termekcsoport->findAll());
  }

Termékcsoportok listája

A termekcsoportok_controller.php fileban hozzunk létre a csoportlista nevű függvényt. A függvény a termékcsoportok neveit és a hozzájuk tartozó termékek adatait fogja lekérni. A recursive tulajdonságot 1-re állítjuk, hogy a kapcsolódó modell (a termékek) adatai is elérhetőek legyenek. A render metódust meg kell hívnunk a végén, hogy a válasz a default.html nélkül kizárólag a következő lépésként létrehozott view file alapján jöjjön.

function csoportlista(){
  //a termékcsoportok neveit adja vissza a hozzá tartozó termékek számával együtt
  $this->Termekcsoport->recursive = 1;
  $this->set('csoportlista', $this->Termekcsoport->findAll(null, null, 'termekcsoport ASC'));
  $this->render('csoportlista','ajax');
  }

A /app/views/termekcsoportok/csoportlista.thtml filet is létre kell hoznunk a következő tartalommal.

<ul>
<?php
foreach ($csoportlista as $csoport){

Végigmegyünk a controllerben létrehozott $csoportlista tömb minden elemén

  print '<li>' .

Minden termékcsoport egy li elemben lesz elhelyezve.

    $html->link($csoport['Termekcsoport']['termekcsoport'], '/termekek/csoport/' . $csoport['Termekcsoport']['id']) .
    ' (' . count($csoport['Termek']) . ')' . 
    '</li>' . "\n";
	}
?>
</ul>

Így kiírattuk a termékcsoportok neveit egy linkkel, ami pl a /termekek/csoport/5 helyre mutat. Azért használunk unordered list-et, mert az ajax kérésünk ezt várja majd vissza eredményül.

Ha most meghívjuk a http://localhost/~rrd/tulasi/index.php/termekcsoportok/csoportlista URL-t, akkor a termékcsoportokról fogunk kapni egy pórias kinézetű listát. Ha nem akkor valamit elszúrtunk.

Ezek után nem marad más hátra, mint hogy az oldalunkban elhelyezzük azt a kódot ami elindítja és fogadja az ajax lekérést. Ehhez először a default.thtml file eljén be kell csatolnunk az ehhez szükséges JavaScript fileokat.

<!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" lang="hu" xml:lang="hu">
<head>
<?php print $html->charset('utf-8')?>
<title><?php print $title_for_layout?></title>
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
<?php print $html->css('cake.generic')?>
<?php print $html->css('tulasi')?>
<?php print $javascript->link('prototype')?>
<?php print $javascript->link('scriptaculous.js?load=effects')?>
<?php print $javascript->link('controls')?>
</head>

Ezután pedig valahol a menünkben elhelyezhetjük az ajax-hívó részt.

<li>
  <?php print $ajax->link('Termékeink','/termekcsoportok/csoportlista/',
    array('url' => '/termekcsoportok/csoportlista',
      'update' => 'termekekacsoportban')); ?>
  <div id="termekekacsoportban">
  </div>
</li>

Ajax

Az ajax helper link metódusa az alábbi paraméterekkel dolgozik:
$ajax->link(‘$aLinkSzövege’, ‘$hrefTag’, ‘$opciok’, ‘$confirm’, ‘$escapeTitle’);
A $aLinkSzovege az a szöveg amit meg kívánunk jeleníteni linkként, esetünkben a Termékeink szó, a $hrefTag az az url amire a linkünk mutat (ez nem lesz használva bekapcsolt JavaScript esetén, csak ha ki van kapcsolva) a $opciok tömbben kell átadnunk az Ajax hívás részleteit, a további paramétereket itt nem használtuk.

A $opciok tömbben (pár másik melett) az alábbi paramétereket adhatjuk át:

  • url: Annak a php filenak az url-je ami az Ajax választ fogja adni
  • update: A válaszként érkező html kód ezzel az id-vel rendelkező elembe kerülnek bele
  • loading: A töltés alatt futtatandó JavaScript kód
  • loaded: A válasz megérkezését követően meghívandó JavaScript kód

A termekekacsoportban id-jű div az Ajax válasz befogadására szolgál.

Ezek után ha elmegyünk a főoldalra akkor a termékeink linkre kattintva közvetlenül alá be kell töltődnie a termékcsoport linkeknek. Némi css formázás valószínűleg rájuk fog férni, de ezt megincsak oldja meg mindenki magának.

Termékek egy adott csoportban

Szomorúan tapasztaljuk, hogy ha a menüben valamelyik termékcsoport nevére kattintunk úgy hogy nem vagyunk bejelentkezve, akkor a user beléptető oldal jelenik meg, ha pedig be vagyunk jelentkezve, akkor egy hibaüzenet, ami arra biztat, hogy hozzuk létre a csoport nevezetű függvényt a termekek_controller.php fileban. Hát tegyünk így:

function csoport($id = null){
  //a $id csoportba tartozó termékek listája
  $this->pageTitle = 'Tulasi ::: Termékek';
  if($id){
    $this->Termek->recursive = 0;
    $this->set('termekekacsoportban', $this->Termek->findAll('termekcsoport_id = ' . $id));
    $this->set('termekcsoport', $this->Termek->Termekcsoport->findById($id));
    }
  }

És a hozzá tartozó view létrehozása.

<h1>Termékek a(z) <?php print $termekcsoport['Termekcsoport']['termekcsoport']; ?> termékcsoportban</h1>
<ul>
<?php
foreach ($termekekacsoportban as $termek){
  print '<li>' .
    $html->link($termek['Termek']['termeknev'], '/termekek/mutat/' . $termek['Termek']['id']) .
    '</li>' . "\n";
	}
?>
</ul>

Ezután már nem is marad más hátra mint, hogy a termekek_controller.php fileból a termekcsoportok_controller.php filehoz hasonlóan eltávolítsuk a beforeFilter szűrőt, és a userEllenorzo() függvény kézzel betegyük az index(), hozzaad(), szerkeszt(), és torol() metódusok legelejére. A mutat() és a csoport() metódusok elejére nem tegyük be, mivel ezeket bárki elérheti, nem kell hozzájuk bejelentkezni.

Ezzel akár azt is mondhatjuk, hogy készen vagyunk. Persze a termékek mutat.thtml fileját kicsit lehetne még pofásítani, és mondjuk ebben csak akkor felkínálni a szerkesztő és törlő linkeket, ha a látogató be van jelentkezve, de ezeket az eddigiek alapján már bárki gyorsan megoldja.

Zárszó

Aki vette magának a fáradtságot, hogy végigolvassa mind a 8 részt az mostanra kapott egy kis izelítőt a Cake felépítéséről, gondolatmenetéről és működéséről. Nem volt alkalmam kipróbálni, de úgy saccolom, hogy ennek a projectnek a felépítése eddig a szintig a Cake segítségével egy kis gyakorlás után kb 2 órát vesz igénybe. a bake script létrehozott nekünk összesen kb 400 sornyi programkódot, amihez nekünk 200 sornyi kódot kellet írnunk css-estől, mindenestől. Valószínűleg belefektethetnénk még némi energiát a kód optimalizálásába, csinosításba és a felhasználói élmény javításába, de mindösszesen azt biztosan kijelenhetjük, hogy a CakePHP keretrendszer segítségével a fejlesztésre fordított idő jelentősen csökkent.

Mindenkinak ajánlom a magyar fórumot ha kérdése van más a cikkekben nem tárgyalt dolgokkal kapcsolatban.

Mindenkinek jó tortázást 🙂

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöljük.