Der ultimative Guide für Objektorientierung, Entwurfsmuster und Modellierung sowie fortgeschrittene Datenbankprogrammierung von Sebastian Bergmann
Autor: webpirat
Hier der Scrum Guide von Ken Schwaber für alle die hinter die Kulissen der agilen Produktentwicklung sehen wollen.
Folgender Kommandozeilen Befehl löscht alle .svn Verzeichnisse in einem Ordner.
Im Detail sucht das Kommando find
im aktuellen Ordner (.) rekursiv
nach Verzeichnissen (-type d)
mit dem Namen .svn (-name .svn)
und piped (|) diese Liste
nach xargs,
welches dann an erster Stelle (-0) der Liste
mit der Löschoperation (rm -rf) beginnt.
find . -type d -name .svn -print0 | xargs -0 rm -rf
Um im schlanken Webserver Lighty eine HTTP Authentifizierung für bestimmte Verzeichnisse zu erzeugen, ist es notwendig, in der /etc/lighttpd/lighttpd.conf das Server-Modul mod_access und mod_auth zu aktivieren.
server.modules = ( "mod_access", "mod_auth", "mod_alias", "mod_accesslog", "mod_compress", "mod_cgi", "mod_fastcgi", "mod_rewrite", "mod_magnet", "mod_redirect", "mod_status", )
Um ein Verzeichnis unterhalb eines bestehenden Webroots nun mit einer Authentifizierung zu schützen, tragen wir das in der /etc/lighttpd/vhosts.conf ein.
$HTTP["host"] =~ "(^|\.)domain\.tld$" { server.document-root = "/home/user/pages/" auth.backend = "htpasswd" auth.backend.htpasswd.userfile = "/home/user/passwd.txt" auth.require = ("/" => ( "method" => "basic", "realm" => "admin", "require" => "valid-user" ) ) }
Zu guter Letzt benötigen wir noch die /home/user/passwd.txt die die betreffenden Authentifizierungsinfos bereit hält.
user:basic_encoded_password
Fortan ist der Ordner /home/user/pages/ passwortgeschützt.
Möchte man einen Unterordner passwortschützen, trägt man diesen statt des Slashes ein:
auth.require = ("/subdir/" => ( "method" => "basic", "realm" => "admin", "require" => "valid-user" ) )
Deployment mit ANT
ANT ist ein wunderbares Kommandozeilen-Tool mit dem man Deployment gerade auch von Webapplikationen automatisieren kann.
Ich benutze es um Entwicklungsstände in die Stage oder Liveumgebung auszuspielen.
Zur Konfiguration des Deploymentprozesses erzeugt man eine build.xml Datei, die alle nötigen Anweisungen enthält.
Folgende XML Datei erzeugt einen Backup-Ordner und kopiert die aktuelle Live-Applikation dort hinein.
Desweiteren erzeugt das Skript einen Datenbank Dump und kopiert diesen ebenfalls dorthin.
Danach wird der aktuelle Entwicklungsstand in den Live-Ordner kopiert.
Zu guter Letzt werden noch die Log- und Cache-Ordner geleert.
<project name="builder" default="build" basedir="."> <description> devel to live update including dbdump and clear cache </description> <!-- set global properties for this build --> <property name="devel" location="devel"/> <property name="live" location="live"/> <property name="backup" location="backup"/> <property name="db_host" value="localhost"/> <property name="db" value="databasename"/> <property name="db_user" value="databaseuser"/> <property name="db_pass" value="databasepassword"/> <target name="build"> <!-- create the timestamp --> <tstamp/> <!-- create the backup dir --> <mkdir dir="${backup}_${DSTAMP}"/> <!-- dumb db to backup dir --> <echo message="create mysqldump"/> <exec executable="mysqldump" output="${backup}_${DSTAMP}/dump_${db}.sql"> <arg value="${db}"/> <arg value="-u${db_user}"/> <arg value="-p${db_pass}"/> </exec> <!-- copy current live dir to backup dir --> <copy todir="${backup}_${DSTAMP}"> <fileset dir="${live}"/> </copy> <!-- copy current devel dir to live dir --> <copy todir="${live}"> <fileset dir="${devel}" excludes="**/*index.php"/><!-- beware overiding main config index.php --> </copy> <!-- delete cache/log files --> <echo message="cleanup cache/logs in backup/live"/> <delete includeemptydirs="true"> <fileset dir="${backup}_${DSTAMP}/application/cache" includes="**/*"/> <fileset dir="${backup}_${DSTAMP}/application/logs" includes="**/*"/> <fileset dir="${live}/application/cache" includes="**/*"/> <fileset dir="${live}/application/logs" includes="**/*"/> </delete> </target> </project>
Dieses Skript wird auf der Kommandozeile von Linux ausgeführt.
ANT sucht per default nach einer build.xml im ausführenden Ordner.
user@server:~/pages$ ant Buildfile: build.xml build: [mkdir] Created dir: /home/user/pages/backup_20091027 [echo] create mysqldump [copy] Copying 1153 files to /home/user/pages/backup_20091027 [copy] Copied 261 empty directories to 5 empty directories under /home/user/pages/backup_20091027 [copy] Copying 50 files to /home/user/pages/live [echo] cleanup cache/logs in backup/live BUILD SUCCESSFUL Total time: 27 seconds
Um modular und agil in Kohana zu entwickeln, wurde ein Skript Kollektor notwendig, der aus allen Controllern (Template- oder Standard-Controllern) Skripte (CSS, Javascript) sammeln kann.
Diese Scripte werden dann auf den jeweiligen Mastertemplates wieder an den richtigen Stellen eingebunden.
Dazu habe ich einen neuen Helper unter application/helpers/collector.php eingerichtet.
class Collector_Core { /** * Arrays containing URL's to scripts/styles (fill with standards) * @var string */ static protected $scripts = array(); static protected $styles = array(); /** * Adds a url to store * @param string $file the local path to file * @return void */ static public function addJs($file) { self::$scripts[] = $file; } /** * Adds a url to store * @param string $file the local path to file * @return void */ static public function addCss($file) { self::$styles[] = $file; } /** * Generates/renders collectors items * @param boolean $print whether to echo the output or just return rendered string * @return string the rendered output */ static public function renderJs($print = false) { $scripts = array_unique(self::$scripts); $output = html::script($scripts); if ($print) { echo $output; } else { return $output; } } /** * Generates/renders collectors items * @param boolean $print whether to echo the output or just return rendered string * @param string|array $media type for this style (all, screen, print, media) * @return string the rendered output */ static public function renderCss($print = false, $media = 'all') { $styles = array_unique(self::$styles); $output = html::stylesheet($styles, $media); if ($print) { echo $output; } else { return $output; } } } // end of Collector_Core
Dieser Helper kann nun aus allen Controllern heraus befüllt werden.
class Welcome_Controller extends Template_Controller { /** * set master template */ public $template = 'master_default.tpl'; /** * default constructor * @param void * @return void */ public function __construct() { // load parent constructor parent::__construct(); // collect scripts and styles collector::addCss('/css/fancybox'); collector::addJs('/js/jquery.1.3.2'); collector::addJs('/js/jquery.fancybox'); } /** more code here */ } // end of Welcome_Controller
Nachdem nun alle relevanten Skripte eingesammelt wurden, kann man diese auf dem Template wieder ausgeben lassen.
<?php collector::renderCss(true, 'all'); ?> <!-- html code here --> <?php collector::renderJs(true); ?>
Der Kollektor sorgt dafür das keine doppelten Skripte geladen werden.
die inoffizielle Agavi FAQ
Allen die immernoch sehnsüchtig auf eine offizielle Agavi Doku warten, sei hier die inoffizielle FAQ Variante von mivesto ans Herz gelegt.
Agavi auf XAMPP und Windows
Nachdem ich das offizielle Agavi DOC durchforstet habe und keine Lösung für meine Testumgebung fand, stieß ich auf diesen Link hier:
simonholywell.com/article/installing-agavi-on-xampp-windows
Herr Holywell selbst hat eine prima Einführung in die Installation von Agavi auf XAMPP und Windows geliefert.
Hier der Post im Original:
Having recently heard of the Agavi project from a web framework showdown at a PHP conference in the UK I have decided to trial it. My setup is a WinXP computer with a default install of the latest XAMPP which has thrown up some issues with installing and building Agavi. Please see my hints below to overcome these issues.
1. Open a command prompt (type cmd in the run console)
2. Navigate to your XAMMP PHP directory. Mine is C:\xampp-test\php
3. Execute pear.bat channel-discover pear.agavi.org
4. Execute pear.bat install agavi/agavi
Agavi is now installed! Now we just need a new default project to work from.
Agavi needs to be told where the phing batch file is stored.
1. Edit the agavi.bat file in the XAMPP php directory. Mine is C:\xampp-test\php\agavi.bat
2. Change set PHING_COMMAND=phing to contain the full absolute path to phing.bat which is in the XAMPP php folder. Mine looks like this: set PHING_COMMAND=C:\xampp-test\php\phing.bat
Begin setting up your project directory.
1. Create a new directory in your XAMPP directory. Mine is C:xampp-testhtdocssimonholywell.com
2. Create an empty text file called build.properties in the directory (this banishes a build error where phing fails if it cannot find the file)
3. Open a command prompt and navigate to the new directory
4. Execute agavi.bat project The agavi.bat file is stored in the XAMPP php folder. My command looked like this: C:\xampp-test\php\agavi.bat project
5. Follow the prompts the installer gives you (hitting enter will supply the installer with the [default] value)
Agavi should now be setup for your project. View it in your browser to verify.
die SVN Quickreferenz als PDF
…für alle die mal eben schnell SVN Kommandos nachsehen wollen.
© by Tobias Zeising (tobias.zeising@aditu.de | http://www.aditu.de)
Eine einfache all-in-one Lösung für Standard SOAP Services kann man mit dem Kohana Framework und der Zend Bibliothek realisieren.
Dazu bedarf es lediglich eines Kohana Frontcontrollers über den wir den Service und die WSDL ansprechen können.
Zur automatischen Generierung der WSDL, bedienen wir uns hier der Zend AutoDiscover Klasse. Dieser Klasse übergibt man lediglich die ServiceModel-Klasse mit enthaltenen Annotationen, die die Servicefunktionen enthält.
Aus den Annotationen generiert Zend AutoDiscover eine passende WSDL.
/** * include libs and models * */ include('Zend/Soap/AutoDiscover.php'); include(APPPATH . 'models/service.php'); /** * this class represents a controller * application/controllers/soap.php * * @package SOAPService * @subpackage ... * @author saegefisch (xxx@xxx.xx) * @copyright (c) 2009 xxx */ class Soap_Controller extends Controller { /** * default constructor * * @param void * @return void */ public function __construct() { // load parent constructor parent::__construct(); } /** * service to call * * @param void * @return void */ public function service() { // disable wsdl cache ini_set('soap.wsdl_cache_enabled', '0'); // set auth settings if needed $settings = array( 'login' => 'user', 'password' => 'password', 'authentication' => SOAP_AUTHENTICATION_BASIC, 'soap_version' => SOAP_1_2, 'encoding' => 'UTF-8', 'cache_wsdl' => WSDL_CACHE_NONE ); // include user:password if needed $wsdl = 'http://user:password@' . $_SERVER['HTTP_HOST'] . '/soap/wsdl'; $server = new SoapServer($wsdl, $settings); $server->setClass('Service_Model'); $server->handle(); } /** * wsdl to call * * @param void * @return void */ public function wsdl() { // disable wsdl cache ini_set('soap.wsdl_cache_enabled', '0'); $wsdl = new Zend_Soap_AutoDiscover(); $wsdl->setUri('http://' . $_SERVER['HTTP_HOST'] . '/soap/service'); $wsdl->setClass('Service_Model'); $wsdl->handle(); } }
Hier stellen wir das Standard Model für unseren SOAP Service zusammen.
/** * this class represents a model * application/models/service.php * * @package SOAPService * @subpackage ... * @author saegefisch (xxx@xxx.xx) * @copyright (c) 2009 */ class Service_Model extends Model { /** * default constructor * * @param void * @return void */ public function __construct() { // load database library into $this->db (can be omitted if not required) parent::__construct(); } /** * dummy function * * @param int $int * @param string $string * @param array $arr * @param object $obj * @param bool $bool * @return array */ public function get_dummy_array($int, $string, $arr, $obj, $bool) { return array(); } /** * dummy function * * @param int $int * @param string $string * @param array $arr * @param object $obj * @param bool $bool * @return bool */ public function get_dummy_boolean($int, $string, $arr, $obj, $bool) { return true; } /** * dummy function * * @param int $int * @param string $string * @param array $arr * @param object $obj * @param bool $bool * @return string */ public function get_dummy_string($int, $string, $arr, $obj, $bool) { return 'foo=bar'; } }