How do I remove entities in Doctrine 2? I want to know how to do this through the command line and with PHP. Thanks!
Edit:
I'm not sure if I'm asking this question right (I'm new to Doctrine). I want to leave the Entity file in the directory, but I want to delete its table from the database. This stems from Zend based modular architecture where modules can be installed/uninstalled without the module directory being removed. If a module is uninstalled, I want its entities removed. The opposite is also true.
As far as I know, there is no way to do this. You have to manually remove associated database tables.
You can just remove \ORM annotation from entity if you want to exclude it from entity generation process.
I did some looking into Doctrine's API and eventually figured it out:
$classes = array();
$entityManager = ...
$classes[] = $entityManager->getClassMetadata('Entities\MyEntity1');
$classes[] = $entityManager->getClassMetadata('Entities\MyEntity2');
$classes[] = $entityManager->getClassMetadata('Entities\MyEntity3');
$classes[] = $entityManager->getClassMetadata('Entities\MyEntity4');
//Doctrine Schema Tool
$st = new Doctrine\ORM\Tools\SchemaTool( $entityManager );
$st->dropSchema($classes);
This will remove the tables associated with Entities\MyEntity1, 2, 3 and 4 from the database.
Also, using the exact same code above except the last line, the following methods are useful:
$st->createSchema($classes);
AND
$st->updateSchema($classes);
You can find all the info in Doctrine's documentation:
http://www.doctrine-project.org/projects/orm/2.0/api
Related
Without scrutinizing why I want this (it may sound like a bad approach, but I have good reason) I want to know if there is a way in the standard-framework-edition 3.1+ to create a relational association to an entity that may not exist...
Firstly I do realize this determines the schema and that's fine. So if an entity does not exist, it doesn't create a foreign key and the field is always null, or if the target entity does exist, it creates the foreign key and the field works like a normal association...
Secondly, this only changes project to project, and may change down the line as an update to which I realize a manual schema update could be necessary.
Preferably without 3rd party bundle dependencies... hoping for the standard framework to do this,
Anybody?
Thanks in advance
Edit
I am using annotations in my entities with doctrine ORM
Furthermore
The simplest version of why I am doing this is because certain bundles are optional project-to-project, and bundle A may make use of entities in bundle B only if it is present. I have considered using services and if container->has then container->get, or the XML on-invalid="null" approach, but that doesn't address property persistence. I was happy with storing a non-mapped value as a custom relational field, which is fine, just lengthier and wondered if perhaps there was a way Doctrine could ignore a missing targetEntity...
Hm, perhaps I misunderstand your question, but this sounds like a normal 'nullable' association to me?
Create your assocation via annotation:
/**
*
* #var Child
* #ORM\ManyToOne(targetEntity="Child")
*/
private $child;
and use
setChild(Child $child = null)
{
$this->child = $child;
}
as a Setter to allow nullable values.
And your getter might look like:
getChild()
{
return $this->child;
}
In case there isn't any child it will return null.
I will keep the other answer as it responds to the question for a 'nullable association target' live data.
This is the answer for a 'nullable association target' meta data which is a different thing.
OP asks to provide a targetEntity in the metadata which cannot exist in his case, e.g. is not there in a different bundle (or whatever OP's mysterious reason might be).
In that case I recommend to build upon Doctrine's TargetEntityListener which is able to resolve the targetEntity during runtime and targetEntity can be set to an Abstract Class or an Interface:
/**
* #ORM\ManyToOne(targetEntity="Acme\InvoiceBundle\Model\InvoiceSubjectInterface")
* #var InvoiceSubjectInterface
*/
protected $subject;
InvoiceSubjectInterface will then be replaced during runtime by a specific class provided by config e.g.:
# app/config/config.yml
doctrine:
# ...
orm:
# ...
resolve_target_entities:
Acme\InvoiceBundle\Model\InvoiceSubjectInterface: AppBundle\Entity\Customer
So this should be eiter an extendable behaviour for providing no class or implementing an own solution.
I'm using this official tutorial to generate entityies from database, all works well except db column comments they are totally missing.
When i run this mapping import command in xml i see column comment
php bin/console doctrine:mapping:import --force AcmeBlogBundle xml
right after running
php bin/console doctrine:mapping:convert annotation ./src
when i open Entity/SomeTable.php some_column (which had comment in database) dose not have options={"comment":"some comment"} in annotation
So do i miss some option for convert command or it is bug of doctrine/symfony and is there a solution for this ?
Note: i have tested this with both symfony2 and symfony3 issue is same
Currently there is no option that will convert your comments and add it to the entity class. The Entity geneartion can be seen in the DoctrineBundle of Symfony in the class Doctrine\ORM\Tools\EntityGenerator this class says it all:
Generic class used to generate PHP5 entity classes from ClassMetadataInfo instances.
So in easy words the mapping you create in xml is then read as ClassMetadataInfo and the EntityGenerator generates the entity class from that ClassMetadataInfo. If you want you can try to add an implementation for the comment or propose a PR or bug in the symfony git repository.
See generateFieldMappingPropertyDocBlock method of the Doctrine\ORM\Tools\EntityGenerator class and see if you can manage to understand the code and add your comment from there.
Based on #SimeonKolev answer i was able to implement simple fix for this issue in doctrine/orm/lib/Doctrine/ORM/Tools/EntityGenerator.php to have options={"comment"=".."} filled in each Entity
Solution was add in EntityGenerator.php method generateFieldMappingPropertyDocBlock before if (isset($fieldMapping['unsigned']) ... condition near to ~1652 line
if( isset($fieldMapping['options']) && is_array($fieldMapping['options'])
&& isset($fieldMapping['options']['comment']) ){
$column[] = 'options={"comment"="'.$fieldMapping['options']['comment'].'"}';
}
It is straightforward to ignore tables when your schema format is :ruby, but is there a way to do it when your schema format is :sql?
Ideally something like this in environment.rb:
ActiveRecord::SQLDumper.ignore_tables = ['table_name']
After a quick perusal through the AR source code it looks unpromising.
There is currently no way to do this, when the schema format is set to :sql, Rails doesn't go through the regular SchemaDumper but instead uses the tasks in ActiveRecord::Tasks::PostgreSQLDatabaseTasks to do the dump, check it out here.
The code is quite straightforward. I came up with a simple patch for ActiveRecord that should work as expected. It relies on setting the tables to ignore in your database.yml file. It basically adds the following code:
ignore_tables = configuration['ignore_tables']
unless ignore_tables.blank?
args += ignore_tables.split(',').map do |table|
"-T #{table}"
end
end
I just submitted a pull request to rails with those changes. In case you'd want to test it.
For the sake of people landing here after Googling this problem in 2022: As of this PR the structure.sql dump should respect the ignore_tables configuration of ActiveRecord::SchemaDumper. If you're using a regular schema.rb, this option can be a mix of strings and regexes; However, if you're using a structure.sql, it will only take strings according to the docs.
In any case, you can add an initializer to modify the list of ignored tables however you need. In my case, I have a number of backup tables that are created when certain risky operations are performed, and I'd like to exclude those from the structure.sql. Adding this initializer solved it for me:
# config/initializers/ignore_tables.rb
backup_tables = ActiveRecord::Base.connection.tables.select do |t|
t.match?(/_backup_.*$/)
end
ActiveRecord::SchemaDumper.ignore_tables += backup_tables
So I'm working on some unit tests and relational fixtures.
I'm creating a model dynamically like:
$model = CActiveRecord::model('Post');
$post = $model->findByPk(1);
But after that I cannot for some reason get $post->id. I traced the problem to CActiveRecord class:
public function __get($name)
{
if(isset($this->_attributes[$name]))
return $this->_attributes[$name];
...
Where $name = "id". It says that $this->_attributes[$name] does not exist! As a matter of fact _attributes is empty.
My Post class does not define id (or any other properties) as a public property and I don't want to do so either. I just let the AR map it to table columns for me.
What am I missing?
Edit 1
My fixtures are regular Yii fixtures - nothing really special about them.
What differs is the way I load them really. I extended the CDbFixtureManager to be able to specify the order in which they should be loaded by overloading load() method. Only thing of interest that actually fails is that in the fixtures that have foreign keys I use the following:
'comment1' => array('post_id' => $this->getRecord('Post', 'post1')->id);
That's where it fails. getRecord returns the actual Post record (since I know the Post fixture has already been successfully loaded and exists in DB), but on the ->id part I get an exception about that attribute not existing.
If I go into Post model and add public $id; to it, then everything works! But I'm not sure if it's good practice to go about declaring all properties public like that.
If you look at this page carefully:
http://www.yiiframework.com/doc/guide/1.1/en/test.unit
you'll see that they use an array form for retrieving fixtures:
$this->posts['sample1']['id']
There is an alias defined in their fixture array for each record and fixture items aren't loaded as models really ...
Does that help? If not, it would be helpful to see your fixture file :-)
I think I found the root cause of this issue for me. While my FixtureManager was using the testdb DBConnection, the models still used the regular one.
For whatever reason, my debugger was giving me misleading errors like the one described in my original post.
Once I was able to set the DBConnection of all Models in the unit test the puzzle snapped into place and everything is now working smoothly!
Is it possible to use SubSonic 3's Simple Repository with non-plural table names? My DB already exists, the table names a re singular add I cannot change them.
Nope, it is hardcoded in the SubSonic's source. You can pull it down and trace the migration steps to see where the plural happens. I know, cause I wanted the same thing.
I was tinkering with modifying the source to make plurals optional via some parameter/config override or alike. But, I didn't get it completed (yet).
If your tables already exist then this is not the intended use of the Simple Repository model. The simple repository model is designed to generate the table structures for you using migrations.
If you are using a database that already exists then you would be better served using the T4 Templates as they also support the relationships between your tables.
Cheers,
Ed
With Subsonic 3.0.0.4 in the settings.ttinclude I removed the line;
AddSingularRule("s$", String.Empty);
which was down about 260 lines in the Inflector rules class. Didn't need to mess around with the subsonic source code.
HTH