How laravel uses object as an array in Facade class - php

I've noted that for creating a facade class, laravel provides only name "db"
framework/src/Illuminate/Support/Facades/DB.php
class DB extends Facade
{
/**
* Get the registered name of the component.
*
* #return string
*/
protected static function getFacadeAccessor()
{
return 'db';
}
}
I looked deeper and figured out that this method uses the provided name
framework/src/Illuminate/Support/Facades/Facade.php
protected static function resolveFacadeInstance($name)
{
if (is_object($name)) {
return $name;
}
if (isset(static::$resolvedInstance[$name])) {
return static::$resolvedInstance[$name];
}
return static::$resolvedInstance[$name] = static::$app[$name];
}
I understand first and second If statements.
But I have problems with understanding this:
return static::$resolvedInstance[$name] = static::$app[$name]
As I understood that $app is a protected property of Facade class which contains an instance of \Illuminate\Contracts\Foundation\Application class.
/**
* The application instance being facaded.
*
* #var \Illuminate\Contracts\Foundation\Application
*/
protected static $app;
My two questions:
How is it possible to use an object as an array(static::$app[$name]) if Application class doesn't extends ArrayObject class?
How laravel understands which class to call with providing only a short name 'db'?

Clicking through the Laravel source, I found this. As you can see, ApplicationContract (the private static $app from your question) is implemented by Application. This is in turn derived from Container, which implements the PHP core ArrayAccess interface. Carefully implementing this whole chain eventually makes Applicatin accessible like an array.
Turns out it boils down to good ole' object oriented programming :)
// Illuminate/Foundation/Application.php
class Application extends Container implements ApplicationContract, HttpKernelInterface
^^^^^^^^^ ^-> the private static $app in your question.
// Illuminate/Container/Container.php
class Container implements ArrayAccess, ContainerContract
^^^^^^^^^^^
// PHP core ArrayAccess documentation
/**
* Interface to provide accessing objects as arrays.
* #link http://php.net/manual/en/class.arrayaccess.php
*/
interface ArrayAccess {

You can look this, php manual and use ArrayAccess interface:
http://php.net/manual/en/class.arrayaccess.php

Related

How to override methods in Dispatch.php

I'm hard coding the $connection and $queue in over 10 files so I'm trying to clean that up. My first thought is to create some helpers that I can access in all of these files. However, I don't need those methods/variable available throughout my entire app. Instead, it would make most sense to place them in the ShouldQueue class. Any thoughts on the proper way to do this?
namespace App\Listeners\User;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Log;
class CreateJenzUser implements ShouldQueue
{
use InteractsWithQueue;
public $connection = 'sqs_high';
public $queue = 'portal_high.fifo';
//Would rather use
public $connection = $highConnection;
public function handle(UserBeingCreated $event)
{
}
}
EDIT
It turns out Laravel is creating a new instance of CreateJenzUser without the constructor.
vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php - line 479
/**
* Create the listener and job for a queued listener.
*
* #param string $class
* #param string $method
* #param array $arguments
* #return array
*/
protected function createListenerAndJob($class, $method, $arguments)
{
$listener = (new ReflectionClass($class))->newInstanceWithoutConstructor();
return [$listener, $this->propagateListenerOptions(
$listener, new CallQueuedListener($class, $method, $arguments)
)];
}
Just need to figure out how to override this method.
I would make a parent abstract class and extend it from all the classes that needs to use the queue. You can specify all the method that you must implement as abstract methods in the parent class so you do not need to implement the ShouldQueue interface.
So, the parent class will look like
abstract class Queue
{
use InteractsWithQueue;
protected $connection = 'sqs_high';
protected $queue = 'portal_high.fifo';
// list here all the methods in your ShouldQueue interface
abstract protected function handle(UserBeingCreated $event);
}
Then the child class:
class CreateJenzUser extends Queue
{
protected function handle(UserBeingCreated $event)
{
// your code here
}
}
Update
If you need to keep the interface (for type hint check for example) you can extend and implement in the same time. So, the child class in this case will look like:
class CreateJenzUser extends Queue implements ShouldQueue
{
protected function handle(UserBeingCreated $event)
{
// your code here
}
}
The Queue class may not need to be abstract in this case. However, that depends on how you want to design. If you have some methods that you want to call from the parent but define in the child you can still keep it as an abstract class.
It sounds like that all those classes share code, that should be refactored. Probably the best option would be to extract class and then pass it as a dependency in the constructors of classes, which need that behavior.
You should also consider the fact, that trait is basically interpretator assisted copy-paste. You are just using a language structure to hide that code duplication.
P.S.
Don't use extends to fix this. The "extends" keyword should be read as "is a special subtype of". And user is not a special type of queue ... frankly, some could see it as an insult.

Why isn't getFacadeAccessor() method abstract?

In Laravel's illuminate/support/Facades/Facade.php file there's a following method:
/**
* Get the registered name of the component.
*
* #return string
*
* #throws \RuntimeException
*/
protected static function getFacadeAccessor()
{
throw new RuntimeException('Facade does not implement getFacadeAccessor method.');
}
Is there any potential of doing that instead of just defining an abstract method, like below?
abstract protected static function getFacadeAccessor();
Why did they possibly want to reinvent the wheel?
I found the following reason here:
This method is designed to be overridden when extending the Facade class to return a string, the key which the service represented by the facade is bound within the container. By default, it throws an exception if not implemented. This gives a more informative message to those creating custom facades than if the framework were to instead use an abstract method.

PhpStorm warns about "Expected class1, got class2" when class2 extends class1

I'm using Phalcon Framework and it has class for models: Phalcon\Mvc\Model (from now only as P\M\Model). I've defined base domain, which extends that class and then every other domain extends my base domain, thus Phalcons Model class:
Domain.php:
class Domain extends \Phalcon\Mvc\Model
{
...
}
DomainA.php:
class DomainA extends Domain
{
...
}
then I'm using repository manager to get repository for DomainA models. All repositories have same parent, similarly as Domain, which has defined method find()
Repository.php:
class Repository
{
/**
* Will always return object of classes
* which extends Phalcon\Mvc\Model
*
* #return Phalcon\Mvc\Model
*/
public function find()
{
...
$domain::find();
}
}
RepositoryA.php:
class RepositoryA extends Repository
{
...
}
So, the RepositoryA now has method find() from its parent and because parent does not know exactly what he is going to return, but knows parent of what all the returns are so it is type-hinting it via #return.
Then I have some other class, which has method expecting only DomainA object, which is also parent of P\M\Model and I try to push there object of that type it works OK, because returned object from repository actualy IS an DomainA object, but Repository annotates it as P\M\Model so PhpStorm highlights it with message "Expected DomainA, got Phalcon\Mvc\Model..."
public function pleaseGiveDomainA(DomainA $obj)
{
...
}
// Works OK but is higlighted in IDE
$this->pleaseGiveDomainA($repositoryA->find());
How should I annotate this kind of stuff? Hinting in #return all cases of domains like #return DomainA|DomainB|DomainC... is no good as we have hundreds of Domains, also expecting in function the parent P\M\Model is no good, because we want to be sure its only DomainA.
Thanks.
try using an interface rather than a base model. In my experience sometimes PHPStorm can get confused with this sort of complex class hierarchy. In my programs I define an interface and type hint against that. Which allows PHPStorm to properly detect the class
If you redefine find() in class RepositoryA then just annotate its implementation with #return DomainA. Otherwise, declare find() as #method in the docblock of class RepositoryA with DomainA as its return type.
Both approaches are displayed below:
/**
* #method DomainA find() <-- use this when the method is inherited
* but not redefined in this class
*/
class RepositoryA extends Repository
{
/**
* #return DomainA <-- preferably use this
*/
public function find()
{
}
}
A similar trick can be used for inherited properties that in the children class store objects of classes that extend the class used in annotation in the base class:
/**
* #property DomainA $member <-- it was declared as #var Domain $member
* in the base class
*/
PSR-5 defines a #method tag.
Syntax
#method [return type] [name]([type] [parameter], [...]) [description]
Examples
/**
* #method string getString()
* #method void setInteger(int $integer)
* #method setString(int $integer)
*/
class Child extends Parent
{
<...>
}
abstract class EntitySerializer {
/**
* #return Entity
*/
abstract public function getEntity();
}
/**
* #method RealEntity getEntity()
*/
abstract class RealEntitySerializer extends EntitySerializer {}
/**
* #method PseudoEntity getEntity()
*/
abstract class PseudoEntitySerializer extends EntitySerializer {}
Re: taken from my SO answer here.

Referencing an extended class from inside the base class in PHP

Sorry for perhaps not the most accurate title. I'm having trouble figuring out what this would even be called.
I'm somewhat new to OOP with php, as most of my time is spent with procedural programming. In an effort to better learn these concepts, I'm taking an existing application and rewriting portions of it using OOP. The below example is how I set up the base class, and then I extended the base class into several smaller classes for easier maintainability. Below, you can see how I extended the base class to create a user class. Please note, that my class definitions are in separate files, but I have a working autoloader that automatically registers them
class EventScheduler{
function __construct(){
// set up database connections here
}
}
class User extends EventScheduler{
private function getUserProfile($username){
// return an array here representing
// details of passed username from database
}
public function getUserType($username){
return $this->getUserProfile($username)['user_type'];
}
}
What I'd like to be able to do is reference the User class from inside the base class, like this:
$eventApp = new EventScheduler();
$userType = $eventApp->User->getUserProfile("nameHere");
What I'm currently doing is this:
$eventApp = new EventScheduler();
//do some stuff here using the base class
$users = new User();
$userType = $users->getUserProfile("nameHere");
But as I add more child classes, I don't want to have to instantiate every extended class like I did there, I'd like to have them all grouped under the base object, rather than having each extended class in it's own object.
What you want to do is
$users = new User();
//do some stuff here using the base class
// ie $users->someFunctionFromEventScheduler();
$userType = $users->getUserProfile("nameHere");
This is a good reason to start reading up on common design patterns in OOP. There are plenty of good resources for this online and a quick google search will yield plenty of results and examples mostly hosted on github.
The specific pattern I believe you are looking for is the mediator pattern (Mediator pattern example in PHP). Rather than extending a class, as you are doing in your example, the mediator pattern is useful when you want an instance of a class that has access to many other classes that can all communicate with each other through one base class. The premise is that 'One good friend is better than many acquaintances.`.
An example for you: (interfaces are incredibly useful here as they define specific characteristics that are required in each of the classes)
/**
* Interface Mediator
*/
interface Mediator {
/**
* #param string $key
* #param Mediated $mediated
* #return void
*/
public function attach($key, Mediated $mediated);
/**
* #param $key
* #return Mediated
*/
public function getAttached($key);
}
/**
* Interface Mediated
*/
interface Mediated {
/**
* #param Mediator $mediator
* #return void
*/
public function setMediator(Mediator $mediator);
/**
* #return Mediator
*/
public function getMediator();
}
Now we need a base mediator class, I'll use your event scheduler example. Notice that it implements the Mediator interface and must, as a result implement the methods the interface requires.
/**
* Class EventScheduler
*/
class EventScheduler implements Mediator {
/**
* A collection of mediated instances.
*
* #var array
*/
protected $mediated = [];
/**
* #param string $key
* #param Mediated $mediated
* #return void
*/
public function attach($key, Mediated $mediated)
{
// So upon attaching a mediated instance we can build the two
// way binding in one place using the key as the identifier.
// First we set $this on the mediated instance.
$mediated->setMediator($this);
// Then we add this instance to our mediated array inside this instance
$this->mediated[$key] = $mediated;
}
/**
* #param $key
* #return Mediated
*/
public function getAttached($key)
{
return $this->mediated[$key];
}
}
Now we can setup a mediated instance. That can be attached to the mediator. Notice it implements the Mediated interface.
/**
* Class User
*/
class User implements Mediated {
/**
* #var Mediator
*/
protected $mediator;
/**
* #param Mediator $mediator
* #return void
*/
public function setMediator(Mediator $mediator)
{
$this->mediator = $mediator;
}
/**
* #return Mediator
*/
public function getMediator()
{
return $this->mediator;
}
}
You can create as many of the mediated instances as you like and attach them to the Mediator instance. Bear in mind that this isn't a specific mediator, in that many instances can be attached, in most cases it's better to be explicit with which classes can be attached rather than allowing dynamic registration by a key.
$scheduler = new EventScheduler();
$user = new User();
$scheduler->attach('user', $user);
// Now we know that we can get the mediator from the User class
$user->getMediator();
// We can also get the User from the mediator itself.
$scheduler->getAttached('user');
As you attach more classes you'll notice that each of them can use their mediator to get instances of the other attached classes, this is where the concept of one good friend comes from.
This is just an example and not fully featured for brevity, but should give you a good idea why using common design patterns will help you enormously and is a very good place to start when learning OOP if you want to develop good habits.

How to implmenet this mechanism using Abstract Class in PHP?

From the past two days i have been diving into the concepts of OOPS in PHP, and i found Abstract Class to be very useful concept and i wanted to implement it in my application. and here is why i want to implement it.
My Application Consist of Several Unstructured Pattern which uses several different classes without any hierarchies, due to this i have to use several repeated codes. i want to cut this all up and structure it properly, basically what i want to do is
Define a parent class which is not instantiable from outside.
Define all properties in this parent class so that i can re-use the same property for different child classes.
Define re-usable class methods and objects so that child class can use it without the need of defining it again and again (Inheritance).
Basically My Abstract class should be capable of inheriting the re-usable methods and properties and at the same time it should act as an Interface.
To demonstrate you clearly let me show you some sample codes which i have been using.
public $error = array(); //used to handle error mechanism and to hold the errors.
private $data = array(); //used with Accessor Methods (__set and __get)
private $validate; //holds Validate Object
private $dbh; //holds Database Object
public function __set($property, $value) {
if( in_array($property, $this->data)) {
return $this->data[$property] = $value;
} else {
return false;
}
}
public function __get($property) {
return 'Access Denied to Class Property [ '.$property.' ]';
}
Above codes are repeated for almost every class, this is the reason i want to define it once in a parent class and control the mechanism from there.
As i am still Novice to Many OOPs concept i am unable to understand how do i achieve what i want using Abstract Class. below is the sample code i tried using which ofcourse is wrong for declaring an abstract method.
abstract class Property {
protected $error = array();
protected $data = array();
protected $dbh;
protected $validate;
abstract protected function connectDB($dbhandle) {
return $this->dbh = $dbhandle;
}
abstract protected function setValObj($valObj) {
return $this->validate = $valObj;
}
public function __set($property, $value) {
}
public function __get($property) {
}
}
here is what i want to do.
When a child class is initiated it should be forced to define methods as declared in abstract class.
A Child class should only be able to call and pass the arguement but not extend an abstract method. the mechanism should be handled by parent class. this is what i tried to do in my code.
i know i am missing something, or might be i have not got the concept right, could somebody explain me what exactly should i be doing to achieve the same result.
1 . Define a parent class which is not instantiable from outside.
All abstract classes can not be instantiated, only extended. So this is what you already have:
abstract class Property {
On to the next:
2 . Define all properties in this parent class so that i can re-use the same property for different child classes.
Just write them into that abstract class (often called base class or abstract base class or template class as well). All classes extending from a base class, will have access to protected or public member methods and properties. If you make a variable or function private, it's only available to code in the base class.
So just define all you want to have in the base class to be shared amongst all extending classes and you only need to type it once.
3 . Define re-usable class methods and objects so that child class can use it without the need of calling it again and again (Inheritance).
This works automatically. As you extend from the base class, the public and protected class methods defined therein are automatically accessible through the extending class. You do not (but you can unless specified with final) need to add that function again to make it available. E.g. all public methods from the base class are automatically available publicly on all classes that extend from it.
Then you continue:
here is what i want to do.
1 . When a child class is initiated it should be forced to define methods as declared in abstract class.
You can do so by defining these needed methods as abstract. Abstract methods needs to be implemented by the extending class. However you can not put code into abstract methods in the base class. That's left there for the extending class.
2 . A Child class should only be able to call and pass the arguement but not extend an abstract method. the mechanism should be handled by parent class. this is what i tried to do in my code.
If you want to prevent a subclass to overwrite a function, declare it as final in your base class. Final methods can not be further extended.
But probably you want to do something that is technically not possible, e.g. prevent that a method can be extended while you require that is should be extended.
In your code you're using magic functions to access the properties / values. Those don't count in the sense that their name changes. So you loose the control of the inheritance for a bigger part of your class design.
However, you can implement array access to offer getter/setters. It's bound to a concrete interface and you then can disallow access through the base class and prevent extending of this area for classes that will extend from it.
Let me know if you would like to have some example code, probably SPL is new to you as well.
Provide variable inheritance via ArrayAccess
As you've been running into the problem that inheritance can not be easily used on the magic function __get() and __set() which are available, I had the idea to make that part of the access concrete that does not change (get, set) while it's still possible to name the property variable. An interface that is available with PHP that already does this is ArrayAccess. It was designed to give access to properties via the style we know from standard php arrays ([]) and it's normally used for that. But for this example it has the benefit to already provide an interface as well that fits the general need.
First a demonstration how such a class behaves in use:
# give birth to the object
$object = new PropertyClass; // one of your property classes
# get:
$value = $object['propertyA'];
# set:
$object['propertyA'] = 'new value';
# unset:
unset($object['propertyA']); // and gone ;)
# isset:
isset($object['propertyA']); // true / false
Okay, as this shows, this looks like an array, but is an object. The rest of $object works as known, so this is no limitation, but an addition.
As you can imagine already with this code, there must be a get and set routine as well for reading and setting the properties values like with __get() and __set(). Additionally there must be something for isset and unset, so four. This is the interface definition of ArrayAccess:
ArrayAccess {
/* Methods */
abstract public boolean offsetExists ( mixed $offset )
abstract public mixed offsetGet ( mixed $offset )
abstract public void offsetSet ( mixed $offset , mixed $value )
abstract public void offsetUnset ( mixed $offset )
}
You can extend from that in PHP by implementing the interface. That's not extends but implements. This works with every interface in PHP, but this interface is something special as well. It's provided by the SPL/PHP itself and in the moment a class of yours actually implement the functions, the functionality as described in the code above is automatically added to your class.
As those functions are available publicly, you could call them with their name as well naturally.
So actually this interface qualifies for a properties object as you want to build one and will give you an interface you can put your constraints on.
So the only question left is: How can this look like for your properties class?
Implementing ArrayAccess to a variable properties class
<?php
/**
* Property Object base class based on ArrayAccess
*/
abstract class PropertyObject implements ArrayAccess
{
/** Interface Methods */
/**
* implementing classes must return all names of their properties
* in form of an array.
*/
abstract protected function returnNames();
/** class */
/**
* value store
*
* #var array
*/
private $store = array();
/**
*
* By this design, properties can only contain A-Z and a-z.
*
* look like.
*
* #return bool
*/
private function isValidPropertyName($name) {
return ctype_alpha($name);
}
private function checkOffsetArgument($offset) {
if ($this->isValidPropertyName($offset)) return;
throw new InvalidArgumentException(sprintf('"%s" is not a valid property name.', $offset));
}
private function setNames(array $names) {
foreach($names as $name) {
$this->checkOffsetArgument($name);
}
$len = count($names);
$this->store = $len
? array_combine($names, array_fill(0, $len, null))
: array()
;
}
/**
* final constructor to obtain control
*/
final public function __construct() {
$this->setNames($this->returnNames());
}
/**
* ArrayAccess impl.
*
* #return bool
*/
public function offsetExists($offset) {
$this->checkOffsetArgument($offset);
return array_key_exists($offset, $this->store);
}
/**
* ArrayAccess impl.
*
* #return mixed
*/
public function offsetGet ($offset) {
$this->checkOffsetArgument($offset);
return $this->store[$offset];
}
/**
* ArrayAccess impl.
*/
public function offsetSet($offset, $value) {
$this->checkOffsetArgument($offset);
if (!$this->offsetExists($offset)) {
throw new InvalidArgumentException(sprintf('Property "%s" can not be set.', $offset));
}
$this->store[$offset] = $value;
}
/**
* ArrayAccess impl.
*/
public function offsetUnset($offset) {
$this->checkOffsetArgument($offset);
unset($this->store[$offset]);
}
}
/**
* I feel so concrete.
*/
class ConcreteType extends PropertyObject
{
protected function returnNames() {
return array('propertyA');
}
}
$obj = new ConcreteType;
var_dump($obj['propertyA']); # NULL, maybe you need other default values.
$obj['propertyA'] = 'hello';
var_dump($obj['propertyA']); # string(5) "hello"
var_dump(isset($obj['propertyA'])); # bool(true)
// this will trigger an exception
try {
$obj['XProperty'] = 'good night.';
} catch (Exception $e) {
var_dump($e->getMessage()); # string(36) "Property "XProperty" can not be set."
}
// the following might be unwanted but can be prevented in base class:
unset($obj['propertyA']);
var_dump(isset($obj['propertyA'])); # bool(false)
I think you need to implement mixin interface. According to my knowledge PHP does not support this natively. Some PHP frameworks (like Yii framework) implemented it by itself. I found one example here. But I am sure you will be able to find better examples.

Categories