understanding dependency injection in PHP - php

class Author {
private $firstName;
private $lastName;
public function __construct($firstName, $lastName) {
$this->firstName = $firstName;
$this->lastName = $lastName;
}
public function getFirstName() {
return $this->firstName;
}
public function getLastName() {
return $this->lastName;
}
}
class Question {
private $author;
private $question;
public function __construct($question, Author $author) {
$this->author = $author;
$this->question = $question;
}
public function getAuthor() {
return $this->author;
}
public function getQuestion() {
return $this->question;
}
}
Class author is injected into the constructor of Question class am I correct? but how to call the Question class to get the author's name?
$question = new Question('What is PHP', 'Adam');
$question->getFirstname;
like this? I assume Question class inherited Author class so Question's instance can use the function of Author Class?

Simple
echo $question->getAuthor()->getFirstName();
Think of it this way if it helps
$author = $question->getAuthor();
echo $author->getFirstName();
Also note that you can't construct a Question with the string "Adam", you need to pass an instance of Author
$question = new Question('What is PHP', new Author('Adam', 'Lastname'));

You could create a new method:
class Question
{
// ...
function getAuthorFirstname()
{
return $this->author->getFirstname();
}
}
$question = new Question(.., new Author(..., ...));
echo $question->getAuthorFirstname();
Or, if you don't really care about Law of Demeter or feel that it doesn't apply:
$question = new Question(.., new Author(..., ...));
echo $question->getAuthor()->getFirstname();
In the end it all comes down to striking a balance between information hiding and pragmatism.

Related

how cann I convert php class to json [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 10 months ago.
Improve this question
I am trying to convert a simple class object to json as string.
It does not work!. could you help me please.
here are my files:
Peson.php
<?php
class Person
{
private $name;
public function getName()
{
return $this->name;
}
public function setName($name)
{
$this->name = $name;
}
public function toJson()
{
return json_encode($this);
}
}
?>
index.php
include 'Person.php';
$person = new Person();
$person->setName("John");
echo $person->toJson();
Result :
You're getting an empty object because your class doesn't have any public properties to encode. Change name from private to public and you'll get output like this: {"name":"John"}
You can use get_object_vars for this.
public function toJson()
{
return json_encode(get_object_vars($this)); //returns {"name":"stringNameHere"}
}
More info about get_object_vars here.
This is how your code would look:
class Person
{
private $name;
public function getName()
{
return $this->name;
}
public function setName($name)
{
$this->name = $name;
}
public function toJson()
{
return json_encode(get_object_vars($this));
}
}
$person = new Person();
$person->setName('testName');
echo $person->toJson(); //Print {"name":"testName"}
Here you have a live code example
In this case you get an empty object because the properties are private. A way to keep your properties private and still geting their values in a JSON is using the JsonSerializable Interface. Then implementing its method jsonSerialize().
class Person implements JsonSerializable
{
private $name;
public function getName()
{
return $this->name;
}
public function setName($name)
{
$this->name = $name;
}
public function jsonSerialize()
{
$vars = get_object_vars($this);
return $vars;
}
}
<?php
class Person implements \JsonSerializable
{
private $name;
public function getName()
{
return $this->name;
}
public function setName($name)
{
$this->name = $name;
}
public function jsonSerialize()
{
return get_object_vars($this);
}
}
?>
then, you can convert your person object to JSON with json_encode
$person = new Person();
$person->setName("John");
echo json_encode($person);

PHP - Inheritance

I am currently learning OOP concepts. I have used CodeIgniter, I know it has OOP concepts but I don't understand how it works. I just use the methods in the documentation.
I am now on the inheritance part.
Here is my code:
<?php
class Artist {
public $name;
public $genre;
public $test = 'This is a test string';
public function __construct(string $name, string $genre) {
$this->name = $name;
$this->genre = $genre;
}
}
class Song extends Artist {
public $title;
public $album;
public function __construct(string $title, string $album) {
$this->title = $title;
$this->album = $album;
}
public function getSongArtist() {
return $this->name;
}
}
$artist = new Artist('Joji Miller', 'Lo-Fi');
$song = new Song('Demons', 'In Tounges');
echo $song->getSongArtist(); // returns nothing
From what I understand inheritance will let me access properties and methods from the parent class.
In my example I have instantiate the Artist. So now I have Joji Miller as artist name.
Now, if I instantiate the Song class, I thought that I can access the artist name since I am extending the Artist class. But it is just empty.
Would you help me understand why it is not getting the artist name?
Hope I explained myself clearly. Thankyou..
Heh. Learning "oop principles" from CodeIgniter is like going to North Korea to study democracy. And you have already learned the wrong things.
The extends keyword should be read as "is special case of". As in class Admin extends User means that the admin instance is a more specialized case of generic user.
And that's where you are wrong. Song is not a subtype of an artist.
Instead the song has an artist, which performs it. As in:
$artist = new Artist('Freddie Mercury');
$song = new Song('Another One Bites the Dust', $artist);
echo $song->getArtist()->getName();
Another bad practice, that you seem to have picked up: stop defining class variables as public. That breaks the encapsulation. Instead those values should be assigned using methods, because then you will e able top track, format and validate those values.
First of all in your case you have not the best example of inheritance...
And it leads to confusion...
I'd rather advise you to have in base class base behavior related to all descendants, like here.
Base class:
<?php
class SomethingWithName
{
private $name;
public function __construct(string $name)
{
$this->name = $name;
}
public function getName(): string
{
return $this->name;
}
}
Your classes:
class Artist extends SomethingWithName
{
private $genre;
public function __construct(string $name, string $genre)
{
parent::__construct($name);
$this->genre = $genre;
}
public function getGenre(): string
{
return $this->genre;
}
}
class Song extends SomethingWithName
{
private $album;
private $artist;
public function __construct(string $name, string $album, Artist $artist)
{
parent::__construct($name);
$this->album = $album;
$this->artist = $artist;
}
public function getAlbum(): string
{
return $this->album;
}
public function getArtist(): Artist
{
return $this->artist;
}
}
Result:
$a = new Artist('Joji Miller', 'Lo-Fi');
$s = new Song('Demons', 'In Tounges', $a);
var_export([
$s->getName(), // Demons
$s->getAlbum(), // In Tounges
$s->getArtist()->getName(), // Joji Miller
$s->getArtist()->getGenre(), // Lo-Fi
]);
That's because when defining the Song class's __construct() function you are overriding the Artist's __contruct() function. Which is the function that gets called when you do $song = new Song(...)
Using the keyword parent:: you can access the parent's classes functions.
The following works.
<?php
class Artist {
public $name;
public $genre;
public $test = 'This is a test string';
public function __construct(string $name, string $genre) {
$this->name = $name;
$this->genre = $genre;
}
}
class Song extends Artist {
public $title;
public $album;
public function __construct(string $title, string $album, string $ArtistName, string $genre) {
$this->title = $title;
$this->album = $album;
parent::__construct($ArtistName, $genre);
}
public function getSongArtist() {
return $this->name;
}
}
$artist = new Artist('Joji Miller', 'Lo-Fi');
$song = new Song('Demons', 'In Tounges','Joji Miller', 'Lo-Fi');
echo $song->getSongArtist(); // returns nothing

Passing class from another class or dependency injection

I'm having difficulties to understand the given code and the reason behind dependency injection. I've got the following error:
Uncaught Error: Call to undefined method Question::getFullName() in C:\xampp\htdocs\OOP\Index.php:10 Stack trace: #0 {main} thrown in C:\xampp\htdocs\OOP\Index.php on line 10.
Even if I instantiate an object of the Author class in the constructor, I keep getting a string in the Question class once I try to use getQuestion().
require 'Author.php';
class Question {
private $author;
private $question;
public function __construct($question, Author $author) {
$this->author = $author;
$this->question = $question;
}
public function getAuthor() {
$firstname = $this->author->getFirstName();
$lastname = $this->author->getLastName();
$fullaname = $firstname . $lastname;
return $this;
}
public function getQuestion() {
return $this->question;
}
}
<?php
class Author {
private $firstName;
private $lastName;
private $fullName;
public function __construct($firstName, $lastName) {
$this->firstName = $firstName;
$this->lastName = $lastName;
}
public function getFirstName() {
return $this->firstName;
}
public function getLastName() {
return $this->lastName;
}
public function getFullName() {
return $this->fullName = $this->firstName." ".$this->lastName;
}
}
require 'Question.php';
$question = new Question("What is the author's name?", new Author("josel", "parayno"));
echo $question->getQuestion();
echo $question->getFullName();
$question really does not have getFullName method. Method getFullName exists in class Author. And after creating and "sending" to Question, when it was created method getFullName available in class Question private $author property.
But if you want to get Athor name by follow code, you need try
$question->getAuthor()->getFullName();
And if you do this, you take error again, becouse in question->getAuthor you return $this, and in this case this is a Question object. For getting author name from question object you should to do follow:
Fix getAuthor like this
public function getAuthor()
{
$firstname = $this->author->getFirstName();
$lastname = $this->author->getLastName();
return $this->author;
}
Rewite call name in you index.php like this
echo $question->getAuthor()->getFullName();

Importing Parent function data in child php oop

I am trying to learn simple method of php oop by calling parent function data in child.
However somewhere I am making mistake.
class name{
var $firstname;
var $lastname;
var $name;
public function name($firstname, $lastname){
$this->firstname=$firstname;
$this->lastname=$lastname;
$this->name=$this->firstname." ".$this->lastname;
return $this->name;
}
}
class sentence extends name{
var $name;
var $letter;
function sentence(){
$this->letter="My name is ";
echo $this->letter.$this->name;
}
}
$name=new name(ABC, Xyz);
$letter=new sentence();
I have created one calls to get name input and another child class to write the sentence. However not able to call the name in child.
a quick fix since thats probably what you want.
<?php
class name {
private $firstname;
private $lastname;
private $name;
private $sentence;
public function __construct($firstname, $lastname){
$this->firstname = $firstname;
$this->lastname = $lastname;
$this->name = $firstname . " " . $lastname;
$this->sentence = "My name is : " . $this->name;
}
public function getName(){
return $this->name;
}
public function getSentence(){
return $this->sentence;
}
}
$instance = new name("test","lastname");
echo $instance->getSentence();
?>
class name
{
public $firstname;
public $lastname;
public $name;
public function name($firstname, $lastname)
{
$this->firstname = $firstname;
$this->lastname = $lastname;
$this->name = $this->firstname.' '.$this->lastname;
return $this->name;
}
}
class sentence extends name
{
public $name;
public $letter;
public function greeting()
{
$this->letter = 'My name is ';
echo $this->letter.$this->name;
}
}
//$name=new name(ABC, Xyz);
$letter = new sentence('ABC', 'Xyz');
$letter->greeting();
Thanks to #ManhNguyen
Are you trying to read the state of variables in a parent class?
That is not how OOP works.
You have to either group together all the variables into one class or pass it trough as an argument to the function you want to have access to the data.
Second of all you don't seem to not be using a __construct function and yet pass variables into the new name() function that is also a NO-NO.

Get data from object composition

Let's say I have 3 objects : "Place", "Person", "Action".
Depending on the place where is the person and the age of this person, this person can do different action.
For example :
$place->person->action->drive(); // OK if place is "parking" and "person" is 18+
$place->person->action->learn(); // OK if the place is "school" and person is less than 18.
How can I access the data about the objects "Person" and "Place" from the Action class ?
Classes examples :
class Place {
public $person;
private $name;
function __construct($place, $person) {
$this->name = $place;
$this->person = $person;
}
}
class Person {
public $action;
private $name;
private $age;
function __construct($name, $age) {
$this->name = $name;
$this->age = $age;
$this->action = new Action();
}
}
class Action {
public function drive() {
// How can I access the person's Age ?
// How can I acess the place Name ?
}
public function learn() {
// ... Same problem.
}
}
I think I could transmit "$this" from Person to Action when I create the Action Object (ie. $this->action = new Action($this)), but what about the Place data ?
It doesn't make sense to make Person a property of Place nor Action a property of Person.
I'd be more inclined to create public getters for Person and Place's properties and either make them injectable properties of Action or at least pass them as arguments to Action's methods, eg
class Place
{
private $name;
public function __construct($name)
{
$this->name = $name;
}
public function getName()
{
return $this->name;
}
}
class Person
{
private $name;
private $age;
public function __construct($name, $age)
{
$this->name = $name;
$this->age = $age;
}
public function getName()
{
return $this->name;
}
public function getAge()
{
return $this->age();
}
}
class Action
{
private $person;
private $place;
public function __constuct(Person $person, Place $place)
{
$this->person = $person;
$this->place = $place;
}
public function drive()
{
if ($this->person->getAge() < 18) {
throw new Exception('Too young to drive!');
}
if ($this->place->getName() != 'parking') {
throw new Exception("Not parking, can't drive!");
}
// start driving
}
}

Categories