Peter Rehm's Blog

apple,development,life & more

PEAR unter OSX Leopard installieren

Mit 1 Kommentar

Im folgenden wird in aller kürze beschrieben, wie man PEAR unter
OSX 10.5 Leopard installiert. Dies sollte unter den vorherigen OSX
Versionen sicher ähnlich funktionieren.

Auf meinem lokalen System habe ich PHP5 von entropy.ch am laufen, da
ich unbedingt die GD-Lib benötige. Dies hat nur Einfluss auf die Ablage
der php.ini. Dies muss eben von den auf dem jeweilig auf dem System vorhandenen
Gegebenheit abhängig gemacht werden.

Wir werden in /usr/local/ installieren, und dem System gestatten die TEMP-Files
in /usr/local/temp abzulegen.

CODE:
sudo mkdir /usr/local/temp
sudo chmod -R 777 /usr/local/temp
sudo mkdir /usr/local/share/pear
sudo chmod -R 777 /usr/local/share/pear


Im nächsten Schritt wird go-pear ausgeführt.

CODE:
curl http://pear.php.net/go-pear | php


Hier muss bei den Pfaden der 1. auf /usr/local geändert werden.
Alle anderen Einstellungen können in der Regel beibehalten werden.

Während der Installation kommt dann die Warnung, dass der PEAR Pfad
noch nicht in der php.ini vorhanden ist, und es deswegen zu Problemen
mit der Verwendung von den PEAR Scripts kommen kann.

Hier kommen wir an den Punkt wo es wichtig ist, zu wissen, wo die
Konfigurationsdatei des Webservers liegen muss. Dies kann man einfach
über ein kurzes Script herausfinden:

CODE:
<? phpinfo(); ?>


Im Browser die Datei ansehen und nach folgender Zeile suchen.

CODE:
Configuration File (php.ini) Path /usr/local/php5/lib


Hier muss die php.ini für den Webserver liegen, die php.ini für
das Command-Line-Interface (CLI) unabhängig davon in /etc/

Standardgemäß ist eine php.ini.default in /etc/. Diese kopieren
und modifizieren wir zunächst.

CODE:
sudo cp /etc/php.ini.default /etc/php.ini
sudo nano /etc/php.ini


Nun nach dem Eintrag include_path suchen und diesen um "/usr/local/share/pear"
ergänzen. Bei mir sah dies nach der Anpassung so aus.

CODE:
include_path=".:/usr/local/share/pear"


Ist eine php.ini in dem Config-Path des Webservers vorhanden bearbeiten
wir diese, ansonsten kopieren wir die Datei /etc/php.ini an die gewünschte
Stelle

CODE:
sudo cp /etc/php.ini /usr/local/php5/lib/php.ini


Abschließend muss noch der Webserver neu gestartet werden, dann ist PEAR
einsatzfähig.

CODE:
sudo apachectl restart


Anmerkung: Kann PEAR von der Konsole nicht mit dem Befehl pear aufgerufen werden,
ist /usr/local/bin nicht korrekt in den SHELL-Pfaden eingetragen, und sollte nachgetragen
werden. Tipp: echo $PATH zum überprüfen in der SHELL eingeben.

Geschrieben von Peter Rehm

02.01.2008 um 11:16:31

Abgelegt in PHP

Tags für diesen Artikel: , ,

jpgraph und utf-8 daten

Mit 6 Kommentaren

Wer sich wundert wieso die Texte der erzeugten Graphen mittels jpgraph
in kryptischen Buchstaben dargestellt werden, obwohl gültige Daten in UTF-8
angeliefert wurden, ist nur einen kleinen Schritt von der Lösung entfernt.

Die Ursache des Problems liegt darin dass die Standardschriftarten von jpgraph
kein UTF-8 darstellen können.

Daher kann man sich einfach wie auch auf der jpgraph Seite angegeben ein
entsprechendes Schriftpaket herunterladen. Ich hab mich in meinem Fall für
Verda entschieden.Dies bekommt man hier: http://www.gnome.org/fonts/

Die Schirften lädt man sich herunter und lädt Sie in ein beliebiges Verzeichnis.

Nun muss nur noch das Verzeichnis der Library bekannt gemacht werden:

CODE:
DEFINE("TTF_DIR",dirname(_file_) . '/../../ttf-bitstream-vera-1.10/');


Nun muss man noch mittels SetFont angeben, wo welche Schrift eingesetzt werden
soll. Mir ist es allerdings nicht gelungen die Schriftart für die Beschriftung in den
Netzdiagrammen (jpgraph_radar.php) festzulegen, daher musste ich manuell
die Standardschrift ändern, indem ich in jpgraph.php und jpgraph_radar.php FF_FONT1
durch FF_VERA ersetzt habe.

Nun sollten alle Umlaute auch angezeigt werden können.

Geschrieben von Peter Rehm

01.10.2007 um 23:35:00

Abgelegt in PHP

Tags für diesen Artikel: , ,

Weitere Lektion in der Umlautproblematik

Mit 2 Kommentaren

Nachdem ich in einem früheren Blog Eintrag empfohlen habe, alle Daten aus
Speicherplatzgründen die im UTF-8 Format sind in z.b. dem latin1 charset abzulegen,
muss ich dem nun komplett wiedersprechen.
Bei einem durchschnittlichen Projekt lädt man sich deutlich mehr Ärger auf,
als dass man dadurch Vorteile durch Speicherplatzersparnis erzielt.

In meiner Situation sah das dann so aus, dass ich ca. 8 Stunden damit beschäftigt
war, alle Datenbanken meiner Kunden umzustellen, was enorm händische Arbeit
erforderte.

Im Ist-Zustand war es nun auch so, dass mittels phpMyAdmin logischerweise
alle Umlaute kaputt angezeigt wurde, und man nicht oder nur mit hohem manuellen
Aufwand direkt die Daten bearbeiten konnte.

Ausgangssituation
Datenbank mit latin1 als Standardcharset, alle Tabellen latin1, und UTF-8 Daten darin gespeichert.

Ziel
Datenbank & Tabellen UTF-8, und alle Inhalte UTF-8
Ich habe mich für utf8_general_ci entschieden, der unterschied zu utf8_unicode_ci liegt nur in
der Abhandlung von Sortierreihenfolgen. Dies kann man aber im Detail dem MySQL Manual entnehmen.

1.) Datenbank Backup erstellen
Gehen wir einfach mal auf nummer sicher, um die Daten auch sicher nicht
endgültig zu zerstören.

2.) Umwandeln aller Tabellen voll automatisch, und davon sollen auch alle
Text und Varchar Felder umgewandelt werden. Manch einer wird hier noch anpassungen
vornehmen müssen, da ich keine Char Felder umwandle, da die nicht benötigt
werden. ACHTUNG! Das Script basiert wie alle meine Code Snippets auf adodb,
kann aber Problemlos auf die von MySQL zur Verfügung stehenden Funktionen
portiert werden.

CODE:
<?php
// fetch all tables
$data = $cfg['db']->pExecute("SHOW
TABLES");
while($row = $data->FetchRow())
{
$sres = $cfg['db']->pExecute("DESCRIBE ".($row[0]));
while( $column = $sres->FetchRow())
{
// if column is text or varchar, convert
if(strpos($column['Type'],'text')!==false || strpos($column['Type'],'char')!==false
|| strpos($column['Type'],'varchar')!==false)
{
$cfg['db']->Execute("ALTER TABLE ".($row[0])." CHANGE ".($column['Field'])." ".($column['Field'])." ".($column['Type'])." CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL");
}
}

// confert now also full table
$cfg['db']->Execute("ALTER TABLE ".$row[0]." DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci");
}
?>


3.) Manuelles Umwandeln der Datenbank
Ich habe mich dazu entschieden die eigentliche Datenbank händisch umzuwandeln,
da ich mich eh mit der Datenbank verbinden musste. Dazu habe ich dann folgendes
SQL Statement eingegebn

CODE:
ALTER DATABASE `dbname` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci


4.) Exportieren der Daten
Nun werden die Daten der kompletten Datenbank exportiert, nicht aber die
Struktur. Dies wird für die meisten am besten mittels einer grafischen Oberfläche
wie phpMyAdmin erledigt. Hier kann man dies mit weigen Mausklicks erreichen.

5.) Umwandeln des Datendumps
Nun wandeln wir einfach noch die "kaputten Zeichen" zurück in UTF8.
In meinem Fall und in den meisten wird folgendes Script hinreichend sein.
Dazu muss eine Datei data.sql im gleichen Verzeichnis wie das eigentliche
PHP Skript sein.

CODE:
<?php
$str=file_get_contents('data.sql');

$bad_char=array("ä","ö","ü","Ä","Ö","Ü","ß");
$right=array('ä','ö','ü','Ä','Ö','Ü','ß');

$bla=str_replace($bad_char,$right,$str);

echo $bla;

?>


6.) Abschließende Arbeiten
Um die ganze Aktion abzuschließen, muss nur noch die Datenbank geleert werden,
un der neue Dump eingelesen werden. Dann sollte man die Umlaute alle
im entsprechenden Format in der Datenbank haben.

Nun werden einige aber sicher zerstörte Umlaute in der Ausgabe haben,
und sich wundern warum. Dies liegt an der MySQL Verbindung die einen
Befehl zu beginn benötigt um UTF8 sauber zu behandeln.

CODE:
$cfg['db']->Execute("SET names utf8");


Nun sollte es endlich geschafft sein, und man sollte sich nun hoffentlich
wieder wichtigeren Dingen widmen können :-)

Achja, heikel ist dann auch das string handling an manchen stellen, daher sollte man auf
die mb_* funktionen von PHP zurückgreifen.


Geschrieben von Peter Rehm

16.08.2007 um 02:38:50

Abgelegt in PHP

Tags für diesen Artikel: , ,

gängige PHP Fehler - Tipps & Tricks

Mit 2 Kommentaren

Neulich wurde ich gebeten, mir "kurz" ein kleines PHP Skript anzusehen,
und bei der Fehlersuche zu helfen. Dabei ist mit allerdings sehr schnell
aufgefallen dass einige grundlegende Unschönheiten zu finden sind.

Daher will ich anhand des mir zugesandten Codes einige Tipps zur PHP Entwicklung
geben.



  1. register_globals

    Ein immer wieder auftrendes Problem ist die register globals Geschichte,
    da PHP einem lange Zeit die Freiheit ließ, auf die POST Variable 'test' auf
    zwei Arten zuzugreifen. Entweder als $test, oder per $_POST['test'].
    Nutzt man erstere Variante kann man sich nie sicher sein, woher der
    Inhalt der Variablen eigentlich stammt, und man vergisst leicht einen
    vielleicht gefährlichen Inhalt zu escapen. Sofern die Möglichkeit besteht
    ist es sogar empfehlenswert register_globals auszuschalten. Aber man
    sollte es sich zumindest immer angewöhnen, auf POST/GET/REQUEST variablen
    immer mittels den dafür vorgesehenen superglobalen Arrays zuzugreifen.




  2. SQL Injections

    Eine große Gefahr stellen vor allem im Zusammenhang mit register_globals
    die SQL Injections dar, über die nicht gewollter SQL Code eingeschleußt
    werden kann. Um hier nicht auszuschweifen sollte man sich immer angewöhnen,
    Inhalt der manipuliert sein kann, zu escapen. Eine einfach Möglichkeit
    hierzu bietet mysql_real_escape_string(). Man sollte sich wenigstens
    angewöhnen den Inhalt immer zu escapen. Es empfiehlt sich auch eine
    eigene Funktion dafür zu nehmen, dass man später auch noch andere
    Verfahren einsetzen könnte, indem man nur eine Funktion überarbeiten
    muss. Hier ein Beispiel:



    CODE:
    /**
    * easy accesible handle to escape all db strings
    * @param string $string string which should be escaped to be put into an sql statement
    * @return string returns the escaped string
    */
    function escapeDB($string)
    {
    global $run;
    if(is_numeric($string))
    {
    return $string;
    } else {
    return $run['db']->qstr($string,get_magic_quotes_gpc());
    }
    }



  3. Variablen

    Man sollte Variablen immer klein schreiben, und Umlaute sollten nicht
    eingesetzt werden. Es ist meist auch recht angenehm die äquivalente englische
    Bezeichnung für Variablen zu verwenden. EIn unschönes Beispiel:



    CODE:
     '$Arbeitsverhaeltnis', '$Kündigungsfrist', '$Sonstiges'



  4. Fehlermeldungen

    Fehlermeldungen sollte man am besten immer beherzigen. PHP kennt verschiedene
    Modi, je nach "wichtigkeit" eines Fehlers. Meist werden die NOTICE's
    ausgeblendet. Allerdings sind NOTICES oft auch recht hilfreich,
    da man erkennt wo man z.B. eine noch nicht initialisierte Variable
    verwendet. Es empfiehlt sich meistens alle Fehlermeldungen anzuzeigen.
    Die macht man wie folgt:


    CODE:
    error_reporting(E_ALL);

    Vor allem gefährlich ist das manuelle Unterdrücken von Fehlermeldungen
    mittels dem @ Operator. Diesen sollte man auch nicht einsetzen, da dadurch
    die Fehlersuche oft erschwert sein kann.





Dies mal nur als kurze Zusammenfassung.

Geschrieben von Peter Rehm

07.06.2007 um 15:49:13

Abgelegt in PHP

Tags für diesen Artikel: ,

PHP5/PHP5 method_exists

Ohne Kommentare

Wenn mann dynamisch Methoden aus einer Klasse aufrufen möchte, kommt man
vermutlich an method_exists() kaum vorbei.

Heute musste ich allerdings feststellen, dass PHP4 alle Klassennamen im lowercase überprüft,
PHP5 hingegen so wie es geschrieben wurde. Dies führte natürlich in meinem aktuellen Projekt
zu massiven Schwierigkeiten.

Es bleibt kaum eine andere Lösung, als sich selber eine lowercase Version von method_exists anzufertigen.
Die könnte wie folgt aussehen.

CODE:
function _method_exists($class,$method)
{
$classMethods = array_map('strtolower', get_class_methods($class));

if(in_array(strtolower($method),$classMethods))
{
return true;
} else {
return false;
}
}


Das hab ich dann implementiert, und seither funktioniert alles so wie man es verwenden sollte.

Achja und wenn wir gerade beim Thema sind, man wird auch schnell feststellen, dass
call_user_method deprecated ist und daher nicht mehr eingesetzt werden sollte.
Zumindest laut meiner PHP4 version, im Manual konnte ich dazu nicht viel finden.

Dies kann man aus dem Weg schaffen, indem man call_user_func() oder call_user_func_array()
mit folgenden Parametern aufruft.

CODE:
call_user_func(array(&$object,'my_method_name'));

Geschrieben von Peter Rehm

31.03.2007 um 19:02:11

Abgelegt in PHP

Tags für diesen Artikel:

Validierung von Ausweisdaten mit PHP

Ohne Kommentare

Es kursieren unzählige Mythen um die Ausweisnummer. So behaupten einige,
die letzte Ziffer, sei die Zahl, wieviele Leute in Deutschland einem ähnlich
sind :-)
Dem ist nicht so. Hinter der Ausweisnummer steckt ein triviales System.

Der erste Block setzt sich zusammen aus der Ausgabenummer des Ortes, von dem
man den Ausweis bezogen hat, einer zufälligen Nummer, einer Prüfziffer, und
der Staatsangehörigkeit.

Beispiel:

CODE:
0000000005D


Die letzte Zahl vor dem D ist die Prüfziffer (5), und das D ist die Staatsangehörigkeit,
also Deutsch.

Der zweite Block beinhaltet das Geburtsdatum des Ausweisinhabers, in der
Form YYMMDD und eine Prüfziffer

Beispiel:

CODE:
8607209


9 ist in dem Beispiel die Prüfziffer, und der Ausweisinhaber wurde am 20. Juli 1986
geboren.

Der dritte Block ist wie der zweite, beinhaltet allerdings das Gültigkeitsdatum.

Beispiel:
CODE:
8607209


In dem Fall ist die Prüfziffer wieder 9, und der Ausweis ist gültig bis zum 20. Juli 1986.

Der letzte Block ist eine Prüfziffer von den Prüfziffern.

Prüfziffern



Hinter den Prüfziffern verbirgt sich ein einfacher Algorithmus.

CODE:
7 * die erste Zahl + 3 * die zweite Zahl + die dritte Zahl + 7 * die erste Zahl,...


Dies wird solange wiederholt, bis alle Zahlen summiert werden. Das Ergebnis Modulo 10
ist dann die Prüfziffer.

Beispiel:
CODE:
8607209


Berechnung:
CODE:
8*7 + 6*3 + 0 + 7*7 + 2*3 + 0 = 129

129 % 10 = 9

Daher ist die Prüfziffer 9.


Auch die Prüfziffer der Prüfziffern wird nach dem gleichen Algorithmus berechnet.

Code



CODE:
<?php
/**
* class to verify the german passport number
*/
class verify_passport
{

var $full_number;
var $blocks=array();
var $result;
var $is_valid=true;
var $expires;

/**
* Constructor
* @param string $number passportnumber
* @return void
*/
function verify_passport($number)
{
/**
* Remove the < and split into the 4 blocks
* If $number > 26 $number is invalid
*/
if(strlen($number)>26 || strlen($number)<26)
{
$number=str_replace('<','',$number);
if(strlen($number)>26)
{
die('invalid passport length');
}
}

$this->blocks[1]=substr($number,0,11);
$this->blocks[2]=substr($number,11,7);
$this->blocks[3]=substr($number,18,7);
$this->blocks[4]=substr($number,25,1);
foreach($this->blocks as $key => $value)
{
if(!$this->verify_block($key,$value))
{
echo $key;
$this->is_valid=false;
return;
}
}

/**
* Set the expire date
*/
$this->expires=mktime(0,0,0,substr($this->blocks[3],2,2),substr($this->blocks[3],4,2),substr($this->blocks[3],0,2));

}

/**
* Verifies the single Blocks
* @param integer $type block id
* @param string $data block content
* @return boolean
*/
function verify_block($type,$data)
{
switch($type)
{
case 1:
return ($this->calc_checksum(substr($data,0,-2))==$data{9} ? true : false );
break;
case 2:
case 3:
return ($this->calc_checksum(substr($data,0,-1))==$data{6} ? true : false );
break;
case 4:
return ($this->calc_checksum(substr($this->blocks[1],0,-1).substr($this->blocks[2],0).substr($this->blocks[3],0))==$data{0} ? true : false );
break;
}
}

/**
* Calculates the Checksum for the given line
* @param string $data
* @result unit place of the checksum
*/
function calc_checksum($data)
{
$result=0;
$length=strlen($data);
for($i=0;$i<$length;$i++)
{
switch($i%3)
{
case 0:
$result+=$data{$i}*7;
break;
case 1:
$result+=$data{$i}*3;
break;
case 2:
$result+=$data{$i};
break;
}
}
return $result%10;
}

/**
* Checks if all was valid - Also if passport is not expired
* @return boolean
*/
function is_valid()
{
if($this->is_valid)
{
if(time()<=$this->expires)
{
return true;
}
}
return false;
}

/**
* Returns the Age in array or unix timestamp
* @param integer $type 0=array 1=timestamp
* @return array or timestamp
*/
function get_age($type='0')
{

$year=substr($this->blocks[2],0,2);
/*
* Create a 4 digit Year number
*/
if($year>=20)
{
$year=(substr(date("Y"),0,2)-1)*100+$year;
} else {
$year=substr(date("Y"),0,2)*100+$year;
}
$month=substr($this->blocks[2],2,2);
$day=substr($this->blocks[2],4,2);

if($type==0)
{
return array('year'=>$year,
 'month'=>$month,
 'day'=>$day);
} else {
return mktime(0,0,0,$month,$day,$year);
}
}
}
?>


Funktionsweise


Der Constructor teilt die Nummer in die Blocks auf, und überprüft ob die Länge
der Nummer korrekt ist. Ist dies nicht der Fall wird die Class sofort beendet.
Der die() ist zugegeben etwas hart, und sollte im Produktiven Einsatz vielleicht
nicht so verwendet werden :-)

Danach kann ich mir über die Methode is_valid() anzeigen lassen, ob die
Ausweisnummer gültig ist. Die Funktion gibt einen Boolschen Wert zurück.
Neben den Prüfziffern wird auch überprüft, ob das Ablaufdatum noch nicht
erreicht ist.

Man kann sich auch das Geburtsdatum als Unix Timestamp oder als Array ausgeben lassen.
Dies geht mittels get_age($type). ist type 0 wird in Array mit den Keys (year,month,day
zurückgegeben, ansonsten ein Unix Timestam.

Der Einsatz



Das folgende Beispiel soll abschließend die Funktionsweise verdeutlichen.

CODE:
$try=new verify_passport($ppn);
var_dump( date("Ymd",$try->get_age(1)) );
var_dump( $try->is_valid() );


$ppn sollte die Ausweisnummer beinhalten.

Geschrieben von Peter Rehm

05.03.2007 um 18:51:31

Abgelegt in PHP

Tags für diesen Artikel: ,

Mails UTF-8 kodiert versenden

Ohne Kommentare

Ergänzend zum dem Eintrag bezüglich UTF-8 in Webapplikationen hier noch eine kurze Info zum versenden von UTF8 Mails mit PHP.

Man kann zum einen die Mails wieder in ISO konvertieren, allerdings möchte ich nur auf die Möglichkeit eingehen,
Mails unkonvertiert zu versenden. Dazu muss an sich nur das Encoding im Header in der Funktion mail()
gesetzt werden.

CODE:
mail("reciever@reciever.de",
 "subject",
 "content",
 "From: bla@bla.de\r\nContent-Type: text/plain; charset=UTF-8");


Alternativ kann man auch mb_send_mail() verwenden.

Geschrieben von Peter Rehm

17.02.2007 um 18:04:50

Abgelegt in PHP

Tags für diesen Artikel: ,

CSV Dateien in MySQL importieren

Ohne Kommentare

Ich musste gerade eine Reihe Postleitzahlen importieren, daher habe ich eine Quick & Dirty Lösumg geschrieben um CSV Dateien zu importieren.

CODE:
<?php

class csv2mysql
{
/**
* DB Host
*/
var $host='';

/**
* DB User
*/
var $user='root';

/**
* DB Pass
*/
var $pass='';

/**
* DB Name
*/
var $db;

/**
* Table Name
*/
var $table;

/**
* CSV Separator
*/
var $separator=';';

/**
* Filename to import
*/
var $filename;

/**
* DB Handle
*/
var $db_handle;

/**
* File Handle
*/
var $file_handle;

/**
* Max Line length in CSV File
*/
var $max_line_length=1000;

/**
* Insert Count
*/
var $count=0;

/**
* Konstruktor to set the options
*
* options: dbname,tablename,separator
*/
function csv2mysql($options)
{
if(empty($options['dbname']))
{
die("you have to enter a database name!");
} else {
$this->db=$options['dbname'];
}

if(empty($options['table']))
{
die("you have to enter a table name!");
} else {
$this->table=$options['table'];
}

if(empty($options['filename']))
{
die("you have to enter a filename!");
} else {
$this->filename=$options['filename'];
if(!file_exists($this->filename))
{
die("file does not exist");
}
}

if(!empty($options['separator']))
{
$this->separator=$options['separator'];
}

$this->db_handle=mysql_connect($this->host,$this->user,$this->pass);
mysql_select_db($this->db,$this->db_handle);

return;
}

function convert()
{
$this->file_handle=fopen($this->filename,"r");
if($this->file_handle && $this->db_handle)
{
while($data=fgetcsv($this->file_handle,$this->max_line_length,$this->separator))
{
$res=mysql_query("INSERT INTO ".$this->table."
 VALUES (".join($data,',').")",$this->db_handle) or die(mysql_error());
if($res)
{
$this->count++;
}
}
echo $this->count;
} else {
die("could not open file or database");
}
}
}

$imp=new csv2mysql(array('filename'=>'/www/test.csv',
'dbname'=>'plzdb',
'table'=>'plz'));
$imp->convert();
?>


Aufgrund den anstehenden Prüfungen verzichte ich auf das erklären des Codes, das müsste man auch so verstehen können :-)

Geschrieben von Peter Rehm

18.01.2007 um 21:33:35

Abgelegt in PHP

Tags für diesen Artikel: , , ,

Zahlungsverfahren - DTA Dateien per PHP erzeugen

Mit 3 Kommentaren

DTA ist ein in Deutschland existierender Standard für die Abwicklung
von Zahlungen. Die DTA Dateien können von jeder Bank oder per Banking Software
und unter anderem per HBCI verarbeitet werden.

Es gibt einige Szenarios, in denen man mit den DTA Dateien arbeiten könnte.
Z.b. für die Eigenentwicklung einer Finanzsoftware, in der die eingehenden
Rechnungen verwaltet werden. Aus den eingegeben Rechnungen kann man dann
automatsich per DTA Datei die Bezahlung einleiten. Dies wird in einigen großen
Buchhaltungslösungen so eingesetzt.

Es kann aber auch ein Lastschrifteinzug mit einer DTA Datei abgewickelt werden.
So kann man eine Vereinssoftware entwickeln, bei der die Monatsbeiträge per Lastschrift
eingezogen werden.

Wichtig ist, dass in einer DTA Datei entweder nur Überweisungen oder nur Lastschriften
stehen dürfen. Beides vermischt geht nicht!

Diese Dateien kann man sehr einfach mit dem PEAR Package Payment_DTA erzeugen.

Wir fassen nun das Beispiel mit den einzugebenden und zu bezahlenden Rechnungen aus.
Wir geben bei jeder Rechnung die Zahlmodalitäten ein, in dem Fall das Fälligkeitsdatum.
Wurde eine Rechnung bar bezahlt oder bereits überwiesen wird in der Datenbank das
Feld "is_paid" auf 1 gesetzt.

Die Datenbankstruktur sieht wie folgt aus

CODE:
-- 
-- Tabellenstruktur für Tabelle 'bank'
-- 

CREATE TABLE bank (
  bank_id int(11) NOT NULL default '0',
  bank_name text NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

-- --------------------------------------------------------

-- 
-- Tabellenstruktur für Tabelle 'bills'
-- 

CREATE TABLE bills (
  number text NOT NULL,
  creditor int(11) NOT NULL default '0',
  amount float NOT NULL default '0',
  is_paid int(1) NOT NULL default '0',
  payment_date int(11) NOT NULL default '0',
  transaction_info text NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

-- --------------------------------------------------------

-- 
-- Tabellenstruktur für Tabelle 'creditor'
-- 

CREATE TABLE creditor (
  creditorID int(11) NOT NULL auto_increment,
  company text NOT NULL,
  bank_account int(11) NOT NULL default '0',
  bank_id int(11) NOT NULL default '0',
  PRIMARY KEY  (creditorID)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;


Diese Datenstruktur ist nur ein Beispiel und hab ich nur kurz für den
Eintrag hier geschrieben.

Hier nun eine Beispielanwendung, die mit obiger Datenbankstruktur
arbeitet.

CODE:
<?php
/**
*
* DTA Example in a small Application
*
*/
include("Payment/DTA.php");

$conn=mysql_connect('localhost','root');
$res=mysql_select_db('financedev',$conn);

$mode="download"; // valid: download,display,server

if($mode=='download')
{
header('Content-type: text/plain;');
header('Content-Disposition: attachment; filename="DTAUS0"');
}

$res=mysql_query("SELECT *
   FROM bills
   INNER JOIN creditor
   ON bills.creditor=creditor.creditorID
   INNER JOIN bank on creditor.bank_id=bank.bank_id
   WHERE is_paid=0",$conn);
if(count($res)>0)
{

/**
* Erstellt eine neue DTA Datei, für die Überweisung von Beträgen
* Für Lastschrift der Klasse DTA_DEBIT üebergeben.
*/
$dta_file = new DTA(DTA_CREDIT);

/**
* Absender von den Überweisungen, hier müssen die eigenen Daten angegeben werden,
*/
$dta_file->setAccountFileSender(array(
    "name"           => "Max Mustermann",
    "bank_code"      => 60069860,
    "account_number" => 12345
));

while($row=mysql_fetch_array($res))
{
/**
* Transaktionen hinzufügen
*/
$dta_file->addExchange(
     array(
          "name"           => $row['company'],    // Kontoinhaber
        "bank_code"      => $row['bank_id'],           // BLZ
          "account_number" => $row['bank_account'], // Kontonummer
     ),
     $row['amount'],                                      // Betrag
    array(                                      // Verwendungszweck
          (!empty($row['transaction_info']) ? $row['transaction_info'] : $row['number'] ),
         "---"
     )
);
}

/**
* Speichert Datei
*/
if($mode=='server')
{
$dta_file->saveFile("DTAUS0");
} else {
/**
* Gibt Inhalt aus
*/
echo $dta_file->getFileContent();
}

} else {
return;
}
?>


Achtung Nimmt man DTA_DEBIT, also das Lastschriftverfahren ist der Sender der der
das Geld erhält. Bei DTA_CREDIT ist es der von dessen Konto Geld überwiesen wird.
Dies muss beachtet werden, und erscheint etwas unlogisch. Allerdings ist der Sender
so immer in der Regel der fixe Wert, da alles auf mein Konto überwiesen wird, oder
ich Lastschriften auf mein Konto einziehe.

Geschrieben von Peter Rehm

15.01.2007 um 22:55:05

Abgelegt in PHP

Tags für diesen Artikel: ,

Arrays in Smarty

Ohne Kommentare

In Smarty Templates kann man, welch wunder, auch auf Arrays zugreifen.

CODE:
{$array.element1}


Dies stellt die einfachste Art dar, wie man dies erledigen kann. Mit der ist man wohl
auch desöfteren konfrontiert, und stellt daher bestimmt kein Problem dar.

Allerdings kann Smarty auch mit [] umgehen, und ermöglicht daher auch den dynamischen
Zugriff auf mehrdimensionale Arrays.

CODE:
{foreach item=car from=$data}
          <th>{$calc[$car.sxID].20000.total_saving}</th>
{/foreach}


Dies ist für manche Anwendungsfälle ganz praktisch.

Geschrieben von Peter Rehm

31.12.2006 um 00:27:41

Abgelegt in PHP

Tags für diesen Artikel: , ,

[PHP] String als Zipfile

Mit 2 Kommentaren

Wie oft habe ich bereits einen String in ein komprimiertes File schreiben wollen, das vollautomatisiert und zum Download für den User. Allerdings eignet sich dazu das gzip format nicht da die meisten Benutzer mit Windows arbeiten und man ein zusätzliches Tool installieren.

Daher benötigt man das PEAR Module Archive_Zip das hervorragend Zip Dateien erstellen kann. Allerdings benötige ich das Zip File nicht direkt, da ich das File nach dem Download nicht mehr benötige da es veraltet sein könnte. Daher habe ich mir eine Funktion gebaut, die auf Archive_Zip aufbaut, mit der ich das Problem erledigen kann.

Die Funktion stringtozip erstellt temporär das Archiv mit den gewünschten Dateinamen, und löscht danach alles wieder, um nur den String zurückzuliefern.

Aber sehet selbst!

CODE:
/**
* function to create an zip file from an string
* @param string $string content of the file
* @param string $filename name of the file includes the content
* @param string $zipdescription description in the zipfile
* @param string $tmpfolder path for the temporary files with an ending /
*/
function stringToZip($string,$filename,$zipdescription,$tmpfolder)
{
global $cfg;
$rand=rand();

if(!class_exists('Archive_Zip'))
{
// module archive_zip is not existing
return false;
}

if(!is_writable($tmpfolder))
{
// directory is not writeable
return false;
}

if(!file_exists($tmpfolder.$filename))
{
$int_filename=$tmpfolder.$filename;
} else {
$int_filename=$tmpfolder.$filename.'-'.$rand;
}

$fhandler=fopen($int_filename,'a');
fwrite($fhandler,$string);
fclose($fhandler);

$zipHandler=new Archive_Zip($tmpfolder.date("YmdHis").'-'.$zipdescription.'-'.$rand.'.zip');
$zipHandler->create($int_filename,array('remove_all_path'=>true));

// unlink the file containing the string
unlink($int_filename);

// store the data and delete the temp file
$data=file($tmpfolder.date("YmdHis").'-'.$zipdescription.'-'.$rand.'.zip');
unlink($tmpfolder.date("YmdHis").'-'.$zipdescription.'-'.$rand.'.zip');

return join("\n",$data);
}


Viel Spaß!

Geschrieben von Peter Rehm

15.09.2006 um 16:17:50

Abgelegt in PHP, Programmierung

Tags für diesen Artikel: ,

ADODB Table Prefix

Ohne Kommentare

Bei fast jedem Projekt arbeitet man mit Tabellen Prefixen, um das Projekt z.b. 2x in der gleichen Datenbank laufen zu lassen. Gestern habe ich angefangen mein Projekt auf ADOBD und dabei festgestellt dass es noch keine eingebaute Funktion für das Verwalten eines Prefixes gibt. Daher hab ich das nun auf meine Anforderungen angepasst.

Mein Prefix liegt in $cfg['tbl_prefix'].

Die Querys werden nun so aufgebaut ("SELECT * FROM ##daten").

Statt Execute nimmt man nun die neue Funktion pExecute.

Diese Funktion muss in die adodb.inc.php implementiert werden, ich hab diese in der aktuellen ADODB Version in Zeile 784 direkt vor Execute plaziert.

CODE:
/**
*    Function to Replace the Prefixes
*    After replacing it the SQL Statement will be passed to EXECUTE()
*    @param sql SQL statement to execute, ## will be replaced with the Prefix
*/
function &pExecute($sql)
{
global $cfg;
return $this->Execute(str_replace('##',$cfg['tbl_prefix'],$sql));
}

Geschrieben von Peter Rehm

28.06.2006 um 10:39:27

Abgelegt in PHP, Programmierung

Tags für diesen Artikel: ,

Multi List Drag & Drop - Sajax!

Mit 2 Kommentaren

Als ich über die Seite von Tom Westcott gestolpert bin war mir klar, ich muss das in mein neues CMS einbinden. Ich hatte mir damals schon vorgestellt dass das für die Inhaltsstruktur oder für die Sidebar interessant sein könnte, aber ich war damals noch in der Planungsphase.

Als ich dann die Implementation in Serendipity die ich durch Garvin's SuperBlog entdeckt habe getestet habe, war mir klar, genau das will ich auch. Allerdings hat mir nur die AJAX Implementierung zugesagt, da ich ganz genau weiss da manche kunden bei so futuristischen Anwendungen sicher vergessen das abzuschicken. Daher muss das automatisch gemacht werden. Tom hat glücklicherweise auch gleich beide Methoden bereitgestellt.

Allerdings war der Code sehr verworren, und daher habe ich angefangen den Code neu aufzubauen, da ich vor allem im CMS das dann schon sauber einbauen wollte. Anstelle der umfangreicheren Implementation reicht nun folgendes:

CODE:
/**
* db settings
*/
$cfg['server']['host'] = "localhost"; // server
$cfg['server']['user'] = "root"; // dbuser
$cfg['server']['pass'] = ""; // password
$cfg['server']['db'] = "sajaxdemo"; // dbname

/**
*    start the connection
*/
$conn = mysql_connect ($cfg['server']['host'],
$cfg['server']['user'],
$cfg['server']['pass']);
$result = mysql_select_db ($cfg['server']['db'],$conn);

/**
*    include the sajax file
*/
include("sajax.php");


Danach muss noch der Pfad in der sajax Datei angepasst werden, dass das einbinden der styles und des JS auch funktioniert.

CODE:
var $sajax_path='thirdparty/sajax/';


Die Funktion update_db sollte dann auch an die Gegebenheiten angepasst werden. Die Funktion greift auf die global Datenbankverbindung zu.

Das Auslesen wird dann direkt in dem File gemacht in dem Sie die Liste anzeigen möchten.

Um dies zu vereinfachen habe ich eine Bespiel Datei mitgeliefert, in der Sie das alles sehen können. Dazu auch der passende SQL dump.

Beispielseite - Download
    Ich hoffe dieses Script findet irgendwo sinvollen Einsatz. Über Feedback würde ich mich freuen.

Geschrieben von Peter Rehm

20.06.2006 um 00:33:22

Abgelegt in PHP, Programmierung

Tags für diesen Artikel: , ,

PHPThumb Fehler

Mit 1 Kommentar

phpthumb error

Zum Bilder verkleinern und skalieren wird sehr oft phpThumb verwedet was an sich auch toll ist, jedoch hat man oft das Problem, dass man eine Applikation lokal entwickelt und beim Hochladen gibt es dann einen Fehler.

Bei phpThumb kommt es relativ oft zu dem Fehler

Unknown image type identified by ?ph ( 0x3c 0x3f 0x70 0x68 ) in SourceImageToGD

Die ist sehr ärgerlich aber es gibt einen einfach Workaround

Man muss einfach folgende Zeilen in phpThumb/phpThumb.php entfernen:

CODE:
if (@$_SERVER['PATH_INFO']) {
$_SERVER['PHP_SELF'] = str_replace($_SERVER['PATH_INFO'], '', @$_SERVER['PHP_SELF']);</em></em>

<em><em>$args = explode(';', substr($_SERVER['PATH_INFO'], 1));
if (!empty($args)) {
$_GET['src'] = @$args[count($args) - 1];</em></em>

<em><em>}
if (eregi('^([0-9]*)x?([0-9]*)$', @$args[count($args) - 2], $matches)) {
$_GET['w'] = $matches[1];
$_GET['h'] = $matches[2];
}
for ($i = 0; $i < count($args) - 2; $i++) {
@list($key, $value) = explode('=', @$args[$i]);
if (substr($key, -2) == '[]') {
$_GET[substr($key, 0, -2)][] = $value;
} else {
$_GET[$key] = $value;
}
}
}


Danach sollte es gehen, mir ist vor allem das Problem bei meinem 1&1 Server aufgefallen, da es lokal meistens funktionierte.

Geschrieben von Peter Rehm

27.04.2006 um 14:39:57

Abgelegt in PHP, Programmierung

Tags für diesen Artikel: ,

WinBinder - PHP Applicationen für Windows

Ohne Kommentare

Sieht sehr interessant aus ist aber für Windows. Werde ich wohl mal kurz testen müssen wenn ich wieder in Deutschland bin, da ich hier keinen eigenen Windows rechner habe.

Aber interessant wird es erst wenn es auch einen MacBinder gibt.


Vom Prinzip her ist es aber sicher interessant.

http://www.winbinder.com/overview.php

Geschrieben von Peter Rehm

08.03.2006 um 11:17:35

Abgelegt in PHP, Programmierung