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;
}
}
Related
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
I'm using repository pattern in my Laravel project.
what is the good pattern to call service from other service?
For example service will looks like this:
class GetAllUsersService
{
private $userRepository;
public function __construct(UserRepository $repository)
{
$this->userRepository = $repository;
}
public function execute()
{
return $this->userRepository->getAll();
}
}
Now if I want to execute this service from other part of the application I will do something like this:
class AnyClass
{
public function executeUserService()
{
$repository = new UserEloquentRepository();
$service = new GetAllUsersService($repository);
return $service->execute();
}
}
Is it correct way to do it? Is there other ways? Maybe some UI layer should be in between?
I think you have three ways to do it:
1) use method __construct();
class AnyClass
{
private $get_all_users_service;
public function __construct(GetAllUsersService $get_all_users_service)
{
$this->get_all_users_service = $get_all_users_service;
}
public function index()
{
$fetchAllUsers = $this->get_all_users_service->fetchAll();
}
}
2) use the specified services like a parameter of each function needs to use them:
class AnyClass
{
public function index(GetAllUsersService $get_all_users_service)
{
$fetchAllUsers = $get_all_users_service->fetchAll();
}
}
3) use method app() of Laravel helper like this:
class AnyClass
{
public function index()
{
$get_all_users_service = app(GetAllUsersService::class);
$fetchAllUsers = $get_all_users_service->fetchAll();
}
}
I need function (literally i need the $data) from this model in whole project.
when i call in some controller $data = $this->multi_language_model->multi_lang(); it work fine. But is it possible to call in one place, so I can use in every controller and view.
I autoload the model
$autoload['model'] = array('multi_language_model');
class Multi_language_model extends MY_Model
{
public function __construct() {
parent::__construct();
}
public function multi_lang() {
$data['menu_delivery'] = $this->lang->line('menu_delivery');
$data['menu_quotations'] = $this->lang->line('menu_quotations');
$data['menu_customer_service'] = $this->lang->line('menu_customer_service');
return $data;
}
}
Put this helper function in your any loaded helper:
function get_multi_lang(){
$CI = & get_instance();
$data = array();
$CI->load->helper('language');
$CI->lang->load('menu','english');
$data['menu_delivery'] = $CI->lang->line('menu_delivery');
$data['menu_quotations'] = $CI->lang->line('menu_quotations');
$data['menu_customer_service'] = $CI->lang->line('menu_customer_service');
return $data;
}
Controller:
class Yourclassname extends CI_Controller {
var $menu_delivery = "";
var $menu_quotations = "";
var $menu_customer_service = "";
function __construct() {
parent::__construct();
$data = get_multi_lang();
$this->menu_delivery = $data['menu_delivery'];
$this->menu_quotations = $data['menu_quotations'];
$this->menu_customer_service = $data['menu_customer_service'];
}
public function index(){
echo $this->menu_delivery.'<pre>';
echo $this->menu_quotations.'<pre>';
echo $this->menu_customer_service.'<pre>';die;
}
}
If you dont want to use helper function then copy helper function lines in controller __construct() [replace $data to $this->]so direct use global variables do same in model and for view pass this variable via controller
I don't know how codeigniter works but maybe you could do this method static and use it like:
class Multi_language_model extends MY_Model
{
private static $data = [];
public function get_multi_lang()
{
return [
'menu_delivery' => $this->lang->line('menu_delivery'),
'menu_quotations' => $this->lang->line('menu_quotations'),
'menu_customer_service' => $this->lang->line('menu_customer_service'),
];
}
public static function multi_lang()
{
if (empty(self::$data)) {
self::$data = (new self)->get_multi_lang();
}
return self::$data;
}
}
Then, whenever you need it, you can use $data = Multi_language_model::multi_lang();
However, I don't see anything wrong in injecting it from the container, wherever you need it. Doing so would be much easier to build tests.
BTW you don't need to overwrite the class constructor if there are no custom parameters set to the extending class. You can safely remove:
public function __construct() {
parent::__construct();
}
I have this code and i´m trying to use a object
<?php
class Controller {
public $_view;
public function __construct() {
$this->_view = new View();
return $this->_view;
}
}
class View {
public $_params = array ();
public function set_params($index_name,$valores) {
$this->_params[$index_name] = $valores;
}
public function get_param($index_name){
return $this->_params[$index_name];
}
}
?>
i would like to do this:
class Index extends Controller {
public function index() {
$model = Model::get_estancia();
$usuarios = $model->query("SELECT * FROM usuarios");
$this->_view->set_params(); // cant be used.
$this->load_view("index/index");
}
}
i would like to use the set_parms function.
but i can't see the View Function, then i can not use.
Can someone explain and advise me a good and safe way?
Correction from Phil: If a __construct() method isn't found, PHP will revert to legacy constructor syntax and check for a method with the same name as the object. In your case the method index() is being treated as the constructor, and is preventing the parent's constructor from loading the view object into the $_view property.
You can force a class to inherit a parent's constructor by defining __construct() in the child and calling the parent's constructor:
public function __construct() {
parent::_construct();
}
Here is the fixed code:
<?php
class Controller {
public $_view;
public function __construct() {
$this->_view = new View();
return $this->_view;
}
}
.
class View {
public $_params = array ();
public function set_params($index_name,$valores) {
$this->_params[$index_name] = $valores;
}
public function get_param($index_name){
return $this->_params[$index_name];
}
}
.
class Index extends Controller {
public function __construct() {
parent::__construct();
}
public function index() {
$model = Model::get_estancia();
$usuarios = $model->query("SELECT * FROM usuarios");
$this->_view->set_params(); // cant be used.
$this->load_view("index/index");
}
}
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();
}
}