Doctrine 2: Generated entities from database don't have namespaces - php

I am creating entities from the database trough the \Doctrine\ORM\Tools\DisconnectedClassMetadataFactory() class. This works perfectly! Except for the namespace generation. There are no namespaces generated. I am storing my entities in App/Model/Entities.
Does anyone know how to make the generator add namespaces to the entities?
This is the code I use to generate the entities:
<?php
$em->getConfiguration()->setMetadataDriverImpl(
new \Doctrine\ORM\Mapping\Driver\DatabaseDriver(
$em->getConnection()->getSchemaManager()
)
);
$cmf = new \Doctrine\ORM\Tools\DisconnectedClassMetadataFactory();
$cmf->setEntityManager($em);
$metadata = $cmf->getAllMetadata();
// GENERATE PHP ENTITIES!
$entityGenerator = new \Doctrine\ORM\Tools\EntityGenerator();
$entityGenerator->setGenerateAnnotations(true);
$entityGenerator->setGenerateStubMethods(true);
$entityGenerator->setRegenerateEntityIfExists(false);
$entityGenerator->setUpdateEntityIfExists(true);
$entityGenerator->generate($metadata, __dir__. '/Model/Entities");

I think, the better way is set namespace directly to driver
<?php
$driver = new \Doctrine\ORM\Mapping\Driver\DatabaseDriver($em->getConnection()->getSchemaManager());
$driver->setNamespace('App\\Model\\Entities\\');
$em->getConfiguration()->setMetadataDriverImpl($driver);
....

I don't think you can set the namespace when importing from the database, because the EntityGenerator takes the namespace information from the metadata. The database does not have or need namespaces, so the information does not automatically come from there.
You could try looping over the $metadata object and adding the namespace yourself to class names. The code in the EntityGenerator that retrieves the namespace is quite simple:
private function _getNamespace(ClassMetadataInfo $metadata)
{
return substr($metadata->name, 0, strrpos($metadata->name, '\\'));
}
If all else fails, you can always implement your own EntityGenerator that you can feed a namespace to use. We did that in our large project, where there are some other custom tasks to be done during generation. However, the EntityGenerator is not easily overriden, lots of private methods and properties so you probably have to copy&paste the whole thing.

You may use this PHP script to generate entities from database tables.
This script adds a sample namespace to generated files, so you can set your Namespace instead.
https://gist.github.com/SamvelG/3b39622844f23cac7e76#file-doctrine-entity-generator-php

Related

Programmatically Generating Namespaces for CLI application

I am creating a little CLI tool to assist in using a PHP library I built. One of the requirements of this tool is to Generate custom classes and interfaces, from a STUB template, all from a CLI command.
However, I am having a bit of problems with generating namespaces correctly.
So, I have this one stub file that looks like this.
<?php
namespace DummyNamspace;
use Spheracle\ApplicationService\ApplicationServiceInterface;
interface DummyContextNameServiceInterface extends ApplicationServiceInterface
{
// your code goes here
}
?>
I am using this library to create the stubs.
And, in my command class (Symfony), I have this code to create the namespace, which is passed to the generator directly.
$ns = ($project) ? $project . "\\" . $context : $context;
$generator = new AppServiceInterfaceGenerator($context, $dir, $ns);
$generator->generate();
here, $ms is the namespace text that will be placed in the STUB file. However, when I run this code via its assigned CLI command, I get the following output in the generated file.
My expected namespace for this entry is `Foo\Bar'. However, I get the following.
<?php
namespace 'Bar'Namspace;
use Spheracle\ApplicationService\ApplicationServiceInterface;
interface 'Bar'ContextNameServiceInterface extends ApplicationServiceInterface
{
// your code goes here
}
?>
Any suggestions what I am doing wrong? I assume the issue with the interface name would be resolved once the namespace issue is resolved. I have a feeling the problem might have something to do with the underlying library I am using to generate the classes. But, I want to get other's option to double check my work before I start searching for a better stub generation library.
Thanks.

Autoloading package that contains Class of same name as imported class

I have a project that includes a PHP file that defines a class named Response and I'm auto-loading Guzzle via composer (which also defines it's own Response class)
The question is do I run the risk that PHP might get confused as to which Response class it should use? If I use Response by itself I don't run the risk that it will somehow fetch the Guzzle class unless I do a use statement right?
I think it's fine unless I do the use statement but I just wanna be sure.
You don't have any risk of conflicts, that's why PHP Namespaces exist!
Although the short name of both classes are the same, their FQCN (Fully Qualified Class Name) are different, so there's no chance of getting confused.
Guzzle's Response class is:
\Guzzle\Http\Message\Response
Your class would be something like:
\MyApp\Response
(or just \Response if you didn't set a namespace for it, which is a very bad practise!)
You can use either of them in your classes, or even both, as long as you set an alias for one of them:
use \MyApp\Response;
use \Guzzle\Http\Message\Response as GuzzleResponse;
// ...
$myResponse = new Response();
$guzzleResponse = new GuzzleResponse();
As long as the classes got individual namespaces.
Composer (and its autolaoder) will resolve the namespace with the classname.
So if you use your own class ("Class1") and the foreign class ("Class2") with the same classname ("Classname") with different namespaces e.g.
namespace \Me\MyPackage\Classname
namespace \Guzzle\Classname
you will be fine. If you wanna create an instance of one of the classes just type the full qualified namespace e.g.
$var1 = new \Me\MyPackage\Classname();

PHP Namespaces & Referencing Classes not contained within Namespaces

I have a simple question, which should hopefully have a quick answer. The code I have written makes heavy use of namespaces (I use fully qualified names everywhere); however, a piece of code (a calendar / date picker control, not written by myself) needs to be included. When I attempt to create the control, it assumes the current namespace (GUI), resulting in this error: "PHP Fatal error: Class 'GUI\tc_calendar' not found in C:\inetpub\wwwroot\Calico\calico_classes_v2.php on line 1852". Now, the calendar control itself (and it's underlying class file) does not make use of namespaces, and I am a little worried about attempting to modify it (an earlier attempt did not go well).
How can I import / include a control, that is not contained within a namespace, into the rest of my code, that does? Does PHP have something like "Import class calendar from file AS \Calendar\Calendar"?
Edit:
For additional information: I have a class, called "tc_calendar", contained in a file called "tc_calendar.php". It is not part of any namespace.
In a separate file, I have several classes (Bitmap, CompositeCalendar, EventEditor, TimeExtractor), all contained within their appropriate namespaces (GUI, Data, Extract, etc.).
In one of those classes, CompositeCalendar, contained within the GUI namespace, I am trying to create an instance of a tc_calendar. However, PHP is throwing an error (above). tc_calendar is not a part of any namspace (and definitely not a part of the GUI namespace, which PHP is just assuming, because it can't seem to find it), and I need help creating an instance of it.
tldr; $newcontrol = new tc_calendar() doesn't work; PHP tries to guess the namespace for it (because one isn't specified, because tc_calendar isn't a part of any namespace), comes up with \GUI\tc_calendar (obviously wrong). How do I access a class, not contained within a namespace, from inside a namespace?
Do you mean something like this:
namespace GUI;
use \tc_calendar as Calendar;
$myCalendar = new Calendar();
The as Calendar is optional. You could aswell keep it with the original name tc_calendar if you ommit the as Calendar.
Update
To put it in shape of the comment:
namespace {
class tc_calendar {}
}
namespace GUI {
use \tc_calendar;
class CompositeCalendar {
private function blah() {
$control = new tc_calendar();
$control->stuff();
}
}
}
I wouldn't copy paste external libraries into he same file though. It bad practise. It is better to keep them in another file and then include them and have the following:
namespace GUI;
use \tc_calendar;
require_once 'tc_calendar.php';
class CompositeCalendar {
private function blah() {
$control = new tc_calendar();
$control->stuff();
}
}
Or combine my 3 snippets to have it any other form you like.
Also I would suggest to extend the calendar if you are just building calendar class based on the the tc_calendar:
namespace GUI;
use \tc_calendar;
require_once 'tc_calendar.php';
class CompositeCalendar extends tc_calendar {
private function blah() {
$this->stuff();
}
}
Any class not in a namespace is automatically in the global namespace.
To refer to anything in the global namespace from anywhere, use a single preceding \:
new \tc_calendar;

PHP: Instanciating namespaced classes

I can't get dynamic instantiating of classes in PHP to work when my files are namespaced.
PHP seems to be completely ignorant of the use keywords on top of my files, as I try to instantiate classes dynamically based upon the value of a variable.
Is there a good solution to this, besides hardcoding the namespace when dynamically instantiating classes?
Here's some quick samples to show what I mean:
Code new two('one'); results in that the class one isn't found with the below two files being included:
File1:
namespace uno;
use dos;
class one {
function __construct($what) {
new $what;
}
}
File2:
namespace dos;
class two { }
File 3:
new one('two'); // Doesn't work!
Either full-qualified
new \uno\one('two');
or defined by use
use uno\one;
new one('two');
or (relative) qualified (but that makes not much sense with a one-level namespace)
use uno;
new uno\one('two');
With deeper namespace it makes more sense
use path\to\myNamespace;
new myNamespace\foo\BarClass;
or put it in the same namespace
namespace uno;
new one('two');
See http://php.net/language.namespaces.rules

What is a namespace and how is it implemented in PHP?

I've heard the latest PHP has support for namespaces. I know variables defined in the global scope have no namespace, so how does one make a variable in a different namespace?
Is it just a way of categorising variables/functions?
Namespaces are a programming language mechanism for organizing variables, functions and classes. PHP 5.3 adds support for namespaces, which I'll demonstrate in the following example:
Say you would like to combine two projects which use the same class name User, but have different implementations of each:
// Code for Project One (proj1.php)
<?php
class User {
protected $userId;
public function getUserId() {
return $this->userId;
}
}
$user = new User;
echo $user->getUserId();
?>
// Code for Project Two (proj2.php)
<?php
class User {
public $user_id;
}
$user = new User;
echo $user->user_id;
?>
<?php
// Combine the two projects
require 'proj1.php';
require 'proj2.php'; // Naming collision!
$myUser = new User; // Which class to use?
?>
For versions of PHP less than 5.3, you would have to go through the trouble of changing the class name for all instances of the class User used by one of the projects to prevent a naming collision:
<?php
class ProjectOne_User {
// ...
}
$user = new ProjectOne_User; // Code in Project One has to be changed too
?>
For versions of PHP greater than or equal to 5.3, you can use namespaces when creating a project, by adding a namespace declaration:
<?php
// Code for Project One (proj1.php)
namespace ProjectOne;
class User {
// ...
}
$user = new User;
?>
<?php
// Combine the two projects
require 'proj1.php';
use ProjectOne as One; // Declare namespace to use
require 'proj2.php' // No collision!
$user = new \One\User; // State which version of User class to use (using fully qualified namespace)
echo $user->user_id; // Use ProjectOne implementation
?>
For more information:
PHP.net Namespaces
PHP Namespaces
A namespace allows you to organize code and gives you a way to encapsulate your items.
You can visualize namespaces as a file system uses directories to group related files.
Basically namespaces provide you a way in which to group related classes, functions and constants.
They also help to avoid name collisions between your PHP classes/functions/constants, and improve the code readability, avoiding extra-long class names.
Example namespace declaration:
<?php
namespace MyProject;
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
?>
Namespaces solve the problem of naming collisions when importing classes and functions from libraries.
Without namespaces, if you include two libraries which happen to define a function/class with the same name (ie, two libraries that both include a class called 'user'), it will fail.
With no namespace support in PHP, most libraries have taken to prefixing their function/class names with something that is likely to be unique, in an attempt to avoid name collisions. The trouble is, this creates longer function or class names.
The example given here is of the exception class:
PEAR_Form_Loader_Validate_Table_Element_Validator_Exception.
You can import from a long namespace into your own local scope as an alias using the 'AS' keyword - a name you choose. Thus, you can still have a short class name of your choice in your local scope.
The following applies an 'alias' called DbConnection to Zend::DB::Connection.
use Zend::DB::Connection as DbConnection
Namespaces are often used with libraries, the ability to reference the library code with 1 single namespace helps to not clobber up others that are already being used.

Categories