This is method for creating song object
public function getSong() {
return new Song($this->rackDir, $this->getLoadedDisc()->getName(), $this->song);
}
There is Song class
class Song extends CD {
private $id;
public function __construct($rack, $name, $id)
{
$this->id = $id;
parent::__construct($rack, $name);
}
public function getSelectedSongId() {
return $this->id;
}
public function getSelectedSongPath() {
$list = $this->getSongsList();
return $list[$this->id];
}
}
public function getSongInfo () {
$data = [
'name' => $this->getName(),
'size' => $this->getSize(),
];
return $data;
}
public function getSize() {
$path = $this->getPath() . '/' . $this->getName();
return filesize($path);
}
public function getName() {
return $this->getSelectedSongPath();
}
}
And there is CD Class where I check if file has audio extension.
class CD {
private $path;
private $name;
private $rack;
private $validExtensions;
public function __construct($rack, $name)
{
$this->rack = $rack . '/';
$this->name = $name;
$this->path = $this->rack . $this->name;
$this->validExtensions = ['mp3', 'mp4', 'wav'];
}
public function getPath() {
return $this->path;
}
public function getName() {
return $this->name;
}
public function getSongsList () {
$path = $this->rack . $this->name;
$songsList = [];
if (!is_dir($path)) {
return false;
}
if ($handle = opendir($path)) {
while (false !== ($file = readdir($handle)))
{
if ($file != "." && $file != ".." && in_array(strtolower(substr($file, strrpos($file, '.') + 1)), $this->validExtensions))
{
array_push($songsList, $file);
}
}
closedir($handle);
}
return $songsList;
}
}
I want to check if File is real audio file and not just file with an audio extension?
Is there is method to do that in PHP?
Karlos was in right.
I was found a solution with this code bellow.
public function validateFile (Song $song) {
$allowed = array(
'audio/mp4', 'audio/mp3', 'audio/mpeg3', 'audio/x-mpeg-3', 'audio/mpeg', 'audio/*'
);
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$info = finfo_file($finfo, $song->getSelectedSongPath());
if (!in_array($info, $allowed)) {
die( 'file is empty / corrupted');
}
return $song;
}
Related
I was receiving an error message because I upgraded to PHP 7 from 5 and added public function helper(heler = array()) but now I receiving a parse error
Message: syntax error, unexpected 'public' (T_PUBLIC)
I have tried moving the array to the My_loader.php file but I receive the same error
<?php (defined('BASEPATH')) OR exit('No direct script access allowed');
class MX_Loader extends CI_Loader {
protected $_module;
public $_ci_plugins = array();
public $_ci_cached_vars = array();
public function __construct() {
parent::__construct();
/* set the module name */
$this->_module = CI::$APP->router->fetch_module();
/* add this module path to the loader variables */
$this->_add_module_paths($this->_module);
}
/** Initialize the module **/
public function _init($controller) {
/* references to ci loader variables */
foreach (get_class_vars('CI_Loader') as $var => $val) {
if ($var != '_ci_ob_level') $this->$var =& CI::$APP->load->$var;
}
/* set a reference to the module controller */
$this->controller = $controller;
$this->__construct();
}
/** Add a module path loader variables **/
public function _add_module_paths($module = '') {
if (empty($module)) return;
foreach (Modules::$locations as $location => $offset) {
/* only add a module path if it exists */
if (is_dir($module_path = $location.$module.'/')) {
array_unshift($this->_ci_model_paths, $module_path);
}
}
}
/** Load a module config file **/
public function config($file = 'config', $use_sections = FALSE, $fail_gracefully = FALSE) {
return CI::$APP->config->load($file, $use_sections, $fail_gracefully, $this->_module);
}
/** Load the database drivers **/
public function database($params = '', $return = FALSE, $active_record = NULL) {
if (class_exists('CI_DB', FALSE) AND $return == FALSE AND $active_record == NULL AND isset(CI::$APP->db) AND is_object(CI::$APP->db))
return;
require_once BASEPATH.'database/DB'.EXT;
if ($return === TRUE) return DB($params, $active_record);
CI::$APP->db = DB($params, $active_record);
return CI::$APP->db;
}
/** Load a module helper **/
public function helper($helper) {
if (is_array($helper)) return $this->helpers($helper);
if (isset($this->_ci_helpers[$helper])) return;
list($path, $_helper) = Modules::find($helper.'_helper', $this->_module, 'helpers/');
if ($path === FALSE) return parent::helper($helper);
Modules::load_file($_helper, $path);
$this->_ci_helpers[$_helper] = TRUE;
}
/** Load an array of helpers **/
public function helpers($helpers) {
foreach ($helpers as $_helper) $this->helper($_helper);
}
/** Load a module language file **/
public function language($langfile, $idiom = '', $return = FALSE, $add_suffix = TRUE, $alt_path = '') {
return CI::$APP->lang->load($langfile, $idiom, $return, $add_suffix, $alt_path, $this->_module);
}
public function languages($languages) {
foreach($languages as $_language) $this->language($language);
}
/** Load a module library **/
public function library($library, $params = NULL, $object_name = NULL) {
if (is_array($library)) return $this->libraries($library);
$class = strtolower(end(explode('/', $library)));
public function helper($helper = array())
if (isset($this->_ci_classes[$class]) AND $_alias = $this->_ci_classes[$class])
return CI::$APP->$_alias;
($_alias = strtolower($object_name)) OR $_alias = $class;
list($path, $_library) = Modules::find($library, $this->_module, 'libraries/');
/* load library config file as params */
if ($params == NULL) {
list($path2, $file) = Modules::find($_alias, $this->_module, 'config/');
($path2) AND $params = Modules::load_file($file, $path2, 'config');
}
if ($path === FALSE) {
$this->_ci_load_class($library, $params, $object_name);
$_alias = $this->_ci_classes[$class];
} else {
Modules::load_file($_library, $path);
$library = ucfirst($_library);
CI::$APP->$_alias = new $library($params);
$this->_ci_classes[$class] = $_alias;
}
return CI::$APP->$_alias;
}
/** Load an array of libraries **/
public function libraries($libraries) {
foreach ($libraries as $_library) $this->library($_library);
}
/** Load a module model **/
public function model($model, $object_name = NULL, $connect = FALSE) {
if (is_array($model)) return $this->models($model);
($_alias = $object_name) OR $_alias = end(explode('/', $model));
if (in_array($_alias, $this->_ci_models, TRUE))
return CI::$APP->$_alias;
/* check module */
list($path, $_model) = Modules::find(strtolower($model), $this->_module, 'models/');
if ($path == FALSE) {
/* check application & packages */
parent::model($model, $object_name);
} else {
class_exists('CI_Model', FALSE) OR load_class('Model', 'core');
if ($connect !== FALSE AND ! class_exists('CI_DB', FALSE)) {
if ($connect === TRUE) $connect = '';
$this->database($connect, FALSE, TRUE);
}
Modules::load_file($_model, $path);
$model = ucfirst($_model);
CI::$APP->$_alias = new $model();
$this->_ci_models[] = $_alias;
}
return CI::$APP->$_alias;
}
/** Load an array of models **/
public function models($models) {
foreach ($models as $_model) $this->model($_model);
}
/** Load a module controller **/
public function module($module, $params = NULL) {
if (is_array($module)) return $this->modules($module);
$_alias = strtolower(end(explode('/', $module)));
CI::$APP->$_alias = Modules::load(array($module => $params));
return CI::$APP->$_alias;
}
/** Load an array of controllers **/
public function modules($modules) {
foreach ($modules as $_module) $this->module($_module);
}
/** Load a module plugin **/
public function plugin($plugin) {
if (is_array($plugin)) return $this->plugins($plugin);
if (isset($this->_ci_plugins[$plugin]))
return;
list($path, $_plugin) = Modules::find($plugin.'_pi', $this->_module, 'plugins/');
if ($path === FALSE) return;
Modules::load_file($_plugin, $path);
$this->_ci_plugins[$plugin] = TRUE;
}
/** Load an array of plugins **/
public function plugins($plugins) {
foreach ($plugins as $_plugin) $this->plugin($_plugin);
}
/** Load a module view **/
public function view($view, $vars = array(), $return = FALSE) {
list($path, $view) = Modules::find($view, $this->_module, 'views/');
$this->_ci_view_path = $path;
return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_object_to_array($vars), '_ci_return' => $return));
}
public function _ci_is_instance() {}
public function _ci_get_component($component) {
return CI::$APP->$component;
}
public function __get($class) {
return (isset($this->controller)) ? $this->controller->$class : CI::$APP->$class;
}
public function _ci_load($_ci_data) {
foreach (array('_ci_view', '_ci_vars', '_ci_path', '_ci_return') as $_ci_val) {
$$_ci_val = ( ! isset($_ci_data[$_ci_val])) ? FALSE : $_ci_data[$_ci_val];
}
if ($_ci_path == '') {
$_ci_file = strpos($_ci_view, '.') ? $_ci_view : $_ci_view.EXT;
$_ci_path = $this->_ci_view_path.$_ci_file;
} else {
$_ci_file = end(explode('/', $_ci_path));
}
if ( ! file_exists($_ci_path))
show_error('Unable to load the requested file: '.$_ci_file);
if (is_array($_ci_vars))
$this->_ci_cached_vars = array_merge($this->_ci_cached_vars, $_ci_vars);
extract($this->_ci_cached_vars);
ob_start();
if ((bool) #ini_get('short_open_tag') === FALSE AND CI::$APP->config->item('rewrite_short_tags') == TRUE) {
echo eval('?>'.preg_replace("/;*\s*\?>/", "; ?>", str_replace('<?=', '<?php echo ', file_get_contents($_ci_path))));
} else {
include($_ci_path);
}
log_message('debug', 'File loaded: '.$_ci_path);
if ($_ci_return == TRUE) return ob_get_clean();
if (ob_get_level() > $this->_ci_ob_level + 1) {
ob_end_flush();
} else {
CI::$APP->output->append_output(ob_get_clean());
}
}
/** Autoload module items **/
public function _autoloader($autoload) {
$path = FALSE;
if ($this->_module) {
list($path, $file) = Modules::find('constants', $this->_module, 'config/');
/* module constants file */
if ($path != FALSE) {
include_once $path.$file.EXT;
}
list($path, $file) = Modules::find('autoload', $this->_module, 'config/');
/* module autoload file */
if ($path != FALSE) {
$autoload = array_merge(Modules::load_file($file, $path, 'autoload'), $autoload);
}
}
/* nothing to do */
if (count($autoload) == 0) return;
/* autoload package paths */
if (isset($autoload['packages'])) {
foreach ($autoload['packages'] as $package_path) {
$this->add_package_path($package_path);
}
}
/* autoload config */
if (isset($autoload['config'])) {
foreach ($autoload['config'] as $config) {
$this->config($config);
}
}
/* autoload helpers, plugins, languages */
foreach (array('helper', 'plugin', 'language') as $type) {
if (isset($autoload[$type])){
foreach ($autoload[$type] as $item) {
$this->$type($item);
}
}
}
/* autoload database & libraries */
if (isset($autoload['libraries'])) {
if (in_array('database', $autoload['libraries'])) {
/* autoload database */
if ( ! $db = CI::$APP->config->item('database')) {
$db['params'] = 'default';
$db['active_record'] = TRUE;
}
$this->database($db['params'], FALSE, $db['active_record']);
$autoload['libraries'] = array_diff($autoload['libraries'], array('database'));
}
/* autoload libraries */
foreach ($autoload['libraries'] as $library) {
$this->library($library);
}
}
/* autoload models */
if (isset($autoload['model'])) {
foreach ($autoload['model'] as $model => $alias) {
(is_numeric($model)) ? $this->model($alias) : $this->model($model, $alias);
}
}
/* autoload module controllers */
if (isset($autoload['modules'])) {
foreach ($autoload['modules'] as $controller) {
($controller != $this->_module) AND $this->module($controller);
}
}
}
}
/** load the CI class for Modular Separation **/
(class_exists('CI', FALSE)) OR require dirname(__FILE__).'/Ci.php';
It looks like you have an extra line just pasted into the middle of the code at line 105:
$class = strtolower(end(explode('/', $library)));
public function helper($helper = array()) // <===== delete this one
if (isset($this->_ci_classes[$class]) AND $_alias = $this->_ci_classes[$class])
return CI::$APP->$_alias;
If you run php -l <file> on your file(s) from the command line, it will tell you exactly where the errors are.
I've made a website in symfony. This website contains some forms with a checkbox choice and other fields.
The datas from the checkbox are serialized on flush.
It's all good.
Now i have to export this datas and i use the data exporter library from Sonata project. But the datas are still serialized and i have some things like that in my csv file:
a:2:{i:0;s:6:"Volets";i:1;s:22:"Panneau de remplissage";}
How can I unserialize my datas in order to have a clean csv file?
Here's my code
My controller
/**
* #Security("has_role('ROLE_WEBFORM')")
*/
public function exportAction(Request $request)
{
$filters = array();
$this->handleFilterForm($request, $filters);
if (!$filters['webform']) {
throw $this->createNotFoundException();
}
$webForm = $this->getRepository('CoreBundle:WebForm')->find($filters['webform']);
$source = new WebFormEntryIterator($webForm, $this->getEntityManager(), $this->get('ines_core.embedded_form.field_type_registry'), $filters);
return WebFormEntryExporter::createResponse('export.csv', $source);
}
and my class WebFormEntryExporter
class WebFormEntryExporter
{
public static function createResponse($filename, SourceIteratorInterface $source)
{
$writer = new CsvWriter('php://output', ';', '"', "", true, true);
$contentType = 'text/csv';
$callback = function() use ($source, $writer) {
$handler = \Exporter\Handler::create($source, $writer);
$handler->export();
};
return new StreamedResponse($callback, 200, [
'Content-Type' => $contentType,
'Content-Disposition' => sprintf('attachment; filename=%s', $filename)
]);
}
}
And my WebFormEntryIterator
class WebFormEntryIterator implements SourceIteratorInterface
{
protected $em;
protected $registry;
protected $repository;
protected $query;
protected $webForm;
protected $iterator;
public function __construct(WebForm $webForm, EntityManager $em, FieldTypeRegistry $registry, array $filters)
{
$this->webForm = $webForm;
$this->em = $em;
$this->registry = $registry;
$this->initQuery($filters);
}
/**
* {#inheritdoc}
*/
public function current()
{
$current = $this->iterator->current();
$entity = $current[0];
$data = [];
$data['ID'] = $entity->getId();
$data['Formulaire'] = $this->webForm->getName();
$data['Date de création'] = date_format($entity->getCreatedAt(), 'd/m/Y H:i:s');
foreach ($this->webForm->getEmbeddedFieldConfigs() as $fieldConfig) {
$header = $fieldConfig->getLabel();
$meta = $entity->getContentMeta($fieldConfig->getName());
$extension = $this->registry->get($meta->getFormat());
if (method_exists($extension, 'setEntityManager')) {
$extension->setEntityManager($this->em);
}
$value = $extension->formatMeta($meta);
$data[$header] = $value;
unset($extension);
}
$this->query->getEntityManager()->getUnitOfWork()->detach($current[0]);
unset($entity);
unset($webForm);
return $data;
}
/**
* {#inheritdoc}
*/
public function next()
{
$this->iterator->next();
}
/**
* {#inheritdoc}
*/
public function key()
{
return $this->iterator->key();
}
/**
* {#inheritdoc}
*/
public function valid()
{
return $this->iterator->valid();
}
/**
* {#inheritdoc}
*/
public function rewind()
{
if ($this->iterator) {
throw new InvalidMethodCallException('Cannot rewind a Doctrine\ORM\Query');
}
$this->iterator = $this->query->iterate();
$this->iterator->rewind();
}
protected function initQuery(array $filters)
{
$repository = $this->em->getRepository('InesCoreBundle:Content');
$qb = $repository->getWebFormEntryQueryBuilder();
$repository->applyWfeFilters($qb, $filters);
$this->query = $qb->getQuery();
}
}
Sorry for my broken English.
Thanks a lot
thanks chalasr.
I have to make the tratment in this file, in the current() function.
This is what I've done:
public function current()
{
$current = $this->iterator->current();
$entity = $current[0];
$data = [];
$data['ID'] = $entity->getId();
$data['Formulaire'] = $this->webForm->getName();
$data['Date de création'] = date_format($entity->getCreatedAt(), 'd/m/Y H:i:s');
foreach ($this->webForm->getEmbeddedFieldConfigs() as $fieldConfig) {
$header = $fieldConfig->getLabel();
$meta = $entity->getContentMeta($fieldConfig->getName());
$extension = $this->registry->get($meta->getFormat());
if (method_exists($extension, 'setEntityManager')) {
$extension->setEntityManager($this->em);
}
$value = $extension->formatMeta($meta);
if($this->is_serialized($value)) {
$value = unserialize($value);
$data[$header] = implode(' | ', $value);
} else {
$data[$header] = $value;
}
unset($extension);
}
$this->query->getEntityManager()->getUnitOfWork()->detach($current[0]);
unset($entity);
unset($webForm);
return $data;
}
public function is_serialized($data)
{
if (trim($data) == "") { return false; }
if (preg_match("/^(i|s|a|o|d){1}:{1}(.*)/si",$data)) { return true; }
return false;
}
I have multiple entities that have some sort of file attached to them. I have followed the cookbook entry on how to handle file uploads with doctrine (here) but my question is this:
How can I do this for multiple entities without duplicating lots of code? Right now all of my entities share the functions related to getting the path, albeit with some modifications here and there, so they are not identical, but most of the code is. What is the cleanest way of doing this?
Here is an example of two entities, notice overlapping functionality:
Image:
public function preUpload()
{
if (null === $this->file) {
return;
}
$dir = $this->getUploadRootDir().'/'.$this->getParentDir();
if (!is_dir($dir)) {
mkdir($dir);
}
$slugger = new \Sam\TourBundle\Service\SlugService();
$pathinfo = pathinfo($this->file->getClientOriginalName());
$path = $slugger->slugize($pathinfo['filename']).'.'.$pathinfo['extension'];
$this->path = $path;
// If file already exists rename it
if (file_exists($this->getAbsolutePath())) {
$i = 1;
while (file_exists($this->getAbsolutePath())) {
$this->path = $i.'-'.$this->path;
$i++;
}
}
}
/**
* #ORM\PostPersist()
* #ORM\PostUpdate()
*/
public function upload()
{
// the file property can be empty if the field is not required
if (null === $this->file) {
return;
}
$dir = $this->getUploadRootDir().'/'.$this->getParentDir();
$this->file->move($dir, $this->path);
$thumb = new \Sam\TourBundle\Service\ThumbnailService();
$thumb->makeThumbnail($this->getAbsolutePath());
unset($this->file);
}
/**
* #ORM\PostRemove()
*/
public function removeUpload()
{
$file = $this->getAbsolutePath();
$thumb_file = $this->getThumbnailAbsolutePath();
if (file_exists($file)) {
unlink($file);
}
if (file_exists($thumb_file)) {
unlink($thumb_file);
}
}
public function getParentDir()
{
return $galerija = $this->getGalerija()->getSlug().'/';
//return null === $galerija ? null : $this->getUploadRootDir().'/'.$galerija.$this->path;
}
public function getAbsolutePath()
{
return null === $this->path ? null : $this->getUploadRootDir().'/'.$this->getParentDir().$this->path;
}
public function getThumbnailAbsolutePath()
{
$pathinfo = pathinfo($this->getAbsolutePath());
$thumbpath = $pathinfo['dirname'].'/'.$pathinfo['filename'].'_thumb.'.$pathinfo['extension'];
return null === $this->path ? null : $thumbpath;
}
public function getRootDir()
{
return __DIR__;
}
public function getWebPath()
{
return null === $this->path ? null : $this->getUploadDir().'/'.$this->getParentDir().$this->path;
}
public function getThumbnailWebPath()
{
$pathinfo = pathinfo($this->getAbsolutePath());
$thumbpath = $pathinfo['filename'].'_thumb.'.$pathinfo['extension'];
return null === $this->path ? null : $this->getUploadDir().'/'.$this->getParentDir().$thumbpath;
}
protected function getUploadRootDir()
{
// the absolute directory path where uploaded documents should be saved
return realpath(__DIR__.'/../../../../web/'.$this->getUploadDir());
}
protected function getUploadDir()
{
// get rid of the __DIR__ so it doesn't screw when displaying uploaded doc/image in the view
return 'images';
}
Document:
public function preUpload()
{
if (null === $this->file) {
return;
}
$dir = $this->getUploadRootDir().'/'.$this->getParentDir();
if (!is_dir($dir)) {
mkdir($dir);
}
$slugger = new \Sam\TourBundle\Service\SlugService();
$pathinfo = pathinfo($this->file->getClientOriginalName());
$path = $slugger->slugize($pathinfo['filename']).'.'.$pathinfo['extension'];
$this->path = $path;
// If file already exists rename it
if (file_exists($this->getAbsolutePath())) {
$i = 1;
while (file_exists($this->getAbsolutePath())) {
$this->path = $i.'-'.$this->path;
$i++;
}
}
}
/**
* #ORM\PostPersist()
* #ORM\PostUpdate()
*/
public function upload()
{
// the file property can be empty if the field is not required
if (null === $this->file) {
return;
}
$dir = $this->getUploadRootDir().'/'.$this->getParentDir();
$this->file->move($dir, $this->path);
unset($this->file);
}
/**
* #ORM\PostRemove()
*/
public function removeUpload()
{
$file = $this->getAbsolutePath();
if (file_exists($file)) {
unlink($file);
}
}
public function getParentDir()
{
return $ponuda = $this->getPonuda()->getSlug().'/';
}
public function getAbsolutePath()
{
return null === $this->path ? null : $this->getUploadRootDir().'/'.$this->getParentDir().$this->path;
}
public function getRootDir()
{
return __DIR__;
}
public function getWebPath()
{
return null === $this->path ? null : $this->getUploadDir().'/'.$this->getParentDir().$this->path;
}
protected function getUploadRootDir()
{
// the absolute directory path where uploaded documents should be saved
return realpath(__DIR__.'/../../../../web/'.$this->getUploadDir());
}
protected function getUploadDir()
{
// get rid of the __DIR__ so it doesn't screw when displaying uploaded doc/image in the view
return 'documents';
}
I would personally create an upload service class with an method which you can pass the entities, you can inject this service wherever you need and have it written in only one place.
Generally is not a great idea to have this kind of logic in your entities I believe.
Inheritance in this case looks completely incorrect from my point of view since it's a way of adding behavior instead of a generalization, you could do it but I'd advice against it. Inheritance per se is way overused and not the cleanest way to work, and Doctrine's implementation of it is quite annoying to work with as well. Traits could do it, though I haven't had much experience with them yet in this kind of environment.
I'd strongly advice using services the way Symfony was meant to be used.
I have this error while trying to use late static bindings. All I can find in google about this error is that people didn't have PHP5.3, but I have version 5.3.6.
Could someone help me please ?
Thanks
class Media
{
private $nom,
$ext;
public function ext_autorisees() { return array(); }
public function __construct( $fichier, $thumb = false )
{
$fichier = explode( ".", $fichier );
$nom = $fichier[0];
$ext = $fichier[1];
if( in_array( strtoupper( $ext ), static::ext_autorisees() ) )
{
if( strpos( $nom, "thumb_" ) === 0 && !$thumb )
throw new Exception("");
}
else
throw new Exception("");
$this->nom = $nom;
$this->ext = $ext;
}
public function getNom() { return $this->nom; }
public function getExt() { return $this->ext; }
public function getPath() { return $this->getNom() . "." . $this->getExt(); }
public function getThumb() { return "thumb_" . $this->getPath(); }
}
there is a problem in static::ext_autorisees()
I keep getting the following exception with a new resource Im making and i cant figure out why:
PHP Fatal error: Uncaught exception 'Zend_Application_Bootstrap_Exception' with message 'Circular resource dependency detected' in /opt/local/lib/php/Zend/Application/Bootstrap/BootstrapAbstract.php:656
Stack trace:
#0 /opt/local/lib/php/Zend/Application/Bootstrap/BootstrapAbstract.php(623): Zend_Application_Bootstrap_BootstrapAbstract->_executeResource('modules')
#1 /opt/local/lib/php/Zend/Application/Bootstrap/BootstrapAbstract.php(580): Zend_Application_Bootstrap_BootstrapAbstract->_bootstrap('modules')
#2 /Library/WebServer/Documents/doctrine-dev/library/APP/Doctrine/Application/Resource/Doctrine.php(36): Zend_Application_Bootstrap_BootstrapAbstract->bootstrap('modules')
#3 /opt/local/lib/php/Zend/Application/Bootstrap/BootstrapAbstract.php(708): APP_Doctrine_Application_Resource_Doctrine->__construct(Array)
#4 /opt/local/lib/php/Zend/Application/Bootstrap/BootstrapAbstract.php(349): Zend_Application_Bootstrap_BootstrapAbstract->_loadPluginResource('doctrine', Array)
#5 /opt/local/lib/php/Zend/Application/Bootstrap/Bootstra in /opt/local/lib/php/Zend/Application/Bootstrap/BootstrapAbstract.php on line 656
As you'll see below ive created a Doctrine Resource that should load only in the general application bootstrap. In order to perform its tasks it needs the Modules resource to be bootstraped
so it calls $this->getBootstrap()->bootstrap('modules'). the Modules resoure never calls Doctrine though, and this seems to be where i get the circular dependency. Ive tried the code that is currently in the constructor for my Doctrine resource also as part of init directly and that doesnt seem to work either. An even bigger mystery to me though is that if i call $bootstrap->bootstrap('modules')
by itself before calling $bootstrap->bootstrap('doctrine') it all seems to play nicely. So why is there circular reference issue?
Relevant parts of application.xml
<resources>
<frontController>
<controllerDirectory><zf:const zf:name="APPLICATION_PATH" />/controllers</controllerDirectory>
<moduleDirectory><zf:const zf:name="APPLICATION_PATH" />/modules</moduleDirectory>
<moduleControllerDirectoryName value="controllers" />
</frontController>
<modules prefixModuleName="Mod" configFilename="module.xml">
<enabledModules>
<default />
<doctrinetest />
<cms>
<myOption value="Test Option Value" />
</cms>
<menu somevar="menu" />
<article somevar="article" />
</enabledModules>
</modules>
<doctrine>
<connections>
<default dsn="mysql://#####:######localhost/#####">
<attributes useNativeEnum="1" />
</default>
</connections>
<attributes>
<autoAccessorOverride value="1" />
<autoloadTableClasses value="1" />
<modelLoading value="MODEL_LOADING_PEAR" />
</attributes>
<directoryNames>
<sql value="data/sql" />
<fixtures value="data/fixtures" />
<migrations value="data/migrations" />
<yaml value="configs/schemas" />
<models value="models" />
</directoryNames>
</doctrine>
</resources>
Doctrine Resource
<?php
class APP_Doctrine_Application_Resource_Doctrine extends Zend_Application_Resource_ResourceAbstract
{
protected $_manager = null;
protected $_modules = array();
protected $_attributes = null;
protected $_connections = array();
protected $_defaultConnection = null;
protected $_directoryNames = null;
protected $_inflectors = array();
public function __construct($options = null)
{
parent::__construct($options);
$bootstrap = $this->getBootstrap();
$autoloader = $bootstrap->getApplication()->getAutoloader();
$autoloader->pushAutoloader(array('Doctrine_Core', 'autoload'), 'Doctrine');
spl_autoload_register(array('Doctrine_Core', 'modelsAutoload'));
$manager = $this->getManager();
$manager->setAttribute('bootstrap', $bootstrap);
// default module uses the application bootstrap unless overridden!
$modules = array('default' => $bootstrap);
if(!isset($options['useModules']) ||
(isset($options['useModules']) && (boolean) $options['useModules']))
{
$moduleBootstraps = $bootstrap->bootstrap('modules')->getResource('modules');
$modules = array_merge($modules, $moduleBootstraps->getArrayCopy());
}
$this->setModules($modules); // configure the modules
$this->_loadModels(); // load all the models for Doctrine
}
public function init()
{
return $this->getManager();
}
public function setConnections(array $connections)
{
$manager = $this->getManager();
foreach($connections as $name => $config)
{
if(isset($config['dsn']))
{
$conn = $manager->connection($config['dsn'], $name);
}
if(isset($config['attributes']) && isset($conn))
{
$this->setAttributes($config['attributes'], $conn);
}
}
return $this;
}
public function setAttributes(array $attributes, Doctrine_Configurable $object = null)
{
if($object === null)
{
$object = $this->getManager();
}
foreach($attributes as $name => $value)
{
$object->setAttribute(
$this->doctrineConstant($name, 'attr'),
$this->doctrineConstant($value)
);
}
return $this;
}
public function setModules(array $modules)
{
//$this->_modules = $modules;
foreach($modules as $name => $bootstrap)
{
$this->_modules[$name] = $this->_configureModuleOptions($bootstrap);
}
return $this;
}
public function setDirectoryNames(array $directoryNames)
{
$this->_directoryNames = $directoryNames;
return $this;
}
public function getDirectoryNames()
{
return $this->_directoryNames;
}
public function getDirectoryName($key)
{
if(isset($this->_directoryNames[$key]))
{
return $this->_directoryNames[$key];
}
return null;
}
public function getModuleOptions($module = null)
{
if($module === null)
{
return $this->_modules;
}
if(isset($this->_modules[$module]))
{
return $this->_modules[$module];
}
return null;
}
public function doctrineConstant($value, $prefix = '')
{
if($prefix !== '')
{
$prefix .= '_';
}
$const = $this->_getConstantInflector()->filter(array(
'prefix'=>$prefix,
'key' => $value
));
$const = constant($const);
return $const !== null ? $const : $value;
}
/**
* getManager
* #return Doctrine_Manager
*/
public function getManager()
{
if(!$this->_manager)
{
$this->_manager = Doctrine_Manager::getInstance();
}
return $this->_manager;
}
protected function _getConstantInflector()
{
if(!isset($this->_inflectors['constant']))
{
$callback = new Zend_Filter_Callback(array('callback'=>'ucfirst'));
$this->_inflectors['constant'] = new Zend_Filter_Inflector(
'Doctrine_Core::#prefix#key',
array(
':prefix' => array($callback, 'Word_CamelCaseToUnderscore', 'StringToUpper'),
':key' => array('Word_SeparatorToCamelCase', 'Word_CamelCaseToUnderscore', 'StringToUpper')
), null, '#');
}
return $this->_inflectors['constant'];
}
protected function _configureModuleOptions(Zend_Application_Bootstrap_BootstrapAbstract $bootstrap)
{
$coreBootstrapClass = get_class($this->getBootstrap());
if(get_class($bootstrap) === $coreBootstrapClass)
{
// handled differently
$resourceLoader = $bootstrap->bootstrap('DefaultAutoloader')->getResource('DefaultAutoloader');
$moduleName = $resourceLoader->getNamespace();
}
else
{
// handle a module bootstrap
$resourceLoader = $bootstrap->getResourceLoader();
$moduleName = $bootstrap->getModuleName();
}
$resourceTypes = $resourceLoader->getResourceTypes();
$modelResource = isset($resourceTypes['model'])
? $resourceTypes['model']
: array('path'=>'models', 'namespace'=>'Model');
$modulePath = $resourceLoader->getBasePath();
$classPrefix = $modelResource['namespace'];
$modelsPath = $modelResource['path'];
$doctrineOptions = array(
'generateBaseClasses'=>TRUE,
'generateTableClasses'=>TRUE,
'baseClassPrefix'=>'Base_',
'baseClassesDirectory'=> NULL,
'baseTableClassName'=>'Doctrine_Table',
'generateAccessors' => true,
'classPrefix'=>"{$classPrefix}_",
'classPrefixFiles'=>FALSE,
'pearStyle'=>TRUE,
'suffix'=>'.php',
'phpDocPackage'=> $moduleName,
'phpDocSubpackage'=>'Models',
);
$doctrineConfig = array(
'data_fixtures_path' => "$modulePath/{$this->getDirectoryName('fixtures')}",
'models_path' => "$modelsPath",
'migrations_path' => "$modulePath/{$this->getDirectoryName('migrations')}",
'yaml_schema_path' => "$modulePath/{$this->getDirectoryName('yaml')}",
'sql_path' => "$modulePath/{$this->getDirectoryName('sql')}",
'generate_models_options' => $doctrineOptions
);
return $doctrineConfig;
}
protected function _loadModels()
{
$moduleOptions = $this->getModuleOptions();
foreach($moduleOptions as $module => $options)
{
Doctrine_Core::loadModels(
$options['models_path'],
Doctrine_Core::MODEL_LOADING_PEAR,
$options['generate_models_options']['classPrefix']
);
}
return $this;
}
}
Modules Resource
<?php
class APP_Application_Resource_Modules extends Zend_Application_Resource_Modules
{
protected $_prefixModuleNames = false;
protected $_moduleNamePrefix = null;
protected $_defaultModulePrefix = 'Mod';
protected $_configFileName = 'module.xml';
protected $_enabledModules = null;
public function __construct($options = null)
{
if(isset($options['prefixModuleName']))
{
if(($prefix = APP_Toolkit::literalize($options['prefixModuleName']))
!== false)
{
$this->_prefixModuleNames = true;
$this->_moduleNamePrefix = is_string($prefix)
? $prefix
: $this->_defaultModulePrefix;
}
}
if(isset($options['configFileName']))
{
$this->_configFileName = $options['configFileName'];
}
parent::__construct($options);
}
protected function _mergeModuleConfigs(array $applicationConfig)
{
$cacheManager = $this->_getCacheManager();
if(isset($applicationConfig['resources']['modules']['enabledModules']))
{
$applicationModulesOptions = &$applicationConfig['resources']['modules'];
$enabledModules = &$applicationModulesOptions['enabledModules'];
$front = $this->getBootstrap()->getResource('frontcontroller');
foreach($enabledModules as $moduleName => $moduleOptions)
{
// cache testing
// note cache keys for modules are prefixed if prefix is enabled #see _formatModuleName
if(!$cacheManager->test('config', $this->_formatModuleName($moduleName)))
{
$configPath = $front->getModuleDirectory($moduleName).'/configs/'.$this->getConfigFilename();
if(file_exists($configPath))
{
if(strpos($configPath, ".xml") === false)
{
throw new Exception(__CLASS__." is only compatible with XML configuration files.");
}
$config = new Zend_Config_Xml($configPath);
$enabledModules[$moduleName] = array_merge((array) $moduleOptions, $config->toArray());
//$this->setOptions($options);
$cacheManager->save('config', $enabledModules[$moduleName], $this->_formatModuleName($moduleName));
}
}
else
{
$options = $cacheManager->load('config', $this->_formatModuleName($moduleName));
$enabledModules[$moduleName] = array_merge((array) $enabledModules[$moduleName], $options);
}
}
}
return $applicationConfig;
}
public function init()
{
/**
* #var Zend_Application_Bootstrap_BoostrapAbstract
*/
$bootstrap = $this->getBootstrap();
if(!$bootstrap->hasResource('frontController'))
{
$bootstrap->bootstrap('frontController');
}
$front = $bootstrap->getResource('frontController');
$applicationConfig = $this->_mergeModuleConfigs($bootstrap->getOptions());
$bootstrap->setOptions($applicationConfig);
parent::init();
return $this->_bootstraps;
}
/**
* Format a module name to the module class prefix
*
* #param string $name
* #return string
*/
protected function _formatModuleName($name)
{
$name = strtolower($name);
$name = str_replace(array('-', '.'), ' ', $name);
$name = ucwords($name);
$name = str_replace(' ', '', $name);
$options = $this->getOptions();
if($this->prefixEnabled())
{
$name = $this->getModuleNamePrefix().$name;
}
return $name;
}
protected function _getCacheManager()
{
$bootstrap = $this->getBootstrap();
if(!$bootstrap->hasResource('cacheManager'))
{
$bootstrap->bootstrap('cacheManager');
}
return $bootstrap->getResource('cacheManager');
}
public function prefixEnabled()
{
return $this->_prefixModuleNames;
}
public function getModuleNamePrefix()
{
return $this->_moduleNamePrefix;
}
public function getConfigFilename()
{
return $this->_configFileName;
}
public function setEnabledModules($modules)
{
$this->_enabledModules = (array) $modules;
}
public function getEnabledModules($controllerDirectories = null)
{
if($controllerDirectories instanceof Zend_Controller_Front)
{
$controllerDirectories = $controllerDirectories->getControllerDirectory();
}
if(is_array($controllerDirectories))
{
$options = $this->getOptions();
$enabledModules = isset($options['enabledModules'])
? (array) $options['enabledModules']
: array();
$this->_enabledModules = array_intersect_key($controllerDirectories, $enabledModules);
}
elseif(null !== $controllerDirectories)
{
throw new InvalidArgumentException('Argument must be an instance of
Zend_Controller_Front or an array mathing the format of the
return value of Zend_Controller_Front::getControllerDirectory().'
);
}
return $this->_enabledModules;
}
public function setPrefixModuleName($value)
{
$this->_prefixModuleNames = APP_Toolkit::literalize($value);
}
}
Module Bootstrap Base Class
<?php
class APP_Application_Module_Bootstrap extends Zend_Application_Module_Bootstrap
{
public function _initResourceLoader()
{
$loader = $this->getResourceLoader();
$loader->addResourceType('actionhelper', 'helpers', 'Action_Helper');
}
}
Maybe this section of the e-book "Survive the Deep End" might help you : 6.6. Step 5: Fixing ZFExt_Bootstrap -- it specifically speaks about the error you are getting.
(I won't quote as there is quite a couple of long paragraphs, but, hopefully, this'll help)