Have a class that I am using, I am overriding variables in the class to change them to what values I need, but I also not sure if or how to handle an issue. I need to add a key that is generated to each of this URLs before the class calls them. I cannot modify the class file itself.
use Theme/Ride
class ETicket extends Ride {
public $key='US20120303'; // Not in original class
public $accessURL1 = 'http://domain.com/keycheck.php?key='.$key;
public $accessURL2 = 'http://domain.com/keycheck.php?key='.$key;
}
I understand that you cannot use a variable in the setting of the public class variables. Just not sure what would be the way to actually do something like this in the proper format.
My OOP skills are weak. I admit it. So if someone has a suggestion on where I could read up on it and get a clue, it would be appreciated as well. I guess I need OOP for Dummies. =/
---- UPDATE ---
The initial RIDE class has 2 URLs set.
public $accessURL1 = "http://domain.com/index.php";
public $accessURL2 = "http://domain.com/index2.php";
I was to override them so the RIDE class will use my new domains.
I can add the following and it works...
class ETicket extends RIDE {
public $accessURL1 = 'http://mydomain.com/myindex.php';
public $accessURL2 = 'http://mydomain.com/myindex2.php';
}
However, I also want to pass a variable from elsewhere ($key) as a parameter to the URL when I override them so when i call RIDE it has a URL with the value of KEY at the end. (?key=keyvalue)
Your close, if you do not want to allow calling code to change the $key, you can do something like:
class ETicket extends Ride {
public function getKey()
{
return 'US20120303';
}
public function generateUrl()
{
return 'http://domain.com/keycheck.php?key=' . $this->getKey();
}
}
// Calling code example
$eTicket= new ETicket();
// $key is a member of ETicket class, so just call on generateUrl which will
// build and return the url
var_dump($eTicket->generateUrl());
You can also permit calling code to change the key if needed, by adding a public setter/getter:
class ETicket extends Ride {
protected $key;
public function setKey($key)
{
$this->key = $key;
}
public function getKey()
{
return $this->key;
}
public function generateUrl()
{
return 'http://domain.com/keycheck.php?key=' . $this->getKey();
}
}
// Calling code example
$eTicket= new ETicket();
$eTicket->setKey('US20120303');
var_dump($eTicket->generateUrl());
-- UPDATE --
There are a couple of options, you can either append the key to your url as part of the calling code, like this:
$eTicket= new ETicket();
$url = $ride->accessURL1 . '?key=US20120303';
Or, use a method (changed slightly to accept key directly) as I described earlier:
class ETicket extends Ride
{
public function generateUrl($key)
{
return $this->accessURL1 . '?key=' . $key;
}
}
$eTicket= new ETicket();
$url = $eTicket->generateUrl('US20120303');
I guess the point is, you cannot do what you originally asked without which is to concatenate a variable to a member variable initialization.
Related
I'm developing in Laravel 9, though I assume this is Php-specific. Example below of what I'm trying to achieve: Imagine I have a controller named HomeController.php with a getData() method that returns something I need...
<?php
namespace App\Http\Controllers;
class HomeController
{
public function getData()
{
return [my data]
}
}
And I want to be able to call that class and method in a dynamic way, and assign my data to $data...
<?php
use App\Http\Controllers\HomeController;
class Example
{
public $className = 'HomeController';
public $method = 'getData';
public function index()
{
$instance = new $this->className;
$method = $this->method;
$data = $instance->$method();
}
}
I have a variation of this setup in my application, and it's not working. I get the following error: Class "HomeController" not found.
If I replace $this->className with HomeController it works. Keep in mind $className will be passed from elsewhere, I want to avoid hard-coding class names into my Example class.
It is true that I will still need to include them all at the top anyway, but I just want to know if it's possible to pass a class name like that. Unless there's a way to dynamically include those too, but I doubt it.
Edit: Tim's answer in the comments worked great. Here is a fixed version:
<?php
use App\Http\Controllers\HomeController;
class Example
{
public $className = 'App\\Http\\Controllers\\HomeController'; // Change 1
public $method = 'getData';
public function index()
{
$instance = app()->make($this->className); // Change 2
$method = $this->method;
$data = $instance->$method();
}
}
I came across a function, which is being called without defining it anywhere.
No error is shown from intelphense as well.
function I am referring to in the below code is
self::whereIdenityNumber($identityNumber)->exists();
public static function generateUniqueIdentityNumber()
{
$identityNumber = strtoupper(Str::random(10));
while (true) {
$isExist = self::whereIdenityNumber($identityNumber)->exists();
if ($isExist) {
self::generateUniqueIdenityNumber();
}
break;
}
return $identityNumber;
}
There is no problem with the function, just wanted to know how it works.
note:
there is a comment like below in docblock comments. Can this be treated as defining the function?
* #method static \Illuminate\Database\Eloquent\Builder|\App\Models\IdentityUser whereIdentityNumber($value)
That static method seems to be defined at \App\Models\IdentityUser
You must have something like:
Class IdentityUser extends Model{
public static whereIdentityNumber($query){
...
}
}
How do I get the getState variable from one class to another?
Exactly I need to get value of "filter.search". How can I do that?
jimport('joomla.filesystem.folder');
abstract class SroHelper
{
public static function checkIP()
{
SroModelItems::getState(filter.search); ---- ??
}
}
jimport('joomla.application.component.model');
class SroModelItems extends JModel
{
protected function populateState($ordering = null, $direction = null)
{
$this->setState("filter.search", $jform["search$dbextra"]);
}
}
You have two modules to store information in the session automatically from a get / post request and then to read it back:
JFactory::getApplication()->getUserStateFromRequest($key, $request)
JFactory::getApplication()->setUserState($key, $value);
Just ensure you are saving the information before you try to retrieve it!
I am working on an OOP implementation and I have the following:
abstract class Parent{
public abstract function select($order="desc");
}
class Child extends Parent{
public function select($order) // here is the problem error
{
// selection code
}
}
This throws an error that tells me the declaration must be compatible with the parent method.
I did implement it with the right parameters except I didn't carry over the default parameter setting.
I do not want to copy past the same prototype of parent method in 100 classes if i want someday change the default value. How can I do this?
does generic exist in php ??
public abstract function select($order="desc");
and public function select($order) dont match.
remove the default value from the abstract function.
About the only way I can see to avoid updating a lot of values if you ever want to change the common default is this:
abstract class Parent{
const DEFAULT_SELECT_ORDER = "desc";
public abstract function select($order = "");
protected static function select_order(&$order)
{
if (empty($order) || !in_array(strtolower($order), array("asc", "desc"))) {
// additional test to check if the value is valid
$order = self::DEFAULT_SELECT_ORDER;
}
}
}
class Child extends Parent{
public function select($order = "") // here is the problem error
{
self::select_order($order);
// selection code
}
}
Hmm - another, probably better approach:
abstract class Parent {
protected $order = "desc";
public function order($order) {
if (in_array(strtolower($order), array("asc", "desc"))) {
$this->order = $order;
} else {
// probably should throw an exception or return false or something
}
return true;
}
public abstract function select();
}
class Child extends Parent {
public function select() {
// select code using $this->order
}
}
$query = new Child();
$query->order("asc");
$results = $query->select();
All you need to do is change your extended method to be something like:
public function select($order="some other value") // here is the problem error
{
// selection code
}
Essentially because the original method has a default value then ALL overrides must have a default value.
In order to do what you want you would have to make $order an object property of Parent and change the method signature to get rid of the $order parameter. Then within any specific implementation you could simply set $order to whatever else you want.
You possible could use my tiny library ValueResolver, for example:
$myVar = ValueResolver::resolve($var, $default);
and don't forget to use namespace use LapaLabs\ValueResolver\Resolver\ValueResolver;
There are also ability to typecasting, for example if your variable's value should be integer, so use this:
$id = ValueResolver::toInteger('6 apples', 1); // returns 6
$id = ValueResolver::toInteger('There are no apples', 1); // returns 1 (used default value)
Check the docs for more examples
I'm struggling to find a correct approach to pass data between classes, which do not directly call each other, and are only related through a parent class (which I now use, but I consider it a dirty workaround rather than anything near a solution).
I have 3 classes both able to read input and write output, and based on configuration I set one to read, another one to write. It may even be the same class, they all share a parent class, but they are always two separate instances called from a controller class.
Currently I use this sort of functionality:
class daddy {
public static $data;
}
class son extends daddy {
public function setData() {
parent::$data = "candy";
}
}
class daughter extends daddy {
public function getData() {
echo parent::$data;
}
}
while($processALineFromConfig)
$son = new son;
$son->setData();
$daughter = new daughter;
$daughter->getData();
daddy::$data = null; //reset the data, in the actual code $daughter does that in parent::
}
Instantination of these classes runs in a loop, therefore I always need to reset the data after $daughter receives them, 'cos otherwise it would stay there for another pass through the loop.
I'm absolutely sure it's not how class inheritance is supposed to be used, however I'm struggling to find a real solution. It only makes sense the data should be stored in the controller which calls these classes, not the parent, but I already use return values in the setter and getter functions, and I am not passing a variable by reference to store it there to these functions 'cos I have optional parameters there and I'm trying to keep the code clean.
What would be the correct approach to pass data through the controller then?
Thanks!
The best option would be for two object share some other, third object. This would be the class for "third object" which will ensure the exchage:
class Messenger
{
private $data;
public function store($value)
{
$this->data = $value;
}
public function fetch()
{
return $this->data;
}
}
Then a class for both instance, that will need to share some state:
class FooBar
{
private $messenger;
private $name = 'Nobody';
public function __construct($messenger, $name)
{
$this->messenger = messenger;
$this->name = $name;
}
public function setSharedParam($value)
{
$this->messenger->store($value);
}
public function getSharedParameter()
{
return $this->name . ': ' . $this->messenger->fetch();
}
}
You utilize the classes like this:
$conduit = new Messenger;
$john = new FooBar($conduit, 'Crichton');
$dominar = new FooBar($conduit, 'Rygel');
$dominar->setSharedParameter('crackers');
echo $john->getSharedParameter();
// Crichton: crackers
Basically, they both are accessing the same object. This also can be further expanded by making both instance to observe the instance of Messenger.