How to implement a method in a class that can be used by everyone users in php ?
My idea is not to repeat the implementation of readsales in each of the entities
i have 3 users:
admin readSales function,
manager readSales function,
employee, insertSale AND readSales function
Is it possible to implement common methods in a single class? And then call each of the methods to the daughter classes?
abstract class commonMethods {
abstract readSales() {
$pdo = new PDO();
//statements
//readSales
//return $list;
}
}
class Manager extends commonMethods {
function readSales(){
return readSales();
}
}
Yes this is possible, what you need is either a trait or an abstract class.
Here's an example with Abstract class :
<?php
/**
* The abstract class
*/
abstract class CommonMethods
{
public function readSales(){
// Your code
}
public function hello(){
echo "Hello";
}
}
/**
* The Class
*/
class Manager extends CommonMethods
{
// No need to add the "readSales" or "hello" method
// Since we had extended them
public function world(){
echo "World";
}
}
$Manager = new Manager;
$Manager->readSales(); // Works!
$Manager->hello(); // Output: "Hello"
$Manager->world(); // Output: "World"
// The final output: "HelloWorld"
Reference: http://php.net/manual/en/language.oop5.abstract.php
Related
I try to fetch data from database in codeigniter construct function
but getting undefined method error
controller-
class Welcome extends CI_Controller
function __construct()
{
parent::__construct();
$this->load->model('Login');
$this->Login->getadminnav();
}
}
model-
class Login extends CI_Model
{
public function adminnav()
{
$query="SELECT * from adminnav where status='1'";
$query->row_array();
return true;
}
}
You got to load the model you are using first:
$this->load->model('login_model');
$this->Login->getadminnav();
And remember to rename the model to Login_model
Try these pieces of code.
Controller:
class Welcome extends CI_Controller{
function __construct(){
parent::__construct();
$this->load->model('Login');
$this->Login->adminnav();
}
}
Model:
class Login extends CI_Model{
public function adminnav(){
$this->load->database();
$sql = "SELECT * from adminnav where status='1'";
$result = $this->db->query($sql);
return $result;
}
}
I am seeing in your code that-
In controller you didn't start the second bracket after controller name.
You defined the function name as "adminnav" in model but called it as "getadminnav" in Controller
You didn't load the database in model (If you already loaded it in autoload.php then here is not needed)
Anyway please let me know whether your problem is solved or not.
you are calling getadminnav() but in your model the method name is adminnav.and change model name Login to Login_model.
try this:
class Welcome extends CI_Controller{
function __construct(){
parent::__construct();
$this->load->model('Login_model');
$this->Login->adminnav();
}
}
// model
class Login_model extends CI_Model{
public function adminnav()
{
$query="SELECT * from adminnav where status='1'";
$query->row_array();
return true;
}
}
i made controller name crud.php this the code :
class Crud extends CI_Controller{
function __construct(){
parent::__construct();
$this->load->model('m_data');
$this->load->helper('url');
}
public function admin(){
$data['produk'] = $this->m_data->tampil_data()->result();
$this->load->view('v_admin',$data);
}
}
i want take the admin() to place in admin.php code here :
class Admin extends CI_Controller{
function __construct(){
parent::__construct();
if($this->session->userdata('status') != "login"){
redirect(base_url("login"));
}
}
function index(){
$this->crud->admin();
}
}
what's code for take another function in another controller.. that's possible or not?
You could try to require Crud controller within Admin controller :
public function index()
{
require_once('crud.php');
$crud = new crud();
$crud->admin();
}
I do not know if I understood your question very well, but you could have the controller Admin extend the Crud controller, so he would have access to the admin ()
class Admin extends Crud{
function __construct(){
parent::__construct();
if($this->session->userdata('status') != "login"){
redirect(base_url("login"));
}
}
function index(){
$this->admin();
}
}
Loading another controller inside a controller is a bad idea. It can lead to hard to find bugs. One solution is to make Crud a custom library that the controller loads.
File: /application/libraries/Crud.php
class Crud
{
protected $CI;
public function __construct()
{
$this->CI = & get_instance();
$this->CI->load->model('m_data');
$this->CI->load->helper('url');
}
public function admin()
{
$data['produk'] = $this->CI->m_data->tampil_data()->result();
$this->CI->load->view('v_admin', $data);
}
}
Then the controller loads and uses the custom class.
class Admin extends CI_Controller{
public function __construct(){
parent::__construct();
if($this->session->userdata('status') != "login"){
redirect(base_url("login"));
}
}
public function index()
{
$this->load->library('crud');
$this->crud->admin();
}
}
You could load crud in the constructor too. That would make sense if other methods in the controller use the library.
May it can be useful for you, if you will customize your code in the view:
VIEW
your-link-to-another-controller
I imagine I might need to add a special annotation somewhere, but I'm crossing my fingers that PhpStorm is smart enough to resolve return types given awkward inheritance patterns.
For example, I have some code that resembles this:
<?php
class Collection extends \ArrayObject
{
public function __construct(array $items)
{
foreach ($items as $key => $value) {
if (isset(static::$requiredType) && !$item instanceof static::$requiredType)
$this->offsetSet($key, $value);
}
}
public function getFirst()
{
return $this->offsetGet(0);
}
}
class MessageCollection extends Collection
{
protected static $requiredType = 'Message';
}
class UserCollection extends Collection
{
protected static $requiredType = 'User';
}
I'd like it if when I call UserCollection::getFirst() it inferred that a User was returned, while when I call MessageCollection::getFirst() it inferred that a Message was returned. Is there some annotation I could put in somewhere to achieve this result?
My first thought was something like this:
/**
* #return Message|User|XXXX|YYYY|ZZZZ|AAAA|BBBB|CCCC|DDDD
*/
public function getFirst()
{
return $this->offsetGet(0);
}
but I imagine that would get a little ridiculous to the point of being useless as I add more collection classes.
Try this:
/**
* #method \User getFirst()
*/
class UserCollection extends Collection
{
protected static $requiredType = 'User';
}
I would like to trigger some events in my model, if I register my events via app->on in index.php then I don't receive required $event->data from event object.
How register my events handlers, so when I call trigger it will call correct function with event object.
Code sample:
namespace app\modules\Product\models\Product;
class Product extends Entity\Entity {
public static function tableName() {
return 'sometable';
}
public function afterFind() {
parent::afterFind();
$event = new yii\base\Event;
$event->data = $this;
$this->trigger('calculatePrice', $event);
}
}
namespace app\modules\PriceRules\models;
class PriceRules extends yii\base\Model {
public static function calculatePrice($event) {
$entity = $event->data;
}
}
//somehow register events
Add in Product in method init this code:
class Product extends Entity\Entity {
public function init()
{
$this->on('calculatePrice', ['app\modules\PriceRules\models\PriceRules', 'calculatePrice']);
}
...
}
See doc - http://www.yiiframework.com/doc-2.0/guide-concept-events.html
I found solution. I placed PriceRules module inside bootstrap and added this code there:
yii\base\Event::on(Product::className(), 'calculatePrice', [PriceRulesEvent::className(), 'calculatePrice']);
How can I use a ninject factory, which creates an instance with constructor parameters, without relying on the argument names.
The problem is that the ToConstructor()-Method not works, because I bind it to a generic definition.
The following example works, if I use the factory method with the corresponding constructor argument name, but I don't like it rely on names.
Because the following solution is very fragil and breaks if someone chooses a wrong name or renames the ctor-argument in the derived class.
Any solution?
Here's the example code:
[TestFixture]
public class NinjectFactoryBindingsTest
{
[Test]
public void ConstructorSelectionWithArguments()
{
NinjectSettings ninjectSettings = new NinjectSettings();
ninjectSettings.LoadExtensions = false;
using (var kernel = new StandardKernel(ninjectSettings, new FuncModule()))
{
// IDependencyA will be passed to the factory, therefore it is not bounded
//kernel.Bind<IDependencyA>().To<DependencyA>();
kernel.Bind<IDependencyB>().To<DependencyB>();
kernel.Bind(typeof(IGenericBaseClass<>)).To(typeof(GenericDerivedClass<>));
kernel.Bind<IGenericClassFactory>().ToFactory();
IGenericClassFactory factory = kernel.Get<IGenericClassFactory>();
DependencyA dependencyA = new DependencyA();
IGenericBaseClass<GenericImpl> shouldWorkInstance = factory.Create<GenericImpl>(dependencyA);
Assert.NotNull(shouldWorkInstance);
}
}
}
public interface IGenericClassFactory
{
IGenericBaseClass<TGeneric> Create<TGeneric>(IDependencyA someName) where TGeneric : IGeneric;
// This works, but relies on ctor-param-names!!!
// IGenericBaseClass<TGeneric> Create<TGeneric>(IDependencyA otherNameThanInBaseClass) where TGeneric : IGeneric;
}
public class DependencyA : IDependencyA
{
}
public class DependencyB : IDependencyB
{
}
public class GenericDerivedClass<TGeneric> : GenericBaseClass<TGeneric> where TGeneric : IGeneric
{
public GenericDerivedClass(IDependencyA otherNameThanInBaseClass, IDependencyB dependencyB)
: base(otherNameThanInBaseClass, dependencyB)
{
}
}
public abstract class GenericBaseClass<TGeneric> : IGenericBaseClass<TGeneric> where TGeneric : IGeneric
{
protected GenericBaseClass(IDependencyA dependencyA, IDependencyB dependencyB)
{
}
}
public interface IGenericBaseClass<TGeneric> where TGeneric : IGeneric
{
}
public interface IDependencyB
{
}
public interface IDependencyA
{
}
public class GenericImpl : IGeneric
{
}
public interface IGeneric
{
}
The factory extension has the convention that arguments must have the same name as the constructor argument they will be passed to. There are no easy ways to do it differently. The only way I can think of is about the following:
Create a new IParameter implementation that can hold a reference to an IDependencyA.
Create either a hardcoded factory or a custom IInstanceProvider (see documentation) that creates an instance of your IParameter implementation so that it is passed to the Get<> request
Add a new binding for IDependencyA: Bind<IDependency>().ToMethod(ctx => extract and return your parameter from the context)