How to use PHP class extends? - php

QUESTION :
I Cannot figure how to use classes extends in PHP... Even reading php.net website and some examples, there is something I cannot understand or missing !
Can you please tell me what I'm doing wrong ?
Api.php
class Api
{
public static $action = '';
# public function __construct()
# {
# }
public function actionCaller ($action,$args=NULL)
{
return self::$action_($args);
}
}
ApiForum.php
class ApiForum extends Api
{
#private static $forum;
public function __construct()
{
#self::$forum = new Api();
}
private function getPost ($args)
{
echo 'executed.';
#return "get forum post $args";
}
}
test.php
<?php
error_reporting(E_ALL);
ini_set('display_errors', true);
require_once('config.php');
require_once('classes/_Autoload_.php');
echo Api::actionCaller('forum')->getPost();
The result :
PHP Fatal error: Call to a member function getPost() on a non-object in /var/www/html/api.example.com/test.php on line 10
Please be clement with me ;)
CL
ANSWER:
Okay it's working now ! Thanks to all... There was more than one problem, here is the result :
Api.php
class Api
{
# public function __construct()
# {
# }
public function actionCaller ($action,$args=NULL)
{
return self::$action($args);
}
public function forum ()
{
return new ApiForum();
}
}
ApiForum.php
class ApiForum extends Api
{
# public function __construct()
# {
# }
public static function getPost ($args)
{
echo 'executed.';
}
}
test.php
error_reporting(E_ALL);
ini_set('display_errors', true);
require_once('config.php');
require_once('classes/_Autoload_.php');
echo Api::actionCaller('forum')->getPost('test');
I feel I need some more readings about classes and objects scopes ... :)

Just switch your "getPost" method declaration for this:
static function getPost($args){
A private method means only that class can execute that method. A static method means that it can be called without an object being instantiated, like what you're trying to do with the double colon eg. class::method(args).
Just for completeness sake, a public function is the middle ground. An object has to be instantiated for you to call it (via $object->method(args)), but it is available to any file that has imported that class
EDIT
Just a side note: I'd also like to add that for a method to be used as a static method, it still needs to be "included"! I apologise for the use of the word "imported", I've been playing around in a lot of other languages recently!

Related

Laravel Why I can access the method was not declared from Interface?

I have a problem like below:
I have an Interface name IBannerService
<?php
namespace App\Interfaces;
interface IBannerService
{
public function add($data);
public function list();
public function get($data);
public function delete($data);
}
and an instance name BannerService
class BannerService implements IBannerService
{
public function add($data)
{
return true;
}
public function list()
{
return true;
}
public function get($data)
{
return true;
}
public function delete($data)
{
return true;
}
public function test()
{
print_r("aaaa");
die();
}
}
finally I have a Controller name HomeController
class HomeController extends Controller
{
public function __construct(
IBannerService $bannerService
)
{
$this->bannerService = $bannerService;
}
public function index()
{
$listBanner = $this->bannerService->list();
$this->bannerService->test();
}
}
My configuration:
class DIServiceProvider extends ServiceProvider
{
$this->app->bind(
'App\Interfaces\IBannerService',
'App\Services\BannerService'
);
}
In app.php:
'providers'=>[
App\Providers\DIServiceProvider::class,
]
The code run well with $listBanner = true (just for testing).
The problem is:
Test Method was not declared in interface IBannerService but still go through and print out "aaa" the die.
Did I do something wrong?
Please suggest me, thank you!
That's perfectly normal functionality.
In the Laravel container you defined that when you ask for a IBannerService object, you want to get a BannerService class. And that is what you got. BannerService is an implementation of IBannerService, so no problem for the typehint.
A class is not limited to the functions defined by its interface so you can add as many other functions as you like. I wouldn't recommend it though, things like smart IDE's and phpstan would give you errors or warnings because to them, the variable is an implementation of IBannerService and this does not have a test() function.
If you really want to use more functions I would even recommend to use BannerService as the typehint. This way, static code analysis will still work.

codeigniter libraries dependancies

Im trying to pass objects between classes in code igniter and am currently failing. What am I doing wrong. Let me strt showing the pure.php version
Errors.php
<?php
class Errors
{
public function __construct(){}
public function setError($msg){}
}
OtherClass.php
<?php
class OtherClass
{
public function __construct(Errors $errorObject) {}
public function someMethod() {}
}
Then in my main controller..
Controller.php
<?php
class Main
{
public function __construct()
{
$this->errors = new Errors;
$this->other = new OtherClass($this->errors);
}
}
By doing this. I can add errors as I go to my error Object, across any objects i instantiate from the Main controller.
Now my code igniter version looks like this
/library/Errors.php
<?php
class Errors
{
public function __construct(){}
public function setError($msg){}
}
/library/OtherClass.php
<?php
class OtherClass
{
public function __construct(Errors $errorObject) {}
public function someMethod() {}
}
Then in my main controller..
Controller.php
<?php
class Main extends CI_Controller
{
public function __construct()
{
$this->load->library('Errors');
$this->load->library('OtherClass',$this->errors);
}
}
When I do this I get an error in my OtherClass saying that $errorObject is not an instance of Errors. Why is the object not being passed?
The problem is with $this->load->library which is defined like this.
public function library($library, $params = NULL, $object_name = NULL)
$params is expected to be an array. If it is not then the $params is set to NULL.
To get around this requires a bunch of monkey biz.
class Errors is unchanged but class OtherClass needs to be changed to...
class OtherClass
{
public function __construct($errorObject)
{
var_dump($errorObject[0]); //so we can prove it got passed
}
public function someMethod(){}
}
Note the removal of the type hint Error from the constructor declaration. Also, we access index 0 of the argument. The reason lies in what happens at the controller.
function __construct()
{
parent::__construct();
$this->load->library('Errors');
$this->load->library('OtherClass', [$this->errors]);
}
We have to put $this->error in an array so that load->library() won't mess with it.
The alternative is to not use "The CodeIgniter Way" and use good old fashion `new' instead. The controller then is...
function __construct()
{
parent::__construct();
$this->load->library('Errors');
$this->other = new OtherClass($this->errors);
}
And other class reverts to...
class OtherClass
{
public function __construct(Errors $errorObject)
{
var_dump($errorObject);
}
public function someMethod(){}
}
Now the problem is that without adding an autoloader to the system you wind up with
Fatal error: Class 'OtherClass' not found in ...
This LINK goes to a page that talks about the various ways to add an autoloader to CI. I know this has been answered on SO too. But I'm failing to find it at the moment.

Variables in __construct() when called by mysqli_fetch_object

I've got a class 'Event' which I am creating objects from via mysqli_fetch_object. The __construct() function is running and the objects variables are being set but they aren't set within the __construct() function.
I am using the following line to create the object:
$events[$x] = $result->fetch_object("Event")
When I run the following function by calling $events[$x]->eventPlaces(); it echos the variable.
public function eventPlaces()
{
echo $this->capacity;
}
However with the same code in the construct function it echos nothing.
public function __construct()
{
echo $capacity;
echo $this->capacity;
}
Apologies if I have explained this poorly, I've just got back into coding and OO php is new to me, if I missed anything then let me know.
I think you want your class to look like this:
class Event{
protected $capacity;
public __construct($capacity){
$this->capacity = $capacity;
}
public function eventPlaces(){
return $this->capacity;
}
}
Then you would do this:
$events[$x] = $result->fetch_object("Event", array(12));
echo $events[$x]->eventPlaces();

PHP 'non-object' error [duplicate]

This question already has answers here:
Call to a member function on a non-object [duplicate]
(8 answers)
Closed 10 years ago.
I'm working on a small MVC framework in PHP for an exercise. PHP, however, doesn't seem to like my Controller class. The class contains an instance of a loader that loads views:
abstract class Controller
{
public $load;
function __construct($load)
{
$this->load = $load;
}
abstract public function index();
}
From there, I can override Controller for all my controllers. For instace, my index controller:
class Index extends Controller
{
public function index()
{
$this->load->view("hello_world");
}
}
But when I create it:
require 'Controller.php';
require 'Load.php'
require 'controllers/Index.php';
$i = new Index(new Load());
$i->index();
I get this error:
PHP Fatal error: Call to a member function view() on a non-object in /var/www/controllers/Index.php on line 7
Can you guys help me out? I know I set the load in the constructor, and the load class does have a method called view, so why is it giving me this error?
Also: Load class, just for good measure
class Load
{
public function view($filename, $data = null)
{
if(is_array($data)) extract($data);
include ROOT.DS.'views'.DS.$filename.'.php';
}
}
The problem is with this code, and it's not always obvious:
class Index extends Controller
^^^^^
{
public function index()
^^^^^
{
$this->load->view("hello_world");
}
}
This is the same name and therefore a PHP 4 backwards compatible constructor. The parent's constructor then is not called, $load not set and the function not defined.
Knowing this, there are many solutions, including:
namespace DelishusCake;
Introduce a Namespace
This automatically fixes your issue. You need to place this on top of the file.
class Index extends Controller
{
public function index($load = NULL)
{
isset($load) && $this->load = $load;
$this->load->view("hello_world");
}
}
Make the PHP4 backwards compatible constructor work
Or:
class MyIndex extends Controller
{
public function index()
{
$this->load->view("hello_world");
}
}
Rename the class
Or:
class Index extends Controller
{
public function __construct($load) {
parent::__construct($load);
}
public function index()
{
$this->load->view("hello_world");
}
}
Add a PHP 5 constructor, call the parent's constructor
Keep in mind that you only need this because it's the same name. The in depth description you can find as well in the PHP Manual on the Constructors and Destructors page.
You need to instantiate the parent class.
class Index extends Controller
{
public function __construct($load) {
parent::__construct($load);
}
public function index() {
$this->load->view("hello_world");
}
}

How to call static func by passing $_GET params?

i have got a static function> which is called
regenerateThumbnailsCron()
And I would like to execute this function by GET params, for example>
if($_GET["pass"]=="password")
self::regenerateThumbnailsCron();
But if I tryied to call this function in constructor>
class AdminImages extends AdminTab
...
public function __construct()
{
if($_GET["pass"]=="password")
self::regenerateThumbnailsCron();
}
I cannot execute this function.
Is any way, how to call this function before __construct to correctly execute?
Thanks very much for any advice.
EDIT>
I tried also with public function>
<?php
include 'AdminImages.php';
$images = new AdminImages();
$images->regenerateThumbnailsCron();
?>
But i got error>
Fatal error: Class 'AdminTab' not found
You need to do a include 'AdminTab.php'; as well, since your class extends that
Not completely sure I understand your question, are you saying that you have static class "B" which extends class "A", "A" having your regenerateThumbnailsCron() method which you want to call before anything else?
If so then try this:
<?php
class A {
private function regenerate() {
.... do something ....
}
}
class B extends A {
function __construct() {
if ($_GET["pass"] == "password") {
parent::regenerate();
}
}
function regenerateThunbnailsCron() {
.... do somethinig ....
}
}
$images = new B();
$images->regenerateThumbnailsCron();
?>
This way, your parent's "regenerate()" function would get called during the constructor. You can switch this around to be a static class if you want, which if your goal is to compartmentalise any variables and functions away from the global scope would be a better way.

Categories