Archive for the ‘download’ category

neue Music-Downloadplattform mit Freedownloads mit Zend-Framework online.

February 4th, 2010

Hier ein Beispiel wie man es häufiger sehen möchte.

http://www.zeezee.de setzt in Ihrer innovativen Idee mal eine eine etwas andere Musik-Downloadplattform umzusetzen Zend-Framework und Jquery als Schlüsseltechnologie ein und überzeugt auf Anhieb mit Qualität, Einfachheit und Spass beim Musiksuchen.

Die Registrierung ist extrem einfach und man kann sofort loslegen.  Die Mail zur Aktivierung ist auch in der Schweiz unter 1 Minute verfügbar.

Als Erstes habe ich nach dem Login die Charts aus meinem Geburtsjahr gefunden. Coole Sache. Elvis lebt :-)

Die älteren Jahrgänge erinnern sich sicher an die Zeit als man noch am Radio mitgeschnitten hat. Das läuft hier ähnlich. Man sucht sich einen Song aus, der gespielt werden soll und wenn  ein User ihn abspielt wird er für Dich zum Download bereit gestellt. Bei mir dauerte das ca 3 Minuten. Man wird hier per Message über den bereitgestellten Song informiert.

Nach der Registrierung sind die aktuellen Top 20  Songs kostenfrei. Gute Sache.

Was mir persönlich sehr zusagt ist die Performance und die Usability der Seite. Sie ist schnell und sehr einfach. Man kommt mit wenigen Klicks an seine Wunschmusik.

Das Musik Angebot ist riesig. 16 Mio Tracks stehen zur Auswahl. Unglaublich.

Ein Besuch der Seite http://www.zeezee.de ist für PHP-ler eigentlich Pflicht. Musikliebhaber die auf Nostalgie stehen werden begeistert sein.

Seitenweise blättern. Paging ohne doppelte Datenbankzugriffe

November 27th, 2009

Wer mal eben ein Paging für aufwendige Views einbauen möchte findet im Internet meistens ein und das selbe Herrangehen an das Problem.
Es wird erst eine limitierte Query abgesetzt und die Datensätze gezählt und anschliessend wird die Datenbank nochmal abgefragt um das result zu erstellen.

Das ist im Prinzip unperformant, weil man komplexe Tabellen eben 2 mal abfragen muss.
Dazu sehen die Zugriffe und die Codes meist sehr chaotisch aus.
Ein weiterer Nachteil ist die unschöne Darstellung der Seitenlinks, wenn viele Seiten existieren.

Ich habe mir im Zuge eines Kundenprojektes die Arbeit machen müssen eine “saubere” OOP Implemantation vorzunehmen.
Was rauskam ist eine OOP-PHP 5 Portierung der Pagings von ExtJS. Es gibt keine Seitenlinks mehr sondern ein Eingabefeld, welches die momentane Seite anzeigt. Der Vorteil ist, dass man die gewünschte Seite auch einfach eingeben kann.
Ein weiterer Vorteil ist, dass man der Klasse einfach ein Array mit einen Resultset übergeben kann, den Rest mach die Klasse. Keine Weiteren Datenbakabfragen also. Man braucht auch nicht unbeding mysql sondernd die Klasse ist unabhängig vom Datenbanksystem, welches PHP verwendet.

Die Klasse benötigt also keine eigene Datenbankabstraktion sondern nutzt die der Anwendung. Zudem ist der Code gekapselt und man hat keinen Aerger mit ungewollten Namenskonflikten.
Fullscreendemo
Download

Die Einrichtung ist simple. Nun folgt ein Beispiel mit dem Code des Samples hier.
In der Praxis habe ich natürlich statt des einfachen Arrays ein Array mit Objekten verwendet. Und als HTML Engine kam Smarty zum Einsatz.
Wer die Smartyimplementierung sehen will kann sich bei mir melden.
Das Sample ist reduziert. für die Erstellung des Tableheaders sollte man die methode addHeader() verwenden. Und das Form ausserhalb definieren.

Features:

  • OOP
  • Datenbankunabhängig
  • externe Stylesheets
  • keine Linklisten
  • einstellbare Einträge / Seite (auch über den Request)
<?php
/*
 * thats the sample how to use the pagingclass
 */
require_once 'C_PAGING.php';
require_once 'populatedata.php';
//define vars wich must be trasported in the request (UserIDs, Sessions etc)
$arr_params=array("neededParam"=>$_REQUEST['neededParam']);
//instantiiate the pagingclass with 4 parameter
$controller="sample.php";
//the name of the pageparameter (page=1)
$paginVarName="page";
$_paging= new C_PAGING($controller, $arr_params, $result,$paginVarName);
//how many entries per page
$_paging->entriesPerPage=4;
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <head>
        <link rel='stylesheet' type='text/css' href='css/style.css' />
        <link rel='stylesheet' type='text/css' href='css/table.css' />
    </head>
    <body >
        <table id="sortable_table" class="datagrid">
            <thead>

                <tr>
                    <th width="200">Firstname</th>
                    <th width="200">Lastname</th>
                    <th width="300">Street</th>
                    <th>Location</th>
                    <th>Zip</th>
                </tr>
            </thead>
            <?php
            //iterate the resultset
            foreach($result as $key=>$arr_value) {
                $html[$key].="<tbody>";
                $html[$key].="<tr>";
                $html[$key].="<td>".$arr_value['firstname']."</td>";
                $html[$key].="<td>".$arr_value['lastname']."</td>";
                $html[$key].="<td>".$arr_value['street']."</td>";
                $html[$key].="<td>".$arr_value['location']."</td>";
                $html[$key].="<td>".$arr_value['Zip']."</td>";
                $html[$key].="</tr>";
                $html[$key].="</tbody>";
                //add current row to the object
                $_paging->addRow($html[$key]);
            }
            //add navigation
            echo $_paging->addNavigation();
            //diplay tablefooter
            ?>
        </table>
    <body>
</html>

Daten populieren
Die Daten kommen aus einem einfachen array. Ihr könnt auch ein Database result nehmen.
Wichtig ist nur das die Struktur : array(’1′=>value,2=>value2) ist

<?php
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

//populate from an array, sample of using a resultset coming soon
$result = array();

$result[1]['firstname'] ="Peter";
$result[1]['lastname']  ="Böthig";
$result[1]['street']    ="Bodenacher Strasse 65";
$result[1]['location']  ="Benglen";
$result[1]['Zip']       ="Benglen";

$result[2]['firstname'] ="Stephen";
$result[2]['lastname']  ="King";
$result[2]['street']    ="Mainstreet";
$result[2]['location']  ="Manchaster Str.22";
$result[2]['Zip']       ="Birmingham";

?>

Die Klasse C_PAGING.php dazu ist auch überschaubar.

<?php
/*
 * @desc generates a pagein for database views
 * no database is needed.
 * the paging will be generated from an databaseresult. in the simplest was it is an array
 * @author peter boethig
 * @date : 26.11.09
 * @copyright by Peter Böthig
 * @ feel free to use ist for free
 * @version 1.0
 */

class C_PAGING {
//selftalking
    var $entriesPerPage  = 20;
    //simly an iterator
    var $iterator        = 0;
    //current page
    var $page            = 1;
    //count the elements in the db-results
    var $countElements   = 0;
    //the HTML Row
    var $row             = array(0=>'<tr>eine row</tr><tr>eine row</tr><tr>eine row</tr>');
    //the tableheader
    var $headerHTML      = "<table><tr><td>header1</td><td>header2</td><td>header3</td></tr>";
    //the closing table
    var $footerHTML      = "</table>";
    //the linktaget
    var $target          = "_self";
    //the page wich the link routes
    var $controller      = "yourPageHier.php";
    //contains the needed requestparameters
    var $params          = array();
    //the style of the link
    var $buttonCSS       = "buttonCSS";
    //the buttons
    var $pagesCSS         = "pagesCSS";
    //the style for the linkcontainer
    var $pagingDIVCSS    = "pageingDiv";
    //default next, back, next, last arrows you can use images here
    var $arr_images      = array("first"=>"&lt;&lt;","back"=>"&lt;","next"=>"&gt;","last"=>"&gt;&gt;");
    //the displayed HTML
    var $html            = array();

    var $pages           = 0;
    //requestpagameter
    var $currentPage     = 1;
    //hiddenfields needed for request
    var $hiddenfields    = "";
    //default requestvar
    var $requestvariable ="page";

    /**
     * @desc builts the maindatas
     * @param <string> $controller
     * @param <array> $params
     * @param <array> $result
     */
    function  __construct($controller,$params,$result,$requestvariable) {
    //if requestparam > pages or 0
        if($requestvariable=="") {
            $this->requestvariable=$requestvariable;
            echo"Warning: no requestvariable defined: using \$requestvariable";
        }
        if($_REQUEST[$requestvariable] > 0) {
            $this->currentPage = $_REQUEST[$requestvariable];
        }
        else {
            $this->currentPage=1;
        }

        //databaseresult ist needed
        if(count($result)<1) {
            die(get_class()."__construct() keine Daten zu pagen");
        }
        if(isset($controller)) {
            $this->controller=$controller;
        }
        if(isset($params)) {
            $this->params=$params;
        }
        $this->countElements = count($result);
    }
    /**
     * @desc generates needed hiddenfields from needed parameters
     * @return <string>
     */
    function setHiddenFields() {
        if(is_array($this->params)) {
            foreach($this->params as $key=>$param) {
                $this->hiddenfields .="<input type='hidden' name='".$key."' id='".$key."' value='".$param."' />";
            }
            $this->hiddenfields .="<input type='hidden' name='entriesPerPage' value='".$this->entriesPerPage."' />";
        }
        return $this->hiddenfields;
    }
    /**
     * @desc checks the request if var is given
     */
    function setEntriesPerPage() {
        if($_REQUEST['entriesPerPage']!= $this->entriesPerPage && $_REQUEST['entriesPerPage'] > 0 ) {
            $this->entriesPerPage=$_REQUEST['entriesPerPage'];
        }
    }

    /**
     * @desc simply resets the iterator if entriesperpage is reached
     */
    function work() {
        $this->setEntriesPerPage();
        //calc pages
        $this->pages = ceil($this->countElements / $this->entriesPerPage);
        //reset if max is reached
        if($this->currentPage > $this->pages) {
            $this->currentPage=1;
        }

        if($this->iterator == $this->entriesPerPage) {
            $this->iterator=0;
            $this->page++;
        }
    }
    /**
     * @desc adds a HTML ROW to an array
     */
    function addRow($row) {
        $this->work();
        $this->row[$this->page] .= $row;
        $this->next();
    }
    /**
     * @desc increeses iterator
     */
    function next() {
        $this->iterator ++;
    }

    /**
     * @desc returns the list with entries
     * @param <int> $page
     * @return <array>
     */
    function addCurrentPage($page) {
        return $this->row[$page];
    }
    /**
     * @desc contains the HEaderHTML
     * @param <type> $headerHTML
     * @return <type>
     */
    function addTableHeader($headerHTML) {
        return $this->headerHTML = $headerHTML;
    }
    /**
     * @desc returns the tablefooter
     * @param <string> $footerHTML
     * @return <HTML>
     */
    function addTableFooter($footerHTML) {
        return $this->footerHTML = $headerHTML;
    }
    /**
     * @desc adds navigation
     */
    function addNavigation() {
        $this->html ="<form class='f_form' name='form_paging' action='".$this->controller."' target=".$this->target.">";
        $this->html.= $this->setHiddenFields();
        $this->html.="<div id='".$this->pagingDIVCSS."'>";
        //sets the first,next, back, etc
        $this->setFirstLinks();
        //sets the pagelinks
        $this->setPageField();
        //sets the next, lastlinks
        $this->setNextLinks();
        $this->html.="</div>";
        $this->html.="</form>";
        //display page
        $this->html.= $this->addCurrentPage($this->currentPage);
        return $this->html;
    }
    /**
     * @desc sets the next and lastlinks
     */
    function setNextLinks() {

        if($this->arr_images['next']!="&gt;"&& $this->arr_images['last']!="&lgt;&lt;") {
            $this->html.= "<img src='".$this->arr_images['first']."'/>&nbsp;<img src='".$this->arr_images['back']."'/>&nbsp;";
        }else {

            $this->html.= "<a href='".$this->controller."?page=".$this->setNext().$this->getParams()."'
            target=".$this->target." class=".$this->buttonCSS.">".$this->arr_images['next']."</a>
            <a href='".$this->controller."?page=".$this->setLast().$this->getParams()."'
            target=".$this->target." class=".$this->buttonCSS.">".$this->arr_images['last']."</a>";

        }
    }
    /**
     * @desc sets the next and lastlinks
     */
    function setFirstLinks() {
        if($this->arr_images['first']!="&lt;&lt;" && $this->arr_images['back']!="&lt;") {
            $this->html.= "<img src='".$this->arr_images['first']."'/><img src='".$this->arr_images['back']."'/>";
        }else {
            $this->html.= "
            <a href='".$this->controller."?page=".$this->setFirst().$this->getParams()."    ' target=".$this->target."
            class=".$this->buttonCSS.">".$this->arr_images['first']."</a>
            <a href='".$this->controller."?page=".$this->setPrievious().$this->getParams()."' target=".$this->target."
            class=".$this->buttonCSS.">".$this->arr_images['back']."</a>";
        }
    }

    /**
     * @desc sets the privious page
     * @return <int>
     */
    function setFirst() {
        return 1;
    }
    /**
     * @desc sets the privious page
     * @return <int>
     */
    function setPrievious() {
        if($this->currentPage > 1) {
            return $this->currentPage-1;
        }
        return 1;
    }
    /**
     * @desc sets the next page
     * @return <int>
     */
    function setNext() {
        if($this->currentPage < $this->pages) {
            return $this->currentPage + 1;
        }
        return $this->pages;
    }
    /**
     * @desc sets the last page
     * @return <int>
     */
    function setLast() {
        return $this->pages;
    }

    /**
     * @desc sets the pagelinks
     */
    function setPageField() {
        $this->html.="
    <p class='ofPages'>Seite</p>
    <input type='text' id='f_page' name='page' class='f_page' value='".$this->currentPage."'/>
    <p class='ofPages'> von ".$this->pages."</p>";
    }
    /**
     * builts the URL
     */
    function setURL() {

        return $this->controller."?page=".$this->page.$this->getParams();
    }
    /**
     * sets the paramstring
     */
    function getParams() {
        if(is_array($this->params)) {
            foreach($this->params as $key=>$param) {
                $paramString .="&amp;".$key."=".$param;
            }
            $paramString.="&amp;entriesPerPage=".$this->entriesPerPage;
        }
        return $paramString;
    }
}
?>

abschliesend noch die Styles (style.php) dazu:

/*
    Document   : style.css
    Created on : 27.11.2009, 11:34:13
    Author     : Peter Boethig
    Description:
        Styles for the paginengin
*/

/*
   TODO customize this sample style
   Syntax recommendation http://www.w3.org/TR/REC-CSS2/
*/

#pageingDiv
{
    border:0px solid black;
    width:250px;
    color:#000;
    height:30px;
    background-image:url('../images/pagingBackground.gif');
    padding:8px 0 0 40px;
    margin:0 0 0 0;
    font-weight:bold;
    text-align:center;
    font-family:verdana, sans-serif;
    font-size:12px;

}

#pageingDiv a.buttonCSS:link,
#pageingDiv a.buttonCSS:link,
#pageingDiv a.buttonCSS:hover,
#pageingDiv a.buttonCSS:active,
#pageingDiv a.buttonCSS:visited
{
    padding:2px 3px 0 0;
    margin:0 2px 0 0 ;
    color:#487efa;
    font-weight:bold;
    display:block;
    width:22px;
    height:20px;
    float:left;
    text-align:center;
    border:1px solid #ffffff;
    text-decoration:none;
    background-color:#fff;
    background-image:url('../images/pagingBackground.gif');

}
#pageingDiv a.buttonCSS:hover
{
    color:#cecece;
    background-color:#487efa;
    background-image:none;
}

#pageingDiv a.pagesCSS:link,
#pageingDiv a.pagesCSS:link,
#pageingDiv a.pagesCSS:hover,
#pageingDiv a.pagesCSS:active,
#pageingDiv a.pagesCSS:visited
{
    border:0;
    padding:0 3px 0 0;
    color:#000;
    display:block;
    width:20px;
    float:left;
    text-align:center;
}

#pageingDiv a.pagesCSS:hover
{
    color:#cecece;
}

#f_page{
    width:40px;
    height:22px;
    padding:0;
    margin:0;
    float:left;
    color:#487efa;
    font-size:14px;
    background-image:url(../images/inputBG.gif);
}

p.ofPages
{
    float:left;
    padding:4px 3px 0 3px;
    font-size:11px;
    font-weight:normal;
    color:#487efa;
}

.f_form
{
    margin:0;
    padding:0;

}