I wrote these two classes that simple encrypt and decrypt strings:
Encode.php
class Encode {
protected funcion do_encode($string) { .. }
}
Decode.php
class Decode {
protected funcion do_decode($string) { .. }
}
What I would like to do is:
Encrypt.php
class Encrypt extends Encode, Decode {
protected $stuff_for_parents;
function __construct($configs) {
$this->stuff_for_parents = $configs['SomeConf'];
}
public function encode($string) { $this->do_encode($string); }
public function decode($string) { $this->do_decode($string); }
}
But we cannot include more than one class, so: fail.
Now my questions are:
Is it a design problem? Cause this scenario doesn't look weird to me, does it?
Is there another way to have one object that uses both the functions in the different classes? Sort of $encrypt->encode($str); $encrypt->decode($str);
If you want Encode and Decode to be separate classes, you can create instances of them within Encrypt. For example:
<?
class Encrypt {
private $encoder;
private $decoder;
public function __construct() {
$this->encoder = new Encode();
$this->decoder = new Decode();
}
public function encode($string) {
return $this->encoder->encode($string);
}
public function decode($string) {
return $this->decoder->decode($string);
}
}
?>
In that example Encode and Decode must be concrete classes. But you might want to consider using interfaces instead. Interfaces are useful if you think you might need to use different types of Encode and Decode objects, in different situations. For example, maybe you have a TripleDESEncode class and a BlowfishEncode class. They can both implement a common interface, like this:
<?
interface IEncode {
public function encode($string);
}
class TripleDESEncode implements IEncode {
public function encode($string) {...}
}
class BlowfishEncode implements IEncode {
public function encode($string) {...}
}
?>
In that case, you may want to create the particular instances you want to use first, and then pass them into the constructor of Encrypt. This is called dependency injection:
<?
class Encrypt {
public function __construct(IEncode $encoder, IDecode $decoder) {
$this->encoder = $encoder;
$this->decoder = $decoder;
}
...
}
$myEncrypt = new Encrypt(new BlowfishEncode(), new BlowfishDecode());
echo $myEncrypt->encode('test');
?>
There is nothing wrong with encapsulating your algorithms in separate classes (in fact it is good practice if you would like the flexibility to change these, especially at runtime), however, what you probably want is composition rather than inheritance:
class Encrypt {
private $encoder;
private $decoder;
protected $stuff_for_parents;
function __construct($configs, $encoder, $decoder) {
$this->stuff_for_parents = $configs['SomeConf'];
$this->encoder = $encoder;
$this->decoder = $decoder;
}
public function encode($string) { $this->encoder->do_encode($string); }
public function decode($string) { $this->decoder->do_decode($string); }
}
I think you should just creat two methods/functions in Encryption class. It is very logical.
It does make sense but it can be done in the way allowed by programming languages. Encoding decoding are different functions that encryption class should perform so these should be methods.
I would write is somthing like:
class Encrypt
{
protected $stuff_for_parents;
function __construct($configs) {
$this->stuff_for_parents = $configs['SomeConf'];
}
protected funcion encode($string)
{
}
protected funcion decode($string)
{
}
}
Related
Unfortunately I'm stuck here.
Consider the following rudimentary examples:
interface ChargeInterface
{
public function charge($amount);
}
class BraintreeCharge implements ChargeInterface
{
public function charge($amount)
{
// braintree logic here
}
}
class StripeCharge implements ChargeInterface
{
public function charge($amount)
{
// stripe logic here
}
}
So there's an interface for charging a payment method, and there are, in this example, two concrete classes which implement the interface.
I'd like to be able to decide on runtime which implementation should be used. So I thought I'd achieve this with custom factory classes:
class PaymentFactory
{
public static $implementation;
public static function charge()
{
return $implementation::charge();
}
}
class StripeFactory
{
public static function charge()
{
return new StripeCharge();
}
}
class BraintreeFactory
{
public static function charge()
{
return new BraintreeCharge();
}
}
Than I could just use the factories:
PaymentFactory::$implemention = StripeFactory::class;
$payments = PaymentFactory::charge();
$payments->charge(100);
Another idea was to use a singleton based logic:
class PaymentFactory extends Singleton
{
protected $implementation;
// Singleton logic missing in this example
public function useImplementation($class)
{
$this->implementation = $class;
}
public function getImplementation()
{
return $this->implementation;
}
public static function charge()
{
$instance = self::getInstance();
return new $instance->getImplementation();
}
}
Later ...
PaymentFactory::getInstance()->useImplementation(StripeCharge::class);
$payments = PaymentFactory::charge();
$payments->charge(100);
Do you've any suggestions regarding best practices here?
I think I'd favour the first one, since the real implementation consists of more than just one class per package, as outlined in the example.
Also it seems to me, this would be the more cleaner way.
I would like some feedback on my coding approach (i.e., whether it is appropriate or whether what I have done can be done in a perhaps better way):
I would like to create an interface to document that a constructor should have a specific format. Of course, if the interface only contains a constructor (and I was even surprised that PHP lets you put a constructor in an interface), the interface will have no effect (except for possibly documentation). Besides, PHP does not enforce the parameters of any callable to match, neither in number nor in type, and this is true of functions, methods, and constructors alike.
If you see how I have named my classes, you will realize what I am trying to do (: document that the constructor parameter must be a messager instance, too bad I could not do more to enforce this). Please let me know if my approach is OK and whether I can improve it.
class Messenger {
private $message;
function __construct($message = "Hello!") {
$this->message = $message;
}
public function getMessage() {
return $this->message;
}
}
With the above simple class in mind, I want to create an interface such as the following, but since we're dealing with a PHP constructor this should be useless?
interface MessengerAware {
function __construct($messenger);
}
class MessengerKnower implements MessengerAware {
private $messenger;
function __construct($messenger) {
$this->messenger = $messenger;
}
public function displayMessengerMessage() {
echo $this->messenger->getMessage();
}
}
I then want to enforce my interface in a class called Runner such as the following:
class Runner {
private $messengerAware;
function __construct($messengerAware) {
if (!is_a($messengerAware, 'MessengerAware')) {
die("I'm expecting an instance implementing the MessengerAware interface.");
}
$this->messengerAware = $messengerAware;
}
public function run() {
echo "I'm running.\n";
$this->messengerAware->displayMessengerMessage();
}
}
and finally run this code:
$messengerAware = new MessengerKnower(new Messenger());
$runner = new Runner($messengerAware);
$runner->run();
OUTPUT:
I'm running.
Hello!
Perhaps it's not possible, but the problem could be worked around using one (or more) factory methods:
Leave this unchanged:
class Messenger {
private $message;
function __construct($message = "Hello!") {
$this->message = $message;
}
public function getMessage() {
return $this->message;
}
}
This modification...
interface MessengerAware {
public static function create($messenger);
public function displayMessengerMessage();
}
and this one...
class MessengerKnower implements MessengerAware {
private $messenger;
public static function create($messenger) {
$messengerKnower = new MessengerKnower();
$messengerKnower->messenger = $messenger;
return $messengerKnower;
}
public function displayMessengerMessage() {
echo $this->messenger->getMessage();
}
}
Leave this unchanged...
class Runner {
private $messengerAware;
function __construct($messengerAware) {
if (!is_a($messengerAware, 'MessengerAware')) {
die("I'm expecting an instance implementing the MessengerAware interface.");
}
$this->messengerAware = $messengerAware;
}
public function run() {
echo "I'm running.\n";
$this->messengerAware->displayMessengerMessage();
}
}
Finally adjust this code:
$messengerAware = MessengerKnower::create(new Messenger());
$runner = new Runner($messengerAware);
$runner->run();
OUTPUT:
I'm running.
Hello!
I'm new to object oriented php. And if there are no functions in the method testing() in the HumanClass, should i declare them as abstract?
<?php
class HumanClass
{
private $legs;
private $hands;
public function __construct($legs, $hands)
{
$this->legs = $legs;
$this->hands = $hands;
}
public function testing()
{
}
}
class StudentClass extends HumanClass
{
private $books;
public function __construct($legs, $hands, $books)
{
parent::__construct($legs, $hands);
$this->books = $books;
}
public function testing()
{
echo "StudentClass called.";
}
}
function callClass(HumanClass $c)
{
$c->testing();
}
$example = new StudentClass(4, 2, 1);
callClass($a);
?>
Is it possible to have something like this?
echo $a->testing();
instead of having another method to call testing().
Given the code that you give, it's far from clear what the testing() function is supposed to do other than just exist for you to try things. The answer to that will also determine whether the versions in the baseclass should remain there as empty function.
There are other options, too, e.g. that the derived class first invokes the baseclass (extending), or that the baseclass doesn't contain an abstract or concrete such function but only the derived one does. Which to choose is up to the informed programmer to decide.
I've been using __set magic method with protected properties to monitor changes so that my classes know if they have something to save. Is there any way to monitor an array type property for changes? I understand that normally you access the array via a reference and functions like array_push won't trigger the __set method, they'll use a reference to the array.
What I want is basically this:
class Skill{ public $Player, $Name, $Level;}
class Player {
protected $Name, /*Other properties*/, $Skills /*Array*/
}
I then do tracking on all of the properties in Player to tell me if the persistence needs updated. (Skill would also have this function, but this shows the basic example). Also, I want to force them to remain synchronized (it's a bidirectional relationship).
Is there any way to do this that allows it to behave like an array (don't want to go through making a class just to synchronize those if I don't have to).
You could extend ArrayObject and proxy append:
class Skills extends ArrayObject
{
public function append($value)
{
// track changes
parent::append($value);
}
}
You could look into something like runkit_function_redifine(), but is it really too cumbersome to make helper methods for what you want? e.g.
class Player
{
private $skills = array();
protected function addSkill($skill)
{
// Do something.
//
$this->skills[] = $skill;
}
}
Or even a wrapper for an array to make it cleaner:
class FancyArray
{
private $content = array();
public function add($value)
{
// Do something.
//
$this->content[] = $value;
}
public function remove($value){ /* blah */ }
public function getContent(){ return $this->content; }
}
class Player
{
protected $skills;
public function __construct()
{
$this->skills = new FancyArray();
$this->skills->add("Ninjitsu");
}
}
I got a doubt while doing this:
class Logger {
public static $log_INFO = 'INFO';
public static $log_ERROR = 'ERROR';
public function log($logLevel, $param2, $param3) {
// Write log to some file
}
}
class Midea {
public function fn1 {
$logger = new Logger();
$logger->log(Logger::$log_INFO, 'some', 'some2');
}
}
Now my question is: Is there any way to make the log function in Logger class to accept only the static variables (any static variable) of Logger class? It should not accept any other string or integers as arguments.
My answer was based on the fact that $logLevel contains the name of a static class property.
If you use it as the updated example Logger::$INFO, that will pass the value string(4) "INFO" and this will not work. it needs to pass the value string(8) "log_INFO"
Yes, by using reflection:
public function log($logLevel, $param2, $param3) {
$reflection_property = new ReflectionProperty(get_called_class(), $logLevel);
if($reflection_property->isStatic()) {
// rest of the code
}
}
IMO this kind of enforcement is unnecessary, it adds both complexity and overhead to the code. And the benefits are small.
Coding your necessity like this seams more appropriate to me:
public static function $log_levels = array('INFO', 'ERROR');
public function log($log_level, $param2, $param3) {
if(in_array($log_level, static::$log_levels)) {
// code
}
}
The structure above opens up a neat opportunity:
public static function $log_levels = array(
'INFO' => array('Logger', 'handleInfoLogs'),
'ERROR' => array('Logger', 'handleErrorLogs')
);
public function log($log_level, $param2, $param3) {
if(array_key_exists($log_level, static::$log_levels)) {
return(static::$log_levels[$log_level]($param2, $param3));
}
}
What you are asking for is akin to enums in the Java world. Check this question on SO, which has some information on how you can implement similar concepts in PHP.
More specifically, you could implement what you are asking for like this:
class Logger {
const INFO = 1;
const ERROR = 2;
};
You could then use it in code like:
Logger::INFO
It isn't perfect, but I believe it is as close as it gets in PHP. To make it bullet-proof, you would have to employ some reflection to check the arguments passed in. This answer on SO has more information on how you can go about implementing it.
It's quite cumbersome but you could do this:
abstract class LoggerStatus
{
public function __toString()
{
return $this->status;
}
}
class LoggerStatusInfo extends LoggerStatus
{
protected $status = 'INFO';
}
class LoggerStatusError extends LoggerStatus
{
protected $status = 'ERROR';
}
class Logger {
public static $log_INFO;
public static $log_ERROR;
public function __construct()
{
self::$log_INFO = new LoggerStatusInfo();
self::$log_ERROR = new LoggerStatusError();
}
public function log(LoggerStatus $logLevel, $param2, $param3) {
// Write log to some file
}
}
I've never attempted this myself but I don't see any reason it wouldn't work. Personally, I'd go for something simpler.