What is the proper way to handle optional parameters on a service request?
Lets say in this scenario i want to have also $title as optional parameter
<?php
namespace Lw\Application\Service\Wish;
class AddWishRequest
{
private $userId;
private $email;
private $content;
public function __construct($userId, $email, $content)
{
$this->userId = $userId;
$this->email = $email;
$this->content = $content;
}
public function userId()
{
return $this->userId;
}
public function email()
{
return $this->email;
}
public function content()
{
return $this->content;
}
}
Example from here
Usually in DDD and following the rules of clean code also, if you have optional parameters, you have multiple constructors, two in this case:
One for just the mandatory arguments.
One for all the arguments including the optional but in this constructor it would be mandatory too.
If you wanna construct the object without the optional argument you call the first one. And if you wanna supply a non null optional argument you use the second one.
Usually you should use factory methods with meaningful names, and hide the constructors.
AddWishRequest.create ( userId, email, content)
AddWishRequest.createWithTitle ( userId, email, content, title )
You can use optional arguments in any function call, also the constructor. Best practice is, to preceed "get" to the getters.
public function __construct($userId, $email, $content, $title = "")
means, $title is an optional argument. When not supplied, it is set to an empty string. You also could provide any other type or value.
namespace Lw\Application\Service\Wish;
class AddWishRequest
{
private $userId;
private $email;
private $content;
private $title;
public function __construct($userId, $email, $content, $title = "")
{
$this->userId = $userId;
$this->email = $email;
$this->content = $content;
$this->title = $title;
}
public function getUserId()
{
return $this->userId;
}
public function getEmail()
{
return $this->email;
}
public function getContent()
{
return $this->content;
}
public function getTitle()
{
return $this->title;
}
}
Update
If you just declare a property like
private $property
then accessing it via $this->property with always be null (until you set a value). You should make the getter responsible for returning the correct values.
Following example will always return an array making use of the NULL-coalesce operator:
if $something is true (or has an array content) will return $something
else will return empty array
public function getSomething() : array {
return $this->something ?? [];
}
Related
I like PHP, but I miss some of the constructs from other languages that although don't do anything for performance, make the code look cleaner and possibly more maintainable. I'm thinking of Visual Basic days and the "with" statement.
So ideally in PHP we could do this:
with($myWellDescribedInstance) {
->property1="string";
->property2=1;
->property3=2;
->myMethod();
}
Instead of
$myWellDescribedInstance->property1="string";
$myWellDescribedInstance->property2=1;
$myWellDescribedInstance->property3=2;
$myWellDescribedInstance->myMethod();
Is there anything like this in PHP?
You can implement a fluent interface on any class just by having a function return $this.
This is mostly used for setters, but of course it works for any method for which you would normally not have a return value.
For example:
class Person
{
protected $name = '';
protected $surname = '';
protected $email = '';
public function getName()
{
return $this->name;
}
public function getSurname()
{
return $this->surname;
}
public function getEmail()
{
return $this->email;
}
public function setName($name)
{
$this->name = $name;
return $this;
}
public function setSurname($surname)
{
$this->surname = $surname;
return $this;
}
public function setEmail($email)
{
$this->email = $email;
return $this;
}
}
Usage:
$person = new Person;
$person->setName('John')
->setSurname('Doe')
->setEmail('johndoe#email.com');
Of course, calling the method (for example) setName or withName would be entirely up to you.
Another idea might be to have both a setName method (which doesn't return anything) and a withName method (which returns $this), but that might be a bit of an overkill.
If you use "setters" instead of direct property access you can chain methods.
class A {
private $a;
private $b;
public function setA($a)
{
$this->a = $a;
return $this;
}
public function setB($b)
{
$this->b = $b;
return $this;
}
public function doSomething()
{}
}
$a = new A();
$a->setA('a')
->setB('b')
->doSomething();
I can not load data to properties using this construction I receive null in dump
<?php
namespace App\Domain\Good;
class GoodDto
{
public $name;
public $articul;
public $price;
public $type;
public $qnt;
public $discount;
public $category;
public $description;
public $description2;
public $color;
public function load($data)
{
$this->name = $data['name'];
$this->articul = $data['artikul'];
$this->price = $data['price'];
$this->type = (isset($data['type'])) ? $data['type'] : null;
$this->qnt = $data['count'];
$this->discount = $data['spinner-decimal'];
$this->category = $data['id_cat'];
$this->description = $data['editor1'];
$this->description2 = '';
$this->color = $data['color'];
//$this->user_id = Auth::user()->id;
}
public static function fromRequest($request)
{
dump('inp=>',(new self ())->load($request->input()));
return (new self ())->load($request->input());
}
}
Please explain to me why I receive null while request->input() is an array, I call it from another place
$dto=GoodDto::fromRequest($request);
Method chaining, returns the last return from the chain. The other returns are used to call the next link in the chain.
(new self ())->load()
So load() needs to return $this
public function load($data)
{
...
return $this;
}
Currently it returns null, which is why it returns null.
See you are not saving the instance from the constructor, instead you pass it to load by enclosing it within the (....). By pass it I mean you call the load method on the return from the constructor.
You can test this like so:
class foo{
function load(){
return $this;//return this
}
}
var_dump((new foo)->load());
class bar{
function load(){
//return null
}
}
var_dump((new bar)->load());
Output
//return this
object(foo)#1 (0) {
}
//return null
NULL
sandbox
The second class in the example above class bar, is essentially what you are doing.
PS. forgot to scroll down on your post at first ... lol ... So I had to update my answer.
Bonus
You can also simplify the load code like this:
public function load($data)
{
foreach($data as $prop=>$value){
if(property_exists($this,$prop)) $this->$prop = $value;
}
return $this;
}
This way if you add new properties you don't have to edit the load method ever again, you just have to name the array elements the same as the class properties. You can even throw an error if the property does not exist if you want, by adding an else to the condition etc...
Personally, when I do this I prefer to call a set method like this:
//eg. $data = ['foo' => '2019-06-16']
public function load(array $data)
{
foreach($data as $prop=>$value){
$method = 'set'.$prop; //$method = 'setfoo' using the example above
if(method_exists($this,$method )){
$this->$method($value); //calls 'setfoo' with '2019-06-16'
}else{
throw new Exception('Unknown method '.$method);
}
}
return $this;
}
public function setFoo($date){
$this->foo = new DateTime($date);
}
Then you can apply some transforms to the data etc... PHP method names are not case sensitive. You can even combine these by first checking for a method then a property then throw the error etc...
Cheers.
Supposed I have method of repository class like this to create post:
public function create($title, $slug, $custom_slug = '', $meta_keyword, $body, $meta_description, $status, $bla, $bla)
is there any way to avoid this in the right way? because I think it is not good if there are many parameters and not really readable. i often put the value in wrong place since i dont remember the parameters orders.
if I set parameter as array like this:
public function create(array $columns)
but client won't know which required parameters and which one is not.
In general, you can get around this problem by passing in your arguments as an array. Alternatively, you can make the parameters public static fields, so that they can be accessed from within your method without you having to even pass them in as parameters.
You can create a class like this:
class Post {
protected $title;
protected $body;
protected $slug;
protected $metaKeyword;
protected $metaDescription;
protected $status;
function __construct($title, $body) {
$this->setTitle($title);
$this->setBody($body);
}
public function setTitle($title) {
$this->title = $title;
}
public function setBody($body) {
$this->body = $body;
}
public function setSlug($slug) {
$this->slug = $slug;
}
public function setMetaKeyword($metaKeyword) {
$this->metaKeyword = $metaKeyword;
}
public function setMetaDescription($metaDescription) {
$this->metaDescription = $metaDescription;
}
public function setStatus($status) {
$this->status = $status;
}
public function save() {
// do something here
}
}
$post = new Post('Example', 'This is a body');
$post->setSlug('example-post');
$post->save();
I have an issue in PHP.
In my php file, i created the following line:
$foo = $wke->template->notify()
->type("ERROR")
->errno("0x14")
->msg("You are not logged.")
->page("login.tpl");
In the end, I need my $foo variable will return this:
$foo->type = "ERROR"
$foo->errno= "0x14"
$foo->msg= "You are not logged."
$foo->page= "login.tpl"
Please note that the $wke->template is where i need call the notify() element.
The way of calling function of class one by one just by "->" because the function returning the same object of the class. See the example below. You will get this
class Wke {
public $type;
public $errno;
public $msg;
public $page;
public $template = $this;
public function notify(){
return $this;
}
public function errorno($error){
$this->errno = $error;
return $this; // returning same object so you can call the another function in sequence by just ->
}
public function type($type){
$this->type = $type;
return $this;
}
public function msg($msg){
$this->msg = $msg;
return $this;
}
public function page($page){
$this->page = $page;
return $this;
}
}
The whole magic is of return $this;
Each of those methods will need to return some object that stores what you set as the argument in it. Presumably, it will be the template that contains each object property on it, and when you call the method it sets that corresponding variable and returns itself.
This might look as a stupid question. But, I have a class with some public string variables defined in it.
Upon assigning a value to a property:
$a = new user();
$a->FirstName = "sth";
I want to store the value as UTF8.
I know I can do this via:
$a->Firstname = utf8_encode("sth");
However, I want the object to do this automatically.
How can I do this?
Otherwise no, the object cannot do it automatically.
Not automatically, but automagically!
<?php
class User {
/**
* Change the public to private/protected!
*/
private $Firstname;
/**
* This is automatically called upon calling a value that can't be written "from the outside".
*/
public function __set( $key, $value ) {
$this->$key = utf8_encode( $value );
}
public function __get( $key ) {
return isset( $this->$key ) ? $this->$key : false;
}
}
$user = new User;
$user->Firstname = 'Berry';
echo $user->Firstname;
The better solution would be to refactor in using mutators and accessors, or better yet, learn OO.
You want to use setters and getters. See: http://en.wikipedia.org/wiki/Encapsulation_%28object-oriented_programming%29
Like:
class User
{
protected $Firstname;
public function setFirstname($Firstname) {
$this->Firstname = utf8_encode($Firstname);
}
public function getFirstname() {
return $this->Firstname;
}
}
Example using magic methods:
class User
{
protected $data = array(
'Firstname' => '',
// ...
);
public function __set($key, $value) {
if (isset($this->data[$key])) {
$this->data[$key] = utf8_encode($value);
}
}
public function __get($key) {
return isset($this->data[$key]) ? $this->data[$key] : null;
}
}
Edit: I'm using $data so that there is at least a minimum of control of what properties can be set.
If you'd designed your class to have accessors and mutators, rather than public access to raw variables, then this would be easy.
Original code:
class user {
private $FirstName = '';
public function getFirstName() {
return $this->FirstName;
}
}
Solution code:
class user {
private $FirstName = '';
public function getFirstName() {
return utf8_encode($this->FirstName);
}
}
I suggest moving towards this approach.
Otherwise no, the object cannot do it automatically.
Edit
__set and __get might be the most appropriate way to implement this. I'm not too familiar with them, and it doesn't really matter: the point I'm making here is to use accessors and mutators... however you end up implementing them.