Php multi level inheritance best practice [closed] - php

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 20 days ago.
Improve this question
During some workaround with some architecture I faced a question and I am wondering if this implementation follows best practice or not.
Here we have a base abstract class:
abstract class A {
protected mixed $object;
public function __construct() {
$this->loadObject()
->fuc1();
}
abstract protected function loadObject(): self;
abstract public function fuc1(): bool;
abstract public function fuc3(): iterable;
}
In this case, I want to implement Class B and C. if I create each class separately everything is fine but as far as these 2 classes have the same functions I decided to create a base class for them (BC) so codes are now like this:
class BC extends A {
protected string x;
protected string y;
protected function loadObject(): self {
throw new \Exception('Child must implement loeadObject');
}
public function fuc1(): bool {
//Some Codes
}
public function fuc3(): iterable {
//Some Codes
}
}
And Class B and Class C are like this:
class B extends BC {
protected function loadObject(): self {
$this->object = new SomeObject();
return $this;
}
}
class C extends BC {
protected function loadObject(): self {
$this->object = new SomeObject2();
return $this;
}
}
We also can not move loadObject function to class BC cuz maybe class D wants to inherit directly from class A.
We can also rely on interfaces but I was wondering if some one forget to make class B/C implement an Interface then we will have problem in class A.
So is it a good practice that we throw exceptions in the class BC and force other developers to don't forget to overwrite the loadObject function?

This is not a good practice, if you doesn't need to implement the loadObject method in the BC class, you should keep it abstract.
abstract class BC extends A {
protected string $x;
protected string $y;
public function fuc1(): bool {
}
public function fuc3(): iterable {
}
}

Related

Slug solution for a DDD entity [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 20 days ago.
Improve this question
I consider a slug property not being a part of my domain model. It's just a nice convenience for the view layer.
But still: I don't want to calculate it each time I retrieve it to the view.
So I decide to only define a private property with a getter on entities which eventually will be retrieved via an URL - through a Sluggable contract. The constructor doesn't touch it all. I delegate the slug's creation to an Infrastructure Service. The ORM deals with entities using reflections, so my solution kind of looks like how Doctrine would touch those.
I register the event lifecycle listener as a Symfony service.
<?php
namespace App\Common\Domain\Model;
interface Sluggable
{
public function slug();
}
<?php
namespace IMS\Registry\Domain\Model\Manufacturer;
use App\Common\Domain\Model\Sluggable;
class Manufacturer implements Sluggable
{
private ManufacturerId $id;
private ManufacturerName $name;
private string $slug;
public function __construct(ManufacturerId $anId, ManufacturerName $aName)
{
$this->id = $anId;
$this->name = $aName;
}
public function name(): ManufacturerName
{
return $this->name;
}
public function slug(): string
{
return $this->slug;
}
// other methods
}
<?php
namespace App\Common\Infrastructure\Domain\Model;
use App\Common\Domain\Model\Sluggable;
use Cocur\Slugify\SlugifyInterface;
use Doctrine\Persistence\Event\LifecycleEventArgs;
class NameSlugger
{
public function __construct(private readonly SlugifyInterface $slugger)
{
}
public function prePersist(LifecycleEventArgs $args): void
{
$this->preSlugged($args);
}
public function preUpdate(LifecycleEventArgs $args): void
{
$this->preSlugged($args);
}
private function preSlugged(LifecycleEventArgs $args): void
{
$entity = $args->getObject();
if (!$entity instanceof Sluggable) {
return;
}
$reflection = $args->getObjectManager()->getClassMetadata($entity::class)->getReflectionClass();
if (!$reflection->hasProperty('slug')) {
throw new \ReflectionException();
}
$reflectionProperty = $reflection->getProperty('slug');
if (!$reflectionProperty->hasType()) {
throw new \ReflectionException();
}
$reflectionPropertyType = $reflectionProperty->getType()->getName();
if ('string' !== $reflectionPropertyType) {
throw new \ReflectionException();
}
$reflectionProperty->setValue(
$entity,
// ManufacturerName VO has a __toString method
$this->slugger->slugify($entity->name())
);
}
}
My question is: is my reasoning valid in your opinion? From a DDD perspective. What different approach would you incorporate so it fits the DDD concept of a project?

How to structure PHP classes [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
In file A,
Class A {
__construct() {
...
lots of code
...
}
public function P() {
code here
}
}
New A();
In file B,
Class B {
__construct() {
...
lots of code
...
}
public function E() {
I need to call function P in Class A
}
}
New B();
I would like to call the function P() in function E().
Is there any way to call a function in another class?
I found several ways such as dependency injection using __construct( A $aobj ) or "extends"
However, the class A was already instantiated in file A and there're a lot of things in __counstruct so I would like to know
1) the way of refractory technique
2) fancy way to call function E() in function P().
It really depends on how class B is related to A :
no link : the function in A should be static (it doesn't interact with a specific instance of A and its properties), and you can call A::P()
the class B is a child of A :
In B class definition, you have a class B extends A and in the constructor of B, you will have a parent::__construct() to call the constructor of A.
Then you can simply call $this->P() : as B is a subclass of A, and P is public (or protected), B inherits of all methods from A
The class B uses a object of type A`
Then, you must have a $a attribute in the class B, and a $this->a = new A(); in the constructor of B. You can call P with $this->a->P();
Or if you need only temporarily A in E(), you can construct a new object $a = new A(); and call $a->P(); in the code of E
Let's say that we have file a.php which contains class A:
class A {
public function __construct()
{
}
public function P()
{
echo "It is function P";
}
}
And file b.php which contains class B, in file b.php we first include a.php
include('a.php');
class B {
private $aobj;
public function __construct(){
$this->aobj = new A();
}
public function E(){
$this->aobj->P();
}
}
$b = new B();
$b->E();
Now open the browser and http://localhost/your-project/b.php and see the result.

Call all classes that implement an interface [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have the following code in place.
Interface Vehicle which has a method calculateDistance.
Class Car implements Vehicle
Class Bicycle implements Vehicle
Class MotorCycle implements Vehicle
What I want to do next is a method in my controller that calls every class that implements Vehicle and get the values from calculateDistance.
What would be the best way/design pattern to achieve this?
At this moment I am just calling all the classes that implement the interface Vehicle (via ReflectionClass) and loop over them to call this method.
The best way is to implement CompilerPass. Here is an example .
So, create a registry class (TransportChain class in that example), interface, and all classes that implements that interface, define them as services and give them tag name.
After that, you can call that registry service in your action, and call your desired method by each service.
Basic example:
interface
interface SomeInterface {
public function doSomething();
}
Service 1:
class First implement SomeInterface {
public function doSomething() {
// do smth
}
}
Service 2:
class Second implement SomeInterface {
public function doSomething() {
// do smth
}
}
Registry class:
class MyRegistry
{
private $services = [];
public function addMyService($service)
{
$this->services[] = $service;
}
public function all()
{
return $this->services;
}
}
CompilerPass:
...
$myServices = $container->findTaggedServiceIds('my_tag');
if (empty($myServices)) {
return;
}
$registry = $container->getDefinition('my_registry');
foreach ($myServices as $key => $myService) {
$registry->addMethodCall('add', [new Reference($key)]);
}
...
After clearign the cache, you can call them in your action:
...
foreach ($this->get('my_registry')->all() as $myService) {
$myService->doSomething();
}
...
The whole other stuff, like declaring services, give them tag name, registering your compiler pass has been written here.

Yii: What is signature of behaviors? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
what is signature of behaviors in yii? should this be a function or a class method?
Can any provide sample code?
There is no signature for behaviors, as behaviors are intented to add some function to class. Only requirement is to extend from CBehavior. Like in wiki or docs:
class SomeClass extends CBehavior
{
public function add($x, $y) { return $x + $y; }
}
class Test extends CComponent
{
public $blah;
}
$test = new Test();
// Attach behavior
$test->attachbehavior('blah', new SomeClass);
// Now you can call `add` on class Test
$test->add(2, 5);
However since PHP 5.4 you can use Traits which are native php implementation and have a lot more features, example above with traits:
// NOTE: No need to extend from any base class
trait SomeClass
{
public function add($x, $y) { return $x + $y; }
}
class Test extends CComponent
{
// Will additionally use methods and properties from SomeClass
use SomeClass;
public $blah;
}
$test = new Test();
// You can call `add` on class Test because of `use SomeClass;`
$test->add(2, 5);
There are a lot more features with traits

see variable from other class php [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
It's possible to do this if the class B NOT extended the class A but the class A call a new class B
class A{
public $lang;
public function __construct($lang) {
$this->lang=$lang;
}
public function new_B(){
return new B();
}
}
class B{
public function __construct() {
echo 'lang='.A::$lang;
}
}
$root=new A('eng');
$root->new_B();
You seem to have a mixup of concepts here. The $lang property of A is an instance level variable (since it is not defined as static), therefore you cannot access it statically as you are trying to. If you were to declare the variable as static then you would have access to it, but if you have multiple instances of class A that change it, it will change on the class level, rather than instance level.
Is A::$lang common to all A objects you will create? Then make this variable static. If not you can pass A::$lang as parameter to the B constructor. That is
class A{
public $lang;
public function __construct($lang) {
$this->lang=$lang;
}
public function new_B(){
return new B($this->lang);
}
}
class B{
public function __construct($lang) {
echo 'lang='.$lang;
}
}
Following is making A::$lang static:
class A{
public static $lang;
public function __construct($lang) {
self::$lang=$lang;
}
public function new_B(){
return new B();
}
}
class B{
public function __construct() {
echo 'lang='.A::$lang;
}
}
change the class B like this:
class B extends A{
public function __construct() {
echo 'lang='.$this->$lang; // you can use parent variables like this
}
}

Categories