I've the followings classes:
abstract class utility, which contains general functions (e.g. database connection)
class get_conf, which returns the main variables that I will need almost everywhere (e.g. language, login status)
class get_data to handle the query to the database and return the results.
This is in my index file:
$init = new get_conf();
$lang = $init->lang;
$status = $init->status;
(...)
$config = new get_data($lang,$status);
This is the construct of class get_data.
class get_data extends utility {
public function __construct($lang = NULL,$status = NULL) {
$this->lang = $lang;
$this->status = $status;
}
...
Everything work fine, but I don't know how to handle at best during an ajax call.
After instantiate the class that I need,
$config = new get_data();
What is the best way to get $lang and $status? At the moment I'm calling again the functions that define their values - get_language(), check_login().
But there is a better way? Should I use sessions? It doesn't sound good to me call every time those function, especially when I have multiple ajax calls in the same page.
EDIT: I'm sorry, is my fault cause I formulated the question in the wrong way. What I would need is to get the variables from Ajax and ok, but I would need to use them in the class
For example, in the class get_data I've this function:
public function get_category($id_cat) {
$q = "SELECT category FROM p_category WHERE id = '".$id_cat."' AND code = ".$this->lang.";
return $this->exe_query($q);
}
Cause I'm calling this function both from Ajax and not, depending on the situation, $this->lang is defined only when I call it out of an Ajax request. And even using static var doesn't work with Ajax.
Write the following member function inside get_data class:
public function getCVar($var){
$c = new get_data();
eval('$tmp = $c->'.strtolower($var).';');
return $tmp;
}
Then you can get the variables value like below:
echo get_data::getCVar('lang');
echo get_data::getCVar('status');
Try it:
class get_data extends utility {
static $lang = null;
static $status = null;
public function __construct($lang = NULL,$status = NULL) {
if($lang !== null){
self::$lang = $lang;
}
if($status !== null){
self::$status = $status;
}
}
}
$config = new get_data($lang,$status);
echo get_data::$status;
echo get_data::$lang;
Related
I have a bunch of PHP functions that require unit test classes to be written.
I just want to know is there any way to mock-up lines of a function before use assertions?
<?php
function get_Func($args){
$number = $args[0];
$id = "71".$args[1]."0";
//The Line I need to mockup without touching the code
$result = getViaCurl($number,$id);
return $result;
}
?>
You need to extract the function to a service, so you can mock it easily, but as long as your function is inside a class, because this way you can pass the new service to the class constructor to be able to pass the mock in the test, instead of the original.
class YourClass
{
private NewService $service;
public function __construct($service)
{
$this->service = $service;
}
function get_Func($args)
{
$number = $args[0];
$id = "71".$args[1]."0";
//The Line I need to mockup without touching the code
$result = $this->service->getViaCurl();
return $result;
}
}
class NewService
{
public function getViaCurl($number, $id)
{
return getViaCurl($number,$id);
}
}
I have created a PHP class and I want to access its methods from a function in another file. Below is my code:
include_once PLUGIN_DIR_PATH."/classes/Brands.php";
function create_tables(){
$brand_obj = new Brands;
$brand_obj->create_brand_table();
}
function delete_tables() {
$brand_obj = new Brands;
$brand_obj->delete_brand_table();
}
Is it possible to create the object only once and then reuse it in every function? Right now, I am creating object in every function which is not a good practice.
You can use the global keyword to use a variable created outside a function inside a function:
global $object
code example :
include_once PLUGIN_DIR_PATH."/classes/Brands.php";
$brand_obj = new Brands;
function create_tables(){
global $brand_obj;
$brand_obj->create_brand_table();
}
function delete_tables() {
global $brand_obj;
$brand_obj->delete_brand_table();
}
I'm going to assume your actual functions do more than what you posted, otherwise you don't really need functions and can simply do this:
$brand_obj = new Brands;
$brand_obj->create_brand_table();
$brand_obj->delete_brand_table();
Otherwise, you can make a class and inject the Brands dependency into one of its properties via its constructor:
class TablesManager
{
private $brands;
public function __construct(Brands $brands)
{
$this->brands = $brands;
}
public function create_tables(): void
{
$this->brands->create_brand_table();
}
public function delete_tables(): void
{
$this->brands->delete_brand_table();
}
}
Usage:
$brands = new Brands();
$tables_manager = new TablesManager($brands);
$tables_manager->create_tables();
$tables_manager->delete_tables();
Note: calling a class SomethingManager is sometimes considered bad practice / a sign that the class does too many things. Consider (at least) giving it a more accurate name for your needs.
Demo: https://3v4l.org/iTmY6
Non-OOP alternative
function create_tables(Brands $brand_obj): void {
$brand_obj->create_brand_table();
}
function delete_tables(Brands $brand_obj): void {
$brand_obj->delete_brand_table();
}
$brand_obj = new Brands();
create_tables($brand_obj);
delete_tables($brand_obj);
I have a called class called ClientPolicy which is like this
class ClientPolicy {
var $serverHost="www.example.com";
var $httpPort = 80;
var $httpsPort = 443;
var $appKey;
var $secKey;
var $defaultContentCharset = "UTF-8";
}
and another class file name SyncAPIClient which looks like this
class SyncAPIClient{
function SyncAPIClient(ClientPolicy $clientPolicy) {
$this->clientPolicy = $clientPolicy;
}
function SyncAPIClient($appKey, $appSecret) {
$this->clientPolicy = new ClientPolicy();
$this->clientPolicy->appKey=$appKey;
$this->clientPolicy->secKey=$appSecret;
}
}
My questions are
1.) If you check the function in SyncAPIClient, you will notice that the ClientPolicy class was passed as a parameter before a variable, what does it really mean? What is the essence of passing a class in function parameter?
2.) I am getting an error "Cannot redeclare SyncAPIClient::SyncAPIClient()" in my script log and the reason is that SyncAPIClient function was called twice in SyncAPIClient class. How can I solve this issue? Is there any better way to write this SyncAPIClient function instead of passing it twice?
The author of this script is nowhere to be found and I am left to fix it.
1) Here the $clientPolicy variable that is passed to this function, needs be a ClientPolicy instance.
In this way, if the argument that is passed is different from an instance of ClientPolice class, an error is generated.
function SyncAPIClient(ClientPolicy $clientPolicy) {
$this->clientPolicy = $clientPolicy;
}
https://wiki.php.net/rfc/typed_properties_v2
https://laravel-news.com/php7-typed-properties
2) The error Cannot redeclare SyncAPIClient::SyncAPIClient() is caused because you are trying to declare two functions called SyncAPIClient ().
If in first SyncAPIClient() method you just want save the $clientPolicy in $this->clientPolicy, you can use the magic method __construct. Or just try changing the name of one of the functions, and the problem should be a problem.
class SyncAPIClient{
__construct(ClientPolicy $clientPolicy) {
$this->clientPolicy = $clientPolicy;
}
function SyncAPIClient($appKey, $appSecret) {
$this->clientPolicy = new ClientPolicy();
$this->clientPolicy->appKey=$appKey;
$this->clientPolicy->secKey=$appSecret;
}
}
https://www.php.net/manual/en/language.oop5.decon.php
http://www.zentut.com/php-tutorial/php-constructor-and-destructor/
Hope this helps!
I would've fix the code you have like this:
class SyncAPIClient
{
private $clientPolicy = null;
function SyncAPIClient(ClientPolicy $clientPolicy = null)
{
if($clientPolicy instanceof ClientPolicy){
$this->clientPolicy = $clientPolicy;
}else{
$this->clientPolicy = new ClientPolicy();
}
}
public function setAuthParams($appKey, $appSecret) {
$this->clientPolicy->appKey=$appKey;
$this->clientPolicy->secKey=$appSecret;
}
}
This way you can instantiate a SyncAPIClient with or without a ClientPolicy.
Without ClientPolicy:
$syncAPI = new SyncAPIClient();
$syncAPI->setAuthParams($apiKey, $apiSecret);
With ClientPolicy:
$clientPolicy = new ClientPolicy();
$clientPolicy->appKey=$appKey;
$clientPolicy->secKey=$appSecret;
$syncAPI = new SyncAPIClient($clientPolicy);
When using class and functions in combination like
Rtin::
Functions nested inside that class Rtin should have different names than that class name
So you shouldn't have function called rtin
However you can call function from outside the class with it's name
From the error you have may be due to:
function you nested in the class or the function outside the class has a duplicate outside the script itself. Like having function mentioned in included function.php file and also mentioned in the script itself so php get confused because function name is written in two php files at the same time
Example of class
class Rtin{
private $data;
private $results;
public function getResultsType(){
return ........
}
}
To call class use
$q = Rtin::getResultsType($data['name']);
In your example. Adapt it to the example I have provide and review the included files for duplicate function .
I'm using CakePHP and have created a class as follows:
class ApiController extends AppController {
// functions
}
I have about 10 functions in the class and I have found that I have repeated myself with the exact 3 same lines of code at the beginning of every function:
if ($this->request->is('post')) {
$data = $this->request->input('json_decode',true);
$authUser = explode('.',$_SERVER['PHP_AUTH_USER']);
$location_id = $authUser[1];
// Rest of my function
}
Is there any way that I can create something in the class which runs those 3 lines of code first, and then makes the $data and $location_id variables available for my functions to use, or must I write those 3 lines for every function?
It can be done using private method.
private $data = null;
private $locationId = null;
public function __construct($request = null, $response = null) {
parent::__construct($request = null, $response = null);
$this->data = $this->request->input('json_decode',true);
$authUser = explode('.',$_SERVER['PHP_AUTH_USER']);
$this->locationId = $authUser[1];
}
and then use it like this
$this->locationId;
You can write a method and put the 2 variables as a property of the class.
e.g.
class ApiController {
private $location_id;
private $data;
private function init() {
// ...
}
}
And then access the variables by doing $this->location_id.
I don't have alot of experience with OOP programming in PHP, and my search has given no result but solutions to direct methods. What I need is this:
// URL Decides which controller method to load
$page = $_GET['page'];
// I want to load the correct controller method here
$this->$page();
// A method
public function home(){}
// Another method
public function about(){}
// e.g. ?page=home would call the home() method
EDIT: I've tried several of the suggestions, but what I get is a memory overload error message. Here is my full code:
<?php
class Controller {
// Defines variables
public $load;
public $model;
public function __construct() {
// Instantiates necessary classes
$this->load = new Load();
$this->model = new Model();
if (isset($_GET['page'])) {
$page = $_GET['page'];
$fc = new FrontController; // This is what crashes apparently, tried with and without ();
}
}
}
If I understand your question correctly, you'd probably want something more like this:
class FrontController {
public function home(){ /* ... */ }
public function about(){ /* ... */ }
}
$page = $_GET['page'];
$fc = new FrontController;
if( method_exists( $fc, $page ) ) {
$fc->$page();
} else {
/* method doesn't exist, handle your error */
}
Is this what you're looking for? The page will look at the incoming $_GET['page'] variable, and check to see whether your FrontController class has a method named $_GET['page']. If so, it will be called; otherwise, you'll need to do something else about the error.
You can call dynamic properties and methods using something like this:
$this->{$page}();
Use a class.
Class URLMethods {
public function home(){ ... }
public function about(){ ... }
}
$requestedPage = $_GET['page'];
$foo = new URLMethods();
$foo->$requestedPage();
You can achieve this by using call_user_func. See also How do I dynamically invoke a class method in PHP?
I think you'd like also to append another string to the callable functions like this:
public function homeAction(){}
in order to prevent a hacker to call methods that you probably don't want to be.