I have imported a PHP source folder into Enterprise Architect. Now, I'd like to see the inheritance chain of any specific class. In other words, I'd like to see one big diagram displaying all relations of a class. Most classes are in folders separate from the parent/child class. How can I do that..?
This was my reason for installing Enterprise Architect: I get confused within a lengthy and branched inheritance chain. It would be very disappointing if such a powerful tool that recognizes all relationships could not give an overview of these relationships.
For example, I can see a class diagram in the root of one folder, illustrating aggregation. However, the aggregated classes listed are only those located in the same folder as the parent class.
Thank you in advance.
This answer applies to EA 9.3. I don't have an old EA 8 lying around but EA is eminently backwards-compatible, so you should upgrade in any case.
There are a couple of ways to follow inheritance chains in EA.
Method 1: add classes to the same diagram.
In a diagram containing the root class of your inheritance hierarchy, right-click the root class and select Add - Related Elements. In the "Insert Related Elements" dialog, select the length of chain ("levels") you want, up to a maximum of 5. Specify "link type" Generalization. You can leave the other options as they are, or play around with them if you like.
This will cause EA to add those classes to the diagram which inherit from the root class in up to 5 steps/levels. You don't have to start from a root class; the option "link direction" in the dialog controls whether relationships should be followed in one or both directions.
You can use this same function to add classes related through other relationships, such as aggregations.
Method 2: Use the Traceability window.
In the main menu, select View - Traceability. This opens the Traceability window, which is a tree view with the currenty selected element at the top, and nodes for all related elements in a hierarchy.
Select the root class and violà, all its inheriting classes are shown as child nodes in the Traceability window, and you can expand them in turn to follow the chains further.
Method 1 puts the information in diagrams, where it is kept and needs to be updated. Method 2 is dynamic and more usefu when you need to check a specific relationship chain.
The relationships in a diagram are automatically updated if the underlying model changes, so if for instance you change the code and reimport it, this will be reflected in the diagram. To be on the safe side, always work with manually created diagrams in a separate package from the source package.
Am not sure if there is existing solution but is something you can easily implement using ReflectionClass and Google Graph
Example
class A {
}
class B extends A {
}
class C extends B {
}
class D extends C {
}
class E extends D {
}
class F extends E {
}
function getPath($className) {
$class = new ReflectionClass($className);
$name = $class->getParentClass();
if ($name) {
echo $class->getName(), " extends ";
getPath($name->getName());
} else {
echo $class->getName();
}
}
getPath("C");
getPath("F");
Output
C extends B extends A
F extends E extends D extends C extends B extends A
Related
Let's take the following class structure:
class A {
... has all the functionalities of A
}
class B extends A {
... has all the functionalities of A and B
}
And these two other class structures:
class C extends B {
... has all the functionalities of A and B and C
}
class D extends A {
... all the functionalities of A, and D
}
how could I create a class easily, that would gain all the functionalities of all four of my classes, if I am not allowed to modify class A or class B? Would something like this be possible with PHP?
EDIT:
The reason I would like to do this is the following, I am open for suggestions on other ways my desired outcome can be achieved:
I have a module, which has several classes on which I plan to build on, and I do not want to edit the module directly, but I would like to add functionalities potentially to multiple classes of this module (this is where class A and class B is coming from).
So to edit class A, I would create a class D, which extends it, and add new functionalities, or rewrite already added functionalities that needs rewrite in class D.
But there are multiple classes in this module, which are simmilar in structure to class B, which I would also like to potentially modify, hence my class C. But if I modified the modules class A in my class D, I would need my new class C to extend the class D instead of the class A. (hope you can still follow me:P)
No, in PHP it is not possible to inherit from multiple parents due to "Dimond Problem". In your case, this means you can extend c for the functionality of a, b & c, but you cannot extend d too. Since you cannot modify the other classes, there is not right solution here, but I'd recommend looking into traits (https://www.php.net/manual/en/language.oop5.traits.php), as these allow you to 'inherit' from multiple traits.
As it is described thoroughly in the propel documentation, propel generates a base class, e.g., Base\Foo that is extended by an individual class Foo. The same applies to another another table, e.g., Base\Bar and Bar respectively. I could add the necessary attributes/methods to the Base classes but they can be regenerated. By using a middle-class
class Foo extends MyClass {}
class MyClass extends Base\Foo
{
//must be created for each Foo, Bar, Buzz,
//they must extend Base/Foo, Base/Bar, Base/Buzz respectively
}
What is the best way (in terms of propel) to have the single extendible class? Should behaviours be used?
I've been trying to build a PDO extension, and I wanted to have special classes in different files but I wanted to have them all link to the same original class.
I have worked with some Frameworks and I see that they use the extends class keyword, and I thought that it added the class you are making to the class that you have given.
Some code I have tried is:
class PSMQuery extends PSM {
// Functions and Jargon
}
I tried making an object for the original PSM class:
$psm = new PSM(/*Information*/);
But when I call the $psm variable like $psm->functionInTheExtendedClass it comes up with an error saying that it was an undefined method when I called it.
Am I using the extends keyword incorrectly?
Am I using the extends keyword incorrectly?
You use it correctly, but it works the other way around.
If PSMQuery extends from PSM, this means you can access and use stuff from PSM in PSMQuery, but not the other way around.
I think to understand it you can use a good example:
class twoRoomApartment extends building { }
So now you can think logical and already see, that a two room apartment probably extends from a building and not the other way around.
Means now in your code, you just create an instance of PSMQuery.
It's inheritance.
Parent : PSM
Child : PSMQuery
When you use extends you are extending parent class functionality and creating child class.
Your child class will inherit all the parent class functionality.
Parent will not get child class functionality.
So when u r trying to create object of parent class it doesn't know child class functionality.
You need to create object of child class and then you can access methods from parent class.
I've separated my models from my entities. I have three models with corresponding entities: Review, RatedReview, and ScoredReview. Their relationship is ScoredReview extends RatedReview extends Review.
So for my models I have:
// Project/ReviewBundle/Model/Review.php
class Review
{
}
// Project/ReviewBundle/Model/RatedReview.php
class RatedReview extends Review
{
}
// Project/ReviewBundle/Model/ScoredReview.php
class ScoredReview extends RatedReview
{
}
Then I implement the entities by extending the models, like so:
// Project/ReviewBundle/Entity/Review.php
use Project\ReviewBundle\Model\Review as BaseReview;
class Review extends BaseReview
{
}
// Project/ReviewBundle/Entity/RatedReview.php
use Project\ReviewBundle\Model\RatedReview as BaseRatedReview;
class RatedReview extends BaseRatedReview
{
}
// Project/ReviewBundle/Entity/ScoredReview.php
use Project\ReviewBundle\Model\ScoredReview as BaseScoredReview;
class ScoredReview extends BaseScoredReview
{
}
So the inheritance is happening on the model side. Doctrine can't seem to see this, and maps them to separate tables. I understand this is because Doctrine only looks for entities extending other entities, not entities extending models.
Is there a better way for me to separate the models from the entities, while retaining the ability to extend entities? Is this where traits come in handy?
Put another way, is there anyway that I can have a tree made of models, and a tree made of entities that extends those models?
I've come up with a solution for this issue, and it does involve traits.
What I'm doing is basically trying to create several variations of a table. The relationship between the reviews is more horizontal than vertical (One type of review might have ratings, another one a video, another both). Traits are apparently perfect for horizontal relationships, so instead of creating models for each variation, I create traits.
So now my "models" look like this:
// Project/ReviewBundle/Entity/Review.php
use Project\ReviewBundle\Model\Review as BaseReview;
class Review extends BaseReview
{
}
// Project/ReviewBundle/Entity/RatedReviewTrait.php
trait RatedReviewTrait
{
}
// Project/ReviewBundle/Entity/ScoredReviewTrait.php
trait ScoredReviewTrait
{
}
And my entities look like this:
// Project/ReviewBundle/Entity/Review.php
use Project\ReviewBundle\Model\Review as BaseReview;
class Review extends BaseReview
{
}
// Project/ReviewBundle/Entity/RatedReview.php
use Project\ReviewBundle\Model\RatedReviewTrait;
class RatedReview extends Review
{
use RatedReviewTrait;
}
// Project/ReviewBundle/Entity/ScoredReview.php
use Project\ReviewBundle\Model\RatedReviewTrait;
use Project\ReviewBundle\Model\ScoredReviewTrait;
class ScoredReview extends Review
{
use RatedReviewTrait;
use ScoredReviewTrait;
}
My models stay separated from my entities and as a bonus I decouple the variations from each other – pretty awesome. The only issue I see is that this requires PHP >= 5.4.
my models in CI are set up so that they load "sub"-models whenever they need certain functions. In order to keep my code as accessible and clean as possible, I want those submodels to extend the model they are called to.
So if I have two models:
<?php
class Mymodel extends Model
{
}
And:
<?php
class Submodel extends Model
{
function test() { do something.. }
}
Then I need to, somehow, be able get the submodel to extend mymodel, so that I can do something like $this->mymodel->test(). It doesn't have to be mymodel that submodel extends, it could be any model. Any ideas?
Thanks for your time.
You have an incorrect understanding of inheritance between classes.
Inheritance only flows one way, Down.
if Myodel extends Submodel your $this->mymodel->test() would work, but it does not make sense as sub (child) objects are suppose to inherit from parent objects, not the other way around.
As an analogy, you wouldn't look at a child and tell the parent, "You look just like your child", because it is the child that is a part representation of the parent.
you need to take the word extends very literally, you are literally 'extending' the functionality of the parent.
===================
One way i believe you could accomplish this is to create ghost functions that simply load the proper model and call that models function (though I do not recommend this as it could get very confusing for debugging.
per your example
<?php
class Mymodel extends Model
{
function test() {
$this->load->model('submodel');
$this->submodel->test();
}
}
Submodel
<?php
class Submodel extends Model
{
function test() { do something.. }
}
BUT again, if you are going for clean code, this is NOT the way to go, try and observe inheritance, and design your data with that in mind.
You can create utility model which may extends codeigniter's model and then all your models can extend that utility model. The methods you are going to add to the utility model will be available to all it's child classes aka your models.
How can you call a method which your class does not have or does not inherit from any other classes? Looking at your code, there is no relationship in your classes between Mymodel and Submodel.