How to use namespace properly in PHP? - php

I have this file root/core/Router.php
<?php
namespace Core;
class Router {
protected $url;
protected $controller;
private function parseURL() {
// threat the $this->url; for example ["r", "product"]
}
private function request() {
$this->controller = Controller::get($this->url[1]);
}
public function __construct() {
$this->parseURL();
$this->request();
}
}
?>
then file root/core/Controller.php
<?php
namespace Core;
class Controller {
public static function model($name, $params = []) {
$model = "\\Model\\$name";
return new $model($params);
}
public static function view($name, $params = []) {
require_once APP_DIR . "view/" . $name . ".php";
}
public static function get($name, $params = []) {
require_once APP_DIR . "controller/" . $name . ".php";
$name = "\\Controller\\$name";
return new $name($params);
}
}
?>
then root/controler/Product.php
<?php
namespace Controller;
use Core\Controller;
use Model\Product;
class Product {
public function get() {
$ret['state'] = 510;
$productModel = new Product;
$products = $productModel->getAll();
if(isset($products)) {
$ret['products'] = $products;
$ret['state'] = 200;
}
return $ret;
}
}
?>
then file root/model/Product.php
<?php
namespace Model;
class Product {
public function add($values) {
return Database::insert("product", $values);
}
}
?>
and root/core/Model.php
<?php
namespace Core;
class Model {
protected $table = null;
public function getAll() {
// some code to collect data
}
}
?>
What i want to achive is that every Controller in root/controller/*.php able to load any Model in root/model/*.php but class inside root/model/*.php must able to access (inheritance/extends) the Model class inside root/core/Model.php i firstly asked on chatGPT for some AI Generated answer, that the reason why i get this far.
Then i get this error, when the AI keep giving the same answer.
Fatal error: Cannot declare class Controller\Product because the name is already in use in C:\xampp\htdocs\app\shop\controller\Product.php on line 6
I actually realize that the simple way probably with naming the class so ther no conflict between it but i became aware how to properly using the namespace if its such features in php. Those files loaded without any autoloader, so i just require_once each file in root/init.php file.
I read few documentations but hard to implement in multiple files and directorys.
I Apreciate any feedback, thanks

Related

PHP class not found when using class in another class

I have 2 class in Two sub folders within a mother folder in am trying to auto load classes within index.php file and then use one into another one but not working yet.Take a look at this->
FOLDER STRUCTURE
MotherFOlder
|- lib
| |- Api.php
|- inc
| | - SC.php
|- index.php
in index.php i am coding like this:
namespace ACX;
use ACX\lib\Api;
use ACX\inc\SC;
spl_autoload_register(__NAMESPACE__ . '\\autoload');
function autoload($class = '') {
if (!strstr($class, 'ACX')) {
return;
}
$result = str_replace('ACX\\', '', $class);
$result = str_replace('\\', '/', $result);
require $result . '.php';
}
Then in Api.php
<?php
namespace ACX\lib;
class Api{
private static $instance = null;
public static function getDataJSON(){
return 'data';
}
public static function getInstance(){
if (empty(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
}
And in SC.php
<?php
namespace ACX\inc;
class SC{
private static $instance = null;
public static function getDataSets(){
$data = Api::getDataJSON();
return $data;
}
public static function getInstance(){
if (empty(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
}
But i am getting this error Fatal error: require(): Failed opening required 'inc/Api.php'
Is there any bug in the code?
It's simple because you forgot to import Api.php class inside SC.php class where you call Api::getDataJSON(). As Api.php is under this ACX\lib namespace, import it as below:
<?php
namespace ACX\inc;
use ACX\lib\Api; // This needs to be imported
class SC {
// other code
public static function getDataSets(){
$data = Api::getDataJSON(); // You're calling Api.php class here
return $data;
}
// other code
}

How can i implement a factory pattern with codeigniter?

I need to implement a function called 'learn skill'. In the controller i added this code:
public function learnskill( $character_id, $skillname )
{
$this->load->model('skillfactory_model');
// Ideally i would need that the factory returns the model
// skill_parry_model so i can use it
$skill_instance = $this->skill_factory_model->create($skillname);
$skill_instance->learn($character_id);
}
How can i implement the model 'skill_factory_model' and how i can write the controller and follow CI guidelines?
Found out a way to do it:
public function learnskill( $character_id, $skillname )
{
$this->load->model('skillfactory_model');
$model = $this->skillfactory_model->create($skillname]);
$this->load->model($model);
$this->$model->learn($character_id);
}
SkillFactory_Model:
class SkillFactory_Model extends CI_Model
{
public function create($tag)
{
$class = "Skill_" . $tag . '_model';
return $class;
}
}

Class autoload not working

I'm a beginner in PHP development and I'm facing a problem in my development in PHP OO. I saw is better use the autoload() function than include each file of PHP Class.
My doubt is: Why my autoload function does not work?
Follow bellow my code:
<?php
function __autoload($class)
{
include_once "model/{$class}.class.php";
}
$avaliacaoLocal = new AvaliacaoLocal();
$avaliacaoLocal->setId(1);
$avaliacaoLocal->setIdLocal(2);
$avaliacaoLocal->setComentarios("Comentários de Pedro");
$avaliacaoLocal->setIdPessoaCliente(3);
$avaliacaoLocal->setValor(5);
var_dump($avaliacaoLocal);
File AvaliacaoLocal.class.php
<?php
namespace model;
class AvaliacaoLocal
{
private $id;
private $valor;
private $comentarios;
private $idLocal;
private $idPessoaCliente;
public function __construct(){
$this->clear();
}
public function clear(){
$this->id = 0;
$this->valor = 0;
$this->comentarios = "";
$this->idLocal = null;
$this->idPessoaCliente = null;
}
public function getId()
{
return $this->id;
}
public function setId($id)
{
$this->id = $id;
}
public function getValor()
{
return $this->valor;
}
public function setValor($valor)
{
$this->valor = $valor;
}
public function getComentarios()
{
return $this->comentarios;
}
public function setComentarios($comentarios)
{
$this->comentarios = $comentarios;
}
public function getIdLocal()
{
return $this->idLocal;
}
public function setIdLocal($idLocal)
{
$this->idLocal = $idLocal;
}
public function getIdPessoaCliente()
{
return $this->idPessoaCliente;
}
public function setIdPessoaCliente($idPessoaCliente)
{
$this->idPessoaCliente = $idPessoaCliente;
}
}
The error:
PHP Fatal error: Class 'AvaliacaoLocal' not found in C:\Users\Pedro
........\index.php on line 14
UPDATE:
When i use include the PHP returns the same error:
Fatal error: Class 'AvaliacaoLocal' not found in C:\Program
Files\VertrigoServ\www\system\index.php on line 10
i've change folder to verify if could be it.
The class is declared belonging to a namespace, you have to call it in this way:
$avaliacaoLocal = new \model\AvaliacaoLocal();
But now, the namespace is also included in $class, so the autoload function needs to handle that:
function __autoload($class)
{
$file = str_replace(array('_', '\\'), '/', $class) . '.php';
if (is_file($file)) {
require $file;
}
}
This function takes $class value and replace every \ (and _) from the namespace with a / to get the file name.

Inherited variables does not work

i have probably a really easy problem, but i dont know how to fix it now. Maybe i just forgot something, but i need your help.
I have model:
<?php
class Model
{
protected $storage;
public function __construct()
{
$this->storage = $_SERVER["DOCUMENT_ROOT"] . "/mvc/images/";
if(!file_exists($this->storage))
{
mkdir($this->storage, 0777);
}
}
public function storageHandler()
{
if(count(glob($this->storage."/*")) === 0)
{
echo "Žiadne kategórie";
}
else
{
$iterator = new DirectoryIterator($this->storage);
return $iterator;
}
}
}
?>
And model Category, which is inherited from Model.
<?php
require_once($_SERVER["DOCUMENT_ROOT"] . "/mvc/model/Model.php");
class Category extends Model
{
private $photos_count;
public function __construct($data)
{
if(isset($data))
{
$gallery_path = $this->storage . $data;
if(!file_exists($this->$storage .$data))
{
mkdir($tihs->storage . $data, 0700);
header("Location: /mvc/" );
}
else
{
echo "Kategória už existuje.";
}
}
}
}
?>
I would love to use $storage variable from Model in my Category class. How should I do that? I know some way, but it's not gonna be the best one. Is there any solution that will make this good way?
besides Ray's answer you need you use parent::__construct() in your category class like so
class Category extends Model
{
private $photos_count;
public function __construct($data)
{
parent::__construct();
//rest of the code
The protected property $storage is available to your child class, but $this is spelt wrong in your examp:
mkdir($tihs->storage . $data, 0700);
It should be:
$this->storage ...
Also, as notedby mamdouh, you need to call the parent constructor from the child to initialize:
public function __construct($data)
{
parent::_construct();
...rest of code...

How to run method inside a Model | MVC

In the index file i have _autoload and load the libs and then i explode the url to get the wanted contoller and the model if exists. In the view i can see the model __construct() so the model is loaded but if i try to use $this->model->test(); i get
Call to a member function test() on a non-object
http://site.com/about
$this->request = about;
$controller = new $this->request;
$controller->loadModel($this->request);
Everething work ok
*Here is the Main controller *
class Conroller {
function __construct() {
// echo 'Main controller<br />';
$this->view = new View();
}
public function loadModel($name) {
$path = 'models/'.$name.'_model.php';
if (file_exists($path)) {
require 'models/'.$name.'_model.php';
$modelName = $name . '_model';
// **here i make the object**
$this->model = new $modelName();
}
}
}
Here is the About model
class about_model{
function __construct() {
echo 'test';
}
public function test() {
$test = 'test one';
}
}
Here is the About Conroller
class About extends Conroller {
function __construct(){
parent::__construct();
$this->model->test();
$this->view->render('/about');
}
}
You will need to call loadModel in your About controller before you refer to the model:
class About extends Conroller {
function __construct(){
parent::__construct();
$this->loadModel('about');
$this->about->test();
}
}

Categories