Skip to content
Browse files

First commit

  • Loading branch information...
0 parents commit af2180b47c5a20b9701d4c937f68fcc9d7b226c1 @wjgilmore committed Feb 18, 2011
6 .gitignore
@@ -0,0 +1,6 @@
+application/configs/application.ini
+.project
+.settings
+.buildpath
+library/Doctrine
+library/Symfony
69 .zfproject.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0"?>
+<projectProfile type="default" version="1.10">
+ <projectDirectory>
+ <projectProfileFile filesystemName=".zfproject.xml"/>
+ <applicationDirectory classNamePrefix="Application_">
+ <apisDirectory enabled="false"/>
+ <configsDirectory>
+ <applicationConfigFile type="ini"/>
+ </configsDirectory>
+ <controllersDirectory>
+ <controllerFile controllerName="Index">
+ <actionMethod actionName="index"/>
+ </controllerFile>
+ <controllerFile controllerName="Error"/>
+ </controllersDirectory>
+ <formsDirectory enabled="false"/>
+ <layoutsDirectory enabled="false"/>
+ <modelsDirectory>
+ <modelFile modelName="FormContact"/>
+ </modelsDirectory>
+ <modulesDirectory enabled="false"/>
+ <viewsDirectory>
+ <viewScriptsDirectory>
+ <viewControllerScriptsDirectory forControllerName="Index">
+ <viewScriptFile forActionName="index"/>
+ </viewControllerScriptsDirectory>
+ <viewControllerScriptsDirectory forControllerName="Error">
+ <viewScriptFile forActionName="error"/>
+ </viewControllerScriptsDirectory>
+ </viewScriptsDirectory>
+ <viewHelpersDirectory/>
+ <viewFiltersDirectory enabled="false"/>
+ </viewsDirectory>
+ <bootstrapFile filesystemName="Bootstrap.php"/>
+ </applicationDirectory>
+ <dataDirectory enabled="false">
+ <cacheDirectory enabled="false"/>
+ <searchIndexesDirectory enabled="false"/>
+ <localesDirectory enabled="false"/>
+ <logsDirectory enabled="false"/>
+ <sessionsDirectory enabled="false"/>
+ <uploadsDirectory enabled="false"/>
+ </dataDirectory>
+ <docsDirectory>
+ <file filesystemName="README.txt"/>
+ </docsDirectory>
+ <libraryDirectory>
+ <zfStandardLibraryDirectory enabled="false"/>
+ </libraryDirectory>
+ <publicDirectory>
+ <publicStylesheetsDirectory enabled="false"/>
+ <publicScriptsDirectory enabled="false"/>
+ <publicImagesDirectory enabled="false"/>
+ <publicIndexFile filesystemName="index.php"/>
+ <htaccessFile filesystemName=".htaccess"/>
+ </publicDirectory>
+ <projectProvidersDirectory enabled="false"/>
+ <temporaryDirectory enabled="false"/>
+ <testsDirectory>
+ <testPHPUnitConfigFile filesystemName="phpunit.xml"/>
+ <testApplicationDirectory>
+ <testApplicationBootstrapFile filesystemName="bootstrap.php"/>
+ </testApplicationDirectory>
+ <testLibraryDirectory>
+ <testLibraryBootstrapFile filesystemName="bootstrap.php"/>
+ </testLibraryDirectory>
+ </testsDirectory>
+ </projectDirectory>
+</projectProfile>
91 README.markdown
@@ -0,0 +1,91 @@
+README
+===========
+z2d2 is a companion project to Chapter 7 ("Integrating Doctrine 2") of the forthcoming book, [Easy PHP Websites with the Zend Framework, Second Edition](http://www.wjgilmore.com), authored by W. Jason Gilmore and published by [WJ Gilmore, LLC](http://www.wjgilmore.com). This project provides readers with a Zend Framework-driven website configured to use Doctrine 2.
+
+Chapter 7 introduces key Doctrine 2 features based on code found throughout this project. You'll learn:
+
+* About the files and configuration parameters used to integrate Doctrine 2 into a Zend Framework 1.X-based website.
+
+* How to create persistent classes (entities) using DocBlock annotations.
+
+* How to generate and update table schemas based on the entity's Docblock annotations using the integrated Doctrine command-line interface.
+
+* How to retrieve and manipulate data using Doctrine's native query methods, magic finders, and the Doctrine Query Language (DQL).
+
+* How to create and manipulate model relationships, complete with a ManyToMany example involving providing users to create video game libraries.
+
+* Why implementing repositories is a good idea, and how you can use repositories to build your own custom "magic finders".
+
+INSTALLATION
+===========
+z2d2 is a skeleton Zend Framework project which includes complete Doctrine 2 integration. It does not however bundle the Zend Framework nor Doctrine 2, meaning you will need to download and install both in order to learn from z2d2.
+
+Installing the Zend Framework can be accomplished in several ways, although I suggest following the instructions located in the [Zend Framework QuickStart](http://framework.zend.com/manual/en/learning.quickstart.create-project.html).
+
+You'll need to pay a bit more attention regarding installing Doctrine. z2d2 is only interested in *the libraries* associated with the four projects (Common, DBAL, ORM, Symfony) bundled into the Doctrine 2 download. There are a few ways to do this but if you're not familiar with Doctrine them one of the easiest ways follows:
+
+1. Clone Doctrine 2
+
+ $ git clone git://github.com/doctrine/doctrine2.git doctrine2-orm
+
+2. Copy the following three directories into a directory named Doctrine found in the z2d2 `library` directory:
+
+ lib/Doctrine/ORM
+ lib/vendor/doctrine-common/lib/Doctrine/Common
+ lib/vendor/doctrine-dbal/lib/Doctrine/DBAL
+
+3. Copy the following directory into the z2d2 `library` directory:
+
+ lib/vendor/Symfony
+
+When done, your `library` directory should look like this:
+
+ library/
+ Doctrine/
+ Common/
+ DBAL/
+ ORM/
+ Symfony/
+ WJG/
+
+You'll also need to modify the Doctrine database connection parameters and entity/proxy/repository paths. These parameters are all found in the `application.ini.example` file. Rename this file to `application.ini` before making your changes.
+
+Finally, you'll need to use the included Doctrine CLI to generate the schemas, done from within the `application` directory using the following command:
+
+ $ ./scripts/doctrine orm:schema-tool:create
+
+Keep in mind that CRUD operations are not incorporated into the application. Instead, you should review the examples found on the application home page, creating your own controllers and actions and executing the various examples.
+
+SAMPLE CHAPTER
+===========
+A PDF version of Chapter 7, "Integrating Doctrine 2", is available for download from [WJGilmore.com](http://www.wjgilmore.com/). Keep in mind this is a late draft version, and probably contains mistakes. If you find mistakes, e-mail me with the details at `wj@wjgilmore.com`.
+
+BUY THE BOOK
+===========
+"Easy PHP Websites with the Zend Framework, Second Edition" is slated to be released in e-book format in late February, 2011. This book includes several sample projects, including all source code for GameNomad, a sample social networking website for video gamers which forms the basis for many of the book's examples.
+
+To celebrate the book's pending release, interested readers can preorder the book for $20. This special price will be good until the day the book publishes, at which time the price will increase to $30. Once published, all readers will be
+notified via e-mail of the book's availability and will be able to download the book in PDF and ePub format, along with all of the sample code.
+
+Preorder the book now at [http://www.wjgilmore.com/](http://www.wjgilmore.com/).
+
+Once an initial round of bugs have been reported and fixed, a print version will be released in late spring of 2011.
+
+ABOUT THE AUTHOR
+===========
+W. Jason Gilmore has been teaching developers from around the world about web development for over a decade, having written six books, including the bestselling "Beginning PHP and MySQL, Fourth Edition" and "Easy PHP Websites
+with the Zend Framework". He has published more than 150 articles within popular publications such as Developer.com, DevShed, JSMag, and Linux Magazine, and instructed hundreds of students in the United States and Europe.
+
+Jason is cofounder of the popular [CodeMash Conference](http://www.codemash.org), and was a member of the 2008 MySQL Conference speaker selection board.
+
+LICENSE, COPYRIGHTS, AND OTHER LEGALESE
+===========
+Copyright (c) 2011 W.J. Gilmore, LLC
+
+z2d2 is a companion project to the book "Easy PHP Websites with the Zend Framework" (http://www.wjgilmore.com). While I place no restrictions on its use, keep in mind that although it does not bundle the [Zend Framework](http://framework.zend.com) nor [Doctrine](http://www.doctrine-project.org), you'll logically want to install both in order to learn from z2d2. Therefore you should carefully review their respective software licenses should you decide to do anything with z2d2 other than use it for learning more about how I have gone about integrating Doctrine 2 into a Zend Framework project.
+
+You can learn more about the Zend Framework license here:
+[http://framework.zend.com/license](http://framework.zend.com/license)
+
+You can learn more about Doctrine's license at [http://www.doctrine-project.org](http://www.doctrine-project.org).
+
44 application/Bootstrap.php
@@ -0,0 +1,44 @@
+<?php
+
+class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
+{
+
+ /**
+ *
+ *
+ *
+ *
+ */
+ protected function _initConfig()
+ {
+
+ $config = new Zend_Config($this->getOptions());
+ Zend_Registry::set('config', $config);
+
+ }
+
+ /**
+ *
+ *
+ *
+ *
+ */
+ protected function _initDoctrine() {
+
+ require_once('Doctrine/Common/ClassLoader.php');
+
+ $autoloader = Zend_Loader_Autoloader::getInstance();
+ $classLoader = new \Doctrine\Common\ClassLoader('Entities',
+ realpath(Zend_Registry::get('config')->resources->entityManager->connection->entities), 'loadClass');
+
+ $autoloader->pushAutoloader(array($classLoader, 'loadClass'), 'Entities');
+
+ $classLoader = new \Doctrine\Common\ClassLoader('Repositories',
+ realpath(Zend_Registry::get('config')->resources->entityManager->connection->entities), 'loadClass');
+
+ $autoloader->pushAutoloader(array($classLoader, 'loadClass'), 'Repositories');
+
+ }
+
+}
+
55 application/configs/application.ini.example
@@ -0,0 +1,55 @@
+[production]
+phpSettings.display_startup_errors = 1
+phpSettings.display_errors = 1
+resources.frontController.params.displayExceptions = 1
+resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/"
+resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/"
+
+includePaths.library = APPLICATION_PATH "/../library"
+includePaths.library = APPLICATION_PATH "/../library/Doctrine"
+includePaths[] = APPLICATION_PATH "/../views"
+
+pluginPaths.WJG_Resource = "WJG/Resource"
+
+bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
+bootstrap.class = "Bootstrap"
+
+autoloaderNamespaces[] = "Doctrine"
+autoloaderNamespaces[] = "WJG"
+autoloaderNamespaces[] = "Symfony"
+
+appnamespace = "Application"
+
+resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
+
+resources.frontController.actionhelperpaths.WJG_Controller_Action_Helper = APPLICATION_PATH "/../library/WJG/Controller/Action/Helper"
+
+;---------------------------------------------------
+; DOCTRINE CONFIGURATION
+;---------------------------------------------------
+resources.entityManager.connection.driver = "pdo_mysql"
+resources.entityManager.connection.host = "localhost"
+resources.entityManager.connection.dbname = "dev_z2d2"
+resources.entityManager.connection.user = "YOUR_MYSQL_USER"
+resources.entityManager.connection.password = "YOUR_MYSQL_PASSWORD"
+resources.entityManager.connection.entities = "/ABSOLUTE/PATH/TO/z2d2/application/models"
+resources.entityManager.connection.proxies.location = "/ABSOLUTE/PATH/TO/z2d2/application/models/Proxies"
+resources.entityManager.connection.proxies.ns = "Proxies"
+
+; According to Doctrine manual, this should be true for
+; development, and false for production
+resources.entityManager.connection.proxies.generate = true
+
+[staging : production]
+
+[testing : production]
+phpSettings.display_startup_errors = 1
+phpSettings.display_errors = 1
+
+[development : production]
+phpSettings.display_startup_errors = 1
+phpSettings.display_errors = 1
+resources.frontController.params.displayExceptions = 1
+
+
+
56 application/controllers/ErrorController.php
@@ -0,0 +1,56 @@
+<?php
+
+class ErrorController extends Zend_Controller_Action
+{
+
+ public function errorAction()
+ {
+ $errors = $this->_getParam('error_handler');
+
+ if (!$errors) {
+ $this->view->message = 'You have reached the error page';
+ return;
+ }
+
+ switch ($errors->type) {
+ case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ROUTE:
+ case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
+ case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
+
+ // 404 error -- controller or action not found
+ $this->getResponse()->setHttpResponseCode(404);
+ $this->view->message = 'Page not found';
+ break;
+ default:
+ // application error
+ $this->getResponse()->setHttpResponseCode(500);
+ $this->view->message = 'Application error';
+ break;
+ }
+
+ // Log exception, if logger available
+ if ($log = $this->getLog()) {
+ $log->crit($this->view->message, $errors->exception);
+ }
+
+ // conditionally display exceptions
+ if ($this->getInvokeArg('displayExceptions') == true) {
+ $this->view->exception = $errors->exception;
+ }
+
+ $this->view->request = $errors->request;
+ }
+
+ public function getLog()
+ {
+ $bootstrap = $this->getInvokeArg('bootstrap');
+ if (!$bootstrap->hasResource('Log')) {
+ return false;
+ }
+ $log = $bootstrap->getResource('Log');
+ return $log;
+ }
+
+
+}
+
20 application/controllers/IndexController.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ *
+ * @author wjgilmore
+ *
+ */
+
+class IndexController extends Zend_Controller_Action
+{
+
+ public function indexAction()
+ {
+
+
+ }
+
+
+}
+
18 application/layouts/scripts/layout.phtml
@@ -0,0 +1,18 @@
+<html>
+<head>
+<title>z2d2 = Zend Framework 1.X + Doctrine 2 Integration</title>
+<style type="text/css">
+html {
+ font-family: Palatino, Arial;
+}
+</style>
+</head>
+<body>
+
+<?php echo $this->layout()->content; ?>
+
+
+</body>
+</head>
+</html>
+
135 application/models/Entities/Account.php
@@ -0,0 +1,135 @@
+<?php
+
+namespace Entities;
+use Doctrine\Common\Collections\ArrayCollection;
+
+/**
+ * @Entity (repositoryClass="Repositories\Account")
+ * @Table(name="accounts")
+ * @HasLifecycleCallbacks
+ */
+class Account
+{
+ /**
+ * @Id @Column(type="integer")
+ * @GeneratedValue(strategy="AUTO")
+ */
+ private $id;
+
+ /** @Column(type="string", length=255) */
+ private $username;
+
+ /** @Column(type="string", length=255) */
+ private $email;
+
+ /** @Column(type="string", length=32) */
+ private $password;
+
+ /** @Column(type="string", length=10) */
+ private $zip;
+
+ /** @Column(type="datetime") */
+ private $created;
+
+ /** @Column(type="datetime") */
+ private $updated;
+
+ /**
+ * @ManyToMany(targetEntity="Game", inversedBy="accounts")
+ * @JoinTable(name="accounts_games",
+ * joinColumns={@JoinColumn(name="account_id", referencedColumnName="id")},
+ * inverseJoinColumns={@JoinColumn(name="game_id", referencedColumnName="id")}
+ * )
+ */
+
+ private $games;
+
+ public function __construct()
+ {
+
+ $this->games = new ArrayCollection();
+
+ $this->created = $this->updated = new \DateTime("now");
+ }
+
+ public function addGame(Game $game)
+ {
+ $game->addAccount($this); // synchronously updating inverse side
+ $this->games[] = $game;
+ }
+
+
+ public function getGames()
+ {
+ return $this->games;
+ }
+
+ /**
+ * @PreUpdate
+ */
+ public function updated()
+ {
+ $this->updated = new \DateTime("now");
+ }
+
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ public function getUsername()
+ {
+ return $this->username;
+ }
+
+ public function setUsername($username)
+ {
+ $this->username = $username;
+ }
+
+ public function getEmail()
+ {
+ return $this->email;
+ }
+
+ public function setEmail($email)
+ {
+ $this->email = $email;
+ }
+
+ public function getPassword()
+ {
+ return $this->password;
+ }
+
+ public function setPassword($password)
+ {
+ $this->password = md5($password);
+ }
+
+ public function getZip()
+ {
+ return $this->zip;
+ }
+
+ public function setZip($zip)
+ {
+ $this->zip = $zip;
+ }
+
+ public function getCreated()
+ {
+ return $this->created;
+ }
+
+ public function setCreated($created)
+ {
+ $this->created = $created;
+ }
+
+ public function getUpdated()
+ {
+ return $this->updated;
+ }
+
+}
87 application/models/Entities/Game.php
@@ -0,0 +1,87 @@
+<?php
+
+namespace Entities;
+use Doctrine\Common\Collections\ArrayCollection;
+
+/**
+ * @Entity @Table(name="games")
+ * @HasLifecycleCallbacks
+ */
+class Game
+{
+ /**
+ * @Id @Column(type="integer")
+ * @GeneratedValue(strategy="AUTO")
+ */
+ private $id;
+
+ /** @Column(type="string", length=255) */
+ private $name;
+
+ /** @Column(type="string", length=255) */
+ private $publisher;
+
+ /** @Column(type="decimal",scale=2, precision=5) */
+ private $price;
+
+ /**
+ * @ManyToMany(targetEntity="Account", mappedBy="games")
+ */
+ private $accounts;
+
+ public function __construct()
+ {
+
+ $this->created = $this->updated = date('Y-m-d H:i:s');
+ $this->accounts = new ArrayCollection();
+
+ }
+
+ public function addAccount(Account $account)
+ {
+ $this->accounts[] = $account;
+ }
+
+
+ public function getAccounts()
+ {
+ return $this->accounts;
+ }
+
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ public function setName($name)
+ {
+ $this->name = $name;
+ }
+
+ public function getPublisher()
+ {
+ return $this->publisher;
+ }
+
+ public function setPublisher($publisher)
+ {
+ $this->publisher = $publisher;
+ }
+
+
+ public function getPrice()
+ {
+ return $this->price;
+ }
+
+ public function setPrice($price)
+ {
+ $this->price = $price;
+ }
+
+}
43 application/models/FormContact.php
@@ -0,0 +1,43 @@
+<?php
+
+class Application_Model_FormContact extends Zend_Form
+{
+
+ public function init($options = null)
+ {
+
+ $this->setName('contact');
+ $this->setMethod('post');
+ $this->setAction('/about/contact');
+
+ $name = new Zend_Form_Element_Text('name');
+ $name->setAttrib('size', 35);
+ $name->setLabel('Your Name:');
+ $name->setRequired(true);
+ $name->addErrorMessage('Please provide your name');
+
+ $email = new Zend_Form_Element_Text('email');
+ $email->setAttrib('size', 35);
+ $email->setLabel('Your E-mail Address:');
+ $email->setRequired(true);
+ $email->addErrorMessage('Please provide a valid e-mail address');
+ $email->addValidator('EmailAddress');
+
+ $message = new Zend_Form_Element_Textarea('message');
+ $message->setLabel('Your Message:');
+ $message->setRequired(true);
+ $message->setAttrib('rows', '10');
+ $message->setAttrib('cols', '55');
+ $message->addErrorMessage('Please specify a message');
+
+ $submit = new Zend_Form_Element_Submit('submit');
+ $submit->setLabel('Send Your Message!');
+
+ $this->addElements(array($name, $email, $message, $submit));
+
+ }
+
+
+
+}
+
31 application/models/Repositories/Account.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Repositories;
+
+use Doctrine\ORM\EntityRepository;
+
+/**
+ * Account
+ *
+ * This class was generated by the Doctrine ORM. Add your own custom
+ * repository methods below.
+ */
+class Account extends EntityRepository
+{
+
+ public function findNewestAccounts() {
+
+ $now = new \DateTime("now");
+ $oneDayAgo = $now->sub(new \DateInterval('P1D'))
+ ->format('Y-m-d h:i:s');
+ $qb = $this->_em->createQueryBuilder();
+ $qb->select('a.username')
+ ->from('Entities\Account', 'a')
+ ->where('a.created >= :date')
+ ->setParameter('date', $oneDayAgo);
+
+ return $qb->getQuery()->getResult();
+ }
+
+
+}
3 application/scripts/doctrine
@@ -0,0 +1,3 @@
+#!/usr/bin/env php
+<?php
+include('doctrine.php');
68 application/scripts/doctrine.php
@@ -0,0 +1,68 @@
+<?php
+
+ /**
+ * This file is responsible for making both the application Entity Manager
+ * (/library/WJG/Resource/Entitymanager.php) and the application configuration
+ * file (/application/configs/application.ini) available to the Doctrine
+ * CLI. It also adds several useful Doctrine CL commands to the menu. I've opted to
+ * omit several of them. See the Doctrine documentation for a complete list.
+ *
+ * This page really helps to understand what's going on in this script:
+ * http://www.doctrine-project.org/docs/orm/2.0/en/reference/tools.html
+ */
+
+ define('APPLICATION_PATH', __DIR__ . '/..');
+
+ set_include_path(
+ implode(PATH_SEPARATOR,
+ array(
+ realpath(APPLICATION_PATH . '/../library'),
+ get_include_path())
+ )
+ );
+
+ require 'Zend/Application.php';
+
+ // Run the application in development mode
+ $application = new Zend_Application('development', APPLICATION_PATH . '/configs/application.ini');
+
+ // Get your hands on the Entity Manager
+ // See /library/WJG/Resource/Entitymanager.php
+ $bootstrap = $application->getBootstrap()->bootstrap('entityManager');
+ $em = $bootstrap->getResource('entityManager');
+
+ // Start setting up the CL tool
+ $helperSet = new \Symfony\Component\Console\Helper\HelperSet(
+ array(
+ 'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()),
+ 'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em)
+ )
+ );
+
+ $cli = new \Symfony\Component\Console\Application('Doctrine Command Line Interface',
+ Doctrine\Common\Version::VERSION);
+
+ // Display exceptions
+ $cli->setCatchExceptions(true);
+ $cli->setHelperSet($helperSet);
+
+ // Add all of the desired CL commands
+ $cli->addCommands(
+ array(
+ new \Doctrine\ORM\Tools\Console\Command\ClearCache\MetadataCommand(),
+ new \Doctrine\ORM\Tools\Console\Command\ClearCache\ResultCommand(),
+ new \Doctrine\ORM\Tools\Console\Command\ClearCache\QueryCommand(),
+ new \Doctrine\ORM\Tools\Console\Command\ConvertMappingCommand(),
+ new \Doctrine\ORM\Tools\Console\Command\EnsureProductionSettingsCommand(),
+ new \Doctrine\ORM\Tools\Console\Command\GenerateRepositoriesCommand(),
+ new \Doctrine\ORM\Tools\Console\Command\GenerateEntitiesCommand(),
+ new \Doctrine\ORM\Tools\Console\Command\GenerateProxiesCommand(),
+ new \Doctrine\ORM\Tools\Console\Command\SchemaTool\CreateCommand(),
+ new \Doctrine\ORM\Tools\Console\Command\SchemaTool\UpdateCommand(),
+ new \Doctrine\ORM\Tools\Console\Command\SchemaTool\DropCommand(),
+ new \Doctrine\ORM\Tools\Console\Command\ValidateSchemaCommand()
+ )
+);
+
+// Run the CLI
+$cli->run();
28 application/views/scripts/error/error.phtml
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <title>Zend Framework Default Application</title>
+</head>
+<body>
+ <h1>An error occurred</h1>
+ <h2><?php echo $this->message ?></h2>
+
+ <?php if (isset($this->exception)): ?>
+
+ <h3>Exception information:</h3>
+ <p>
+ <b>Message:</b> <?php echo $this->exception->getMessage() ?>
+ </p>
+
+ <h3>Stack trace:</h3>
+ <pre><?php echo $this->exception->getTraceAsString() ?>
+ </pre>
+
+ <h3>Request Parameters:</h3>
+ <pre><?php echo var_export($this->request->getParams(), true) ?>
+ </pre>
+ <?php endif ?>
+
+</body>
+</html>
16 application/views/scripts/index/index.phtml
@@ -0,0 +1,16 @@
+<h1>z2d2 = Zend Framework 1.X + Doctrine 2 Integration</h1>
+
+<a href="<a href="http://www.wjgilmore.com/books/read/easy_php_websites_with_the_zend_framework"><img src="/images/epwzf2e.png" alt="Easy PHP Websites with the Zend Framework" style="border: 0px; float: left; padding-right: 5px;" /></a>
+
+<p>
+z2d2 is a companion project to the soon-to-be-released e-book, <a href="http://www.wjgilmore.com/books/read/easy_php_websites_with_the_zend_framework">Easy PHP Websites with the Zend Framework</a>, authored by <a href="http://www.wjgilmore.com/about">W. Jason Gilmore</a> and published by <a href="http://www.wjgilmore.com">WJ Gilmore, LLC</a>.
+</p>
+
+<p>
+z2d2's primary purpose is to provide readers with an operational Zend Framework-driven website complete with <a href="http://www.doctrine-project.org">Doctrine 2</a> integration. Two sample entity classes are included (complete with a ManyToMany relationship definition), however I am currently leaving it as an exercise to the reader to populate the tables and create the application logic for interacting with the classes. If you're new to Doctrine I recommend <a href="http://www.wjgilmore.com/books/read/easy_php_websites_with_the_zend_framework/code/">downloading Chapter 07, "Integrating Doctrine 2"</a>, which guides you through the creation of entities, shows you how to generate schemas, interact with the database using Doctrine's fantastic object-oriented syntax, and even create your own custom entity repositories.
+</p>
+
+<p>
+To celebrate the e-book's pending release, you can pre-order it from for <b>just $20</b> from <a href="http://www.wjgilmore.com">WJGilmore.com</a>. When the e-book publishes later this month the price will increase to $30 so preorder your copy now and save.
+</p>
+
30 docs/README.txt
@@ -0,0 +1,30 @@
+README
+======
+
+This directory should be used to place project specfic documentation including
+but not limited to project notes, generated API/phpdoc documentation, or
+manual files generated or hand written. Ideally, this directory would remain
+in your development environment only and should not be deployed with your
+application to it's final production location.
+
+
+Setting Up Your VHOST
+=====================
+
+The following is a sample VHOST you might want to consider for your project.
+
+<VirtualHost *:80>
+ DocumentRoot "/var/www/dev.doctrinetest.com/public"
+ ServerName dev.doctrinetest.com.local
+
+ # This should be omitted in the production environment
+ SetEnv APPLICATION_ENV development
+
+ <Directory "/var/www/dev.doctrinetest.com/public">
+ Options Indexes MultiViews FollowSymLinks
+ AllowOverride All
+ Order allow,deny
+ Allow from all
+ </Directory>
+
+</VirtualHost>
19 library/WJG/Controller/Action/Helper/EntityManager.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * This custom action helper just cuts down on the lengthy bit of typing we'd otherwise have
+ * to do in order to retrieve the custom Entity Manager resource located in:
+ * /library/WJG/Resource/Entitymanager.php
+ *
+ */
+class WJG_Controller_Action_Helper_EntityManager extends Zend_Controller_Action_Helper_Abstract
+{
+ public function direct()
+ {
+ return $this->getActionController()->getInvokeArg('bootstrap')->getResource('entityManager');
+ }
+}
+
+?>
+
+
66 library/WJG/Resource/Entitymanager.php
@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * This is a Zend Framework resource plugin. It is responsible for making
+ * Doctrine 2 available to the application. See this page for more information about
+ * the purpose of an entity manager:
+ * http://www.doctrine-project.org/docs/orm/2.0/en/reference/working-with-objects.html
+ *
+ */
+class WJG_Resource_Entitymanager extends Zend_Application_Resource_ResourceAbstract
+{
+
+ public function init()
+ {
+
+ // Custom resource plugins inherit this sweet getOptions() method which will retrieve
+ // configuration settings from the application.ini file
+ $config = new Zend_Config($this->getOptions());
+
+ // Define the connection parameters
+ $options = array(
+ 'connection' => array(
+ 'driver' => "{$config->connection->driver}",
+ 'host' => "{$config->connection->host}",
+ 'dbname' => "{$config->connection->dbname}",
+ 'user' => "{$config->connection->user}",
+ 'password' => "{$config->connection->password}"
+ )
+ );
+
+ $configEm = new \Doctrine\ORM\Configuration;
+
+ $cache = new \Doctrine\Common\Cache\ArrayCache;
+
+ $driverImpl = $configEm->newDefaultAnnotationDriver(
+ $config->connection->entities
+ );
+
+ $configEm->setMetadataCacheImpl($cache);
+
+ $configEm->setMetadataDriverImpl($driverImpl);
+
+ // Configure proxies
+
+ $configEm->setAutoGenerateProxyClasses(
+ $config->connection->proxies->generate
+ );
+
+ $configEm->setProxyNamespace($config->connection->proxies->ns);
+
+ $configEm->setProxyDir(
+ $config->connection->proxies->location
+ );
+
+ // Configure cache
+
+ $configEm->setQueryCacheImpl($cache);
+
+ $em = \Doctrine\ORM\EntityManager::create($options['connection'], $configEm);
+ Zend_Registry::set('em', $em);
+
+ return $em;
+
+ }
+
+}
8 public/.htaccess
@@ -0,0 +1,8 @@
+SetEnv APPLICATION_ENV development
+
+RewriteEngine On
+RewriteCond %{REQUEST_FILENAME} -s [OR]
+RewriteCond %{REQUEST_FILENAME} -l [OR]
+RewriteCond %{REQUEST_FILENAME} -d
+RewriteRule ^.*$ - [NC,L]
+RewriteRule ^.*$ index.php [NC,L]
BIN public/images/epwzf2e.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 public/index.php
@@ -0,0 +1,28 @@
+<?php
+
+// Define path to application directory
+defined('APPLICATION_PATH')
+ || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
+
+// Define application environment
+defined('APPLICATION_ENV')
+ || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production'));
+
+// Ensure library/ is on include_path
+set_include_path(implode(PATH_SEPARATOR, array(
+ realpath(APPLICATION_PATH . '/../library'),
+ realpath(APPLICATION_PATH . '/../application/models/Entities'),
+ realpath('/home/wjgilmorecom/libraries'),
+ get_include_path(),
+)));
+
+/** Zend_Application */
+require_once 'Zend/Application.php';
+
+// Create application, bootstrap, and run
+$application = new Zend_Application(
+ APPLICATION_ENV,
+ APPLICATION_PATH . '/configs/application.ini'
+);
+$application->bootstrap()
+ ->run();
47 tests/ModelTestCase.php
@@ -0,0 +1,47 @@
+<?php
+
+class ModelTestCase extends PHPUnit_Framework_TestCase
+{
+
+ protected $em;
+ protected $application;
+ protected $bootstrap;
+
+ public function setUp()
+ {
+
+ $this->appBootstrap();
+
+ //$this->doctrineContainer->getEntityManager()->getMetadataFactory()->getAllMetadata()
+
+
+ //$tool = new \Doctrine\ORM\Tools\SchemaTool($this->em);
+ //$tool->createSchema('/var/www/z2d2/application/models/Entities');
+
+ parent::setUp();
+
+ }
+
+ public function tearDown()
+ {
+ parent::tearDown();
+ }
+
+ public function appBootstrap()
+ {
+
+ $this->application = new Zend_Application(APPLICATION_ENV, APPLICATION_PATH . '/configs/application.ini');
+
+ $this->application->bootstrap();
+
+ $bootstrap = $this->application->getBootstrap();
+
+ $this->em = $bootstrap->getResource('entityManager');
+
+ $front = $bootstrap->getResource('FrontController');
+
+ $front->setParam('bootstrap', $bootstrap);
+
+ }
+
+}
26 tests/application/bootstrap.php
@@ -0,0 +1,26 @@
+<?php
+
+define('BASE_PATH', realpath(dirname(__FILE__) . '/../../'));
+
+define('APPLICATION_PATH', BASE_PATH . '/application');
+
+// Include path
+
+set_include_path(
+ '.'
+ . PATH_SEPARATOR . BASE_PATH . '/library'
+ . PATH_SEPARATOR . get_include_path()
+);
+
+set_include_path(implode(PATH_SEPARATOR, array(
+ realpath(APPLICATION_PATH . '/../application/views/scripts'),
+ realpath(APPLICATION_PATH . '/../application/models'),
+ get_include_path(),
+)));
+var_dump(get_include_path());
+
+define('APPLICATION_ENV', 'testing');
+
+require_once 'controllers/ControllerTestCase.php';
+require_once 'ModelTestCase.php';
+
31 tests/application/controllers/ControllerTestCase.php
@@ -0,0 +1,31 @@
+<?php
+require_once 'Zend/Application.php';
+require_once 'Zend/Test/PHPUnit/ControllerTestCase.php';
+
+abstract class ControllerTestCase extends Zend_Test_PHPUnit_ControllerTestCase
+{
+ protected $application;
+
+ public function setUp()
+ {
+ $this->bootstrap = array($this, 'appBootstrap');
+
+ return parent::setUp();
+ }
+
+ public function appBootstrap()
+ {
+
+ $this->application = new Zend_Application(APPLICATION_ENV, APPLICATION_PATH . '/configs/application.ini');
+
+ $this->application->bootstrap();
+
+ $bootstrap = $this->application->getBootstrap();
+
+ $front = $bootstrap->getResource('FrontController');
+
+ $front->setParam('bootstrap', $bootstrap);
+
+ }
+}
+
15 tests/application/controllers/IndexControllerTest.php
@@ -0,0 +1,15 @@
+<?php
+
+class IndexControllerTest extends ControllerTestCase
+{
+
+ public function testDoesHomePageExist()
+ {
+ $this->dispatch('/');
+ $this->assertController('index');
+ $this->assertAction('index');
+
+ }
+
+}
+
29 tests/application/models/AccountTest.php
@@ -0,0 +1,29 @@
+<?php
+
+class AccountTest extends ModelTestCase
+{
+
+ public function testCanInstantiateAccount()
+ {
+ $this->assertInstanceOf('\Entities\Account', new \Entities\Account);
+ }
+
+ public function testCanSaveAndRetrieveUser()
+ {
+
+ $account = new \Entities\Account;
+ $account->setUsername('wjgilmore-test');
+ $account->setEmail('example@wjgilmore.com');
+ $account->setPassword('jason');
+ $account->setZip('43201');
+ $this->em->persist($account);
+ $this->em->flush();
+
+ $account = $this->em->getRepository('Entities\Account')->findOneByUsername('wjgilmore-test');
+
+ $this->assertEquals('wjgilmore-test', $account->getUsername());
+
+
+ }
+
+}
0 tests/library/bootstrap.php
No changes.
17 tests/phpunit.xml
@@ -0,0 +1,17 @@
+<phpunit bootstrap="./application/bootstrap.php" colors="true">
+ <testsuite name="z2d2">
+ <directory>./</directory>
+ </testsuite>
+
+ <filter>
+ <whitelist>
+ <directory suffix=".php">../application/</directory>
+ <exclude>
+ <file>../application/bootstrap.php</file>
+ <file>../application/controllers/ErrorController.php</file>
+ <directory suffix=".phtml">../application/</directory>
+ </exclude>
+ </whitelist>
+ </filter>
+
+</phpunit>

0 comments on commit af2180b

Please sign in to comment.
Something went wrong with that request. Please try again.