use muliple method in one object in php [duplicate] - php

This question already has answers here:
PHP method chaining or fluent interface?
(10 answers)
Closed 9 years ago.
I am new to php and crating classes for my project . I have reached this far ..
$db->select('id');
$db->from('name');
$db->where("idnum<:num");
$db->bindparamers(':num',100);
$rows=$db->executeQuery();
I wana know to create methods such that i can use all thing at once like below
$db->select('id')->from('name')->where('idnum>100')->executeQuery();
I have tried searching but not getting what exactly i should search for
here is my class structure
class Dbconnections
{
//For Complex Queries
public function select($items)
{
}
public function from($tablenames)
{
}
public function where($arr)
{
}
public function orderby($order)
{
}
public function bindparamers($parameter,$value)
{
}
public function executeQuery()
{}
}
What changes i need to make to use it as :
$db->select('id')->from('name')->where('idnum>100')->executeQuery();

It's called method chaining and in your case can be achieved by returning $this from each method.
class Dbconnections
{
public function select($items)
{
// ...
return $this;
}
public function from($tablenames)
{
// ...
return $this;
}
public function where($arr)
{
// ...
return $this;
}
public function orderby($order)
{
// ...
return $this;
}
public function bindparamers($parameter,$value)
{
// ...
return $this;
}
public function executeQuery()
{
// ...
return $this;
}
}

Related

Why this code throw syntax error unexpected in all function where i invoke more then one -> function [duplicate]

This question already has an answer here:
Call function directly after constructor: new Object()->callFunction()
(1 answer)
Closed 2 years ago.
Why this code throw
syntax error, unexpected '->' (T_OBJECT_OPERATOR), expecting ',' or ';'
php 7.1
<?php
class TestHtml
{
public function Send() { return $this; }
public function Dispose() { return $this; }
public function ToString() { return 'Done'; }
}
echo new TestHtml->Send()->Dispose()->ToString(); // there error
?>
PHP cannot make sense of this. It cannot figure out that the first part is a call to a constructor. Use parens.
<?php
class TestHtml
{
public function Send() { return $this; }
public function Dispose() { return $this; }
public function ToString() { return 'Done'; }
}
echo (new TestHtml)->Send()->Dispose()->ToString(); // there error
Alternatively, you could create the object first, then call the other functions.
$object = new TestHtml;
echo $object->Send()->Dispose()->ToString();
And just for fun, you could make a static function to create the class.
<?php
class TestHtml
{
public function Send() { return $this; }
public function Dispose() { return $this; }
public function ToString() { return 'Done'; }
public static function make() { return new self; }
}
echo TestHtml::make()->Send()->Dispose()->ToString();

Yii2 getters & setters to format string to float

Ok so currently have this function in controller, which is called multiple times.
public function formatFloat($value)
{
return (float)sprintf('%0.6f', $value);
}
So I am trying to use getters and setters so I can just use
$model->$whatever;
and the formatting will be done.
In my model I have
public function getChargePeak()
{
return $this->charge_peak;
}
public function setChargePeak($value)
{
return $this->charge_peak = (float)sprintf('%0.6f', $value);
}
but when doing
$peak = $model->chargepeak;
var_dump($peak);die;
it is still returning as a string
If the charge_peak property is stored as string and you need a float in you app you should use
public function getChargePeak()
{
return floatval($this->charge_peak);
}
Anyway you should store the values in a coherent way as you use the values in your app ..
http://php.net/manual/en/function.floatval.php
So I suggest u another pattern: decorator and helpers. You should use a controller only to get data from request, prepare it for model and send it to view.
Formatting values is a helper logic. So create a new class
\common\helpers\Number.php
namespace common\helpers;
class Number
{
public static function formatFloat($value)
{
return (float)sprintf('%0.6f', $value);
}
}
Then create decorator for your model:
namespace common\models\decorators;
class YourModelDecorator
{
/**
* YourModel
*/
private $model;
public function __construct(YourModel $model)
{
$this->model = $model;
}
public function __get($name)
{
$methodName = 'get' . $name;
if (method_exists(self::class, $methodName)) {
return $this->$methodName();
} else {
return $this->model->{$name};
}
}
public function __call($name, $arguments)
{
return $this->model->$name($arguments);
}
public function getChargePeak()
{
return \common\helpers\Number::formatFloat($this->model->charge_peak);
}
}
and send it to view for example:
public function actionView($id)
{
$model = $this->loadModel($id);
$this->render('view', [
'model' => new \common\models\decorators\YourModelDecorator($model)
]);
}

Magento 2 - Get number of results on current search page when including a block

I'm trying to access getResultCount() in \Magento\CatalogSearch\Block\Result
I have the following block created.
class GetSearch extends \Magento\Framework\View\Element\Template
{
protected $_pageTitle;
protected $_result;
public function __construct(\Magento\Framework\View\Element\Template\Context $context,\Magento\Framework\View\Page\Title $pageTitle,
\Magento\CatalogSearch\Block\Result $result)
{
$this->_pageTitle = $pageTitle;
$this->_result = $result;
parent::__construct($context);
}
public function getTitle()
{
return $this->_pageTitle->getShort();
}
public function getSearchResults()
{
return $this->_result->getResultCount();
}
}
When I call <?=$block->getSearchResults();?>
I receive the following error: Uncaught Error: Call to a member function getLoadedProductCollection() on boolean
I think I'm going about this the wrong way and somehow need to access the current object that contains the search results but I'm a little lost.
What's the best method of doing this?
I have finally found the answer and it is to use the QueryFactory to return the instance of the Query model.
Hopefully this will help someone in the future!
class GetSearch extends \Magento\Framework\View\Element\Template
{
protected $_pageTitle;
protected $_query;
public function __construct(\Magento\Framework\View\Element\Template\Context $context,\Magento\Framework\View\Page\Title $pageTitle,
\Magento\Search\Model\QueryFactory $query)
{
$this->_pageTitle = $pageTitle;
$this->_query = $query;
parent::__construct($context);
}
public function getTitle()
{
return $this->_pageTitle->getShort();
}
public function getSearchResults()
{
return $this->_query->get()->getNumResults();
}
}

Php remove () in a function to make it easier to use

I am creating a little system which will allow users to extend the system with their own classes.
Class Core {
static $confArray;
static $extendArray;
protected static $instance;
public function read($name)
{
return self::$confArray[$name];
}
public function put($name, $value)
{
self::$confArray[$name] = $value;
}
public function extend($function, $handler, $args=null){
self::$extendArray[$function] = new $handler($args);
}
public function __call($method, $args){
return self::$extendArray[$method];
}
public static function getInstance()
{
if (!isset(self::$instance))
{
$object =__CLASS__;
self::$instance= new $object;
}
return self::$instance;
}
}
With That, now a user can come and register a simple extension from such a class:
class WorkersTest{
function isWorking($who){
echo "$who is working";
}
function isNotWorking($who){
echo "$who is not working";
}
}
To call the function (isworking/ isNotWorking), a the programmer needs to register the test class through:
Core::getInstance->extend("worker","WorkersTest");
Then it can now be called through:
Core::getInstance->worker()->isWorking("George");
This is working perfectly. My question is how i can remove the () in the call (dont worry why) and have:
Core::getInstance->worker->isWorking("George");
Is it possible?
You can use the magic __get() method, just like __call():
public function __get($name)
{
return $this->$name();
}
Try overriding the magic __get() method to return what you need:
Class Core {
// (...)
public function __get($name) {
if (isset( self::$extendArray[$function] )) {
return $this->$name();
}
//if there is no function registered under named "$name"
//throwing Exception is by design better, as #scragar suggested
throw new Exception("No function registered under named {$name}");
//return NULL;
}
}

The correct way of doing delegates or callbacks in PHP

I need to implement the following pattern in php:
class EventSubscriber
{
private $userCode;
public function __construct(&$userCode) { $this->userCode = &$userCode; }
public function Subscribe($eventHandler) { $userCode[] = $eventHandler; }
}
class Event
{
private $subscriber;
private $userCode = array();
public function __construct()
{
$this->subscriber = new Subscriber($this->userCode)
}
public function Subscriber() { return $this->subscriber; }
public function Fire()
{
foreach ($this->userCode as $eventHandler)
{
/* Here i need to execute $eventHandler */
}
}
}
class Button
{
private $eventClick;
public function __construct() { $this->eventClick = new Event(); }
public function EventClick() { return $this->eventClick->Subscriber(); }
public function Render()
{
if (/* Button was clicked */) $this->eventClick->Fire();
return '<input type="button" />';
}
}
class Page
{
private $button;
// THIS IS PRIVATE CLASS MEMBER !!!
private function ButtonClickedHandler($sender, $eventArgs)
{
echo "button was clicked";
}
public function __construct()
{
$this->button = new Button();
$this->button->EventClick()->Subscribe(array($this, 'ButtonClickedHandler'));
}
...
}
what is the correct way to do so.
P.S.
I was using call_user_func for that purpose and believe it or not it was able to call private class members, but after few weeks of development i've found that it stopped working. Was it a bug in my code or was it some something else that made me think that 'call_user_func' is able call private class functions, I don't know, but now I'm looking for a simple, fast and elegant method of safely calling one's private class member from other class. I'm looking to closures right now, but have problems with '$this' inside closure...
Callbacks in PHP aren't like callbacks in most other languages. Typical languages represent callbacks as pointers, whereas PHP represents them as strings. There's no "magic" between the string or array() syntax and the call. call_user_func(array($obj, 'str')) is syntactically the same as $obj->str(). If str is private, the call will fail.
You should simply make your event handler public. This has valid semantic meaning, i.e., "intended to be called from outside my class."
This implementation choice has other interesting side effects, for example:
class Food {
static function getCallback() {
return 'self::func';
}
static function func() {}
static function go() {
call_user_func(self::getCallback()); // Calls the intended function
}
}
class Barf {
static function go() {
call_user_func(Food::getCallback()); // 'self' is interpreted as 'Barf', so:
} // Error -- no function 'func' in 'Barf'
}
Anyway, if someone's interested, I've found the only possible solution via ReflectionMethod. Using this method with Php 5.3.2 gives performance penalty and is 2.3 times slower than calling class member directly, and only 1.3 times slower than call_user_func method. So in my case it is absolutely acceptable. Here's the code if someone interested:
class EventArgs {
}
class EventEraser {
private $eventIndex;
private $eventErased;
private $eventHandlers;
public function __construct($eventIndex, array &$eventHandlers) {
$this->eventIndex = $eventIndex;
$this->eventHandlers = &$eventHandlers;
}
public function RemoveEventHandler() {
if (!$this->eventErased) {
unset($this->eventHandlers[$this->eventIndex]);
$this->eventErased = true;
}
}
}
class EventSubscriber {
private $eventIndex;
private $eventHandlers;
public function __construct(array &$eventHandlers) {
$this->eventIndex = 0;
$this->eventHandlers = &$eventHandlers;
}
public function AddEventHandler(EventHandler $eventHandler) {
$this->eventHandlers[$this->eventIndex++] = $eventHandler;
}
public function AddRemovableEventHandler(EventHandler $eventHandler) {
$this->eventHandlers[$this->eventIndex] = $eventHandler;
$result = new EventEraser($this->eventIndex++, $this->eventHandlers);
return $result;
}
}
class EventHandler {
private $owner;
private $method;
public function __construct($owner, $methodName) {
$this->owner = $owner;
$this->method = new \ReflectionMethod($owner, $methodName);
$this->method->setAccessible(true);
}
public function Invoke($sender, $eventArgs) {
$this->method->invoke($this->owner, $sender, $eventArgs);
}
}
class Event {
private $unlocked = true;
private $eventReceiver;
private $eventHandlers;
private $recursionAllowed = true;
public function __construct() {
$this->eventHandlers = array();
}
public function GetUnlocked() {
return $this->unlocked;
}
public function SetUnlocked($value) {
$this->unlocked = $value;
}
public function FireEventHandlers($sender, $eventArgs) {
if ($this->unlocked) {
//защита от рекурсии
if ($this->recursionAllowed) {
$this->recursionAllowed = false;
foreach ($this->eventHandlers as $eventHandler) {
$eventHandler->Invoke($sender, $eventArgs);
}
$this->recursionAllowed = true;
}
}
}
public function Subscriber() {
if ($this->eventReceiver == null) {
$this->eventReceiver = new EventSubscriber($this->eventHandlers);
}
return $this->eventReceiver;
}
}
As time passes, there are new ways of achieving this.
Currently PSR-14 is drafted to handle this use case.
So you might find any of these interesting:
https://packagist.org/?query=psr-14

Categories