I am running php 5.2.12 and Zend Framework 5.0.2
In my Bootstrap.php, I initialize our database connection, and initialize our logger... placing both in the registry.
However, when I try to log info in the IndexController.php, it gives the following message:
"*Fatal error: Call to undefined method Zend_Config::insert() in /usr/local/zendsvr/share/ZendFramework/library/Zend/Log/Writer/Db.php on line 137*"
At the bottom of this post, you will find the Zend Framework's class file, db.php , and the _write function being called.
I believe the problem is that I am getting the database connection options from my application.ini... and there is no insert() function defined in my application.ini for the database. But I dont really know how to add one to the config, or how I should be doing this.
Bootstrap.php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initConfig()
{
Zend_Registry::set('config', new Zend_Config($this->getOptions()));
}
protected function _initDatabases()
{
$this->bootstrap('multidb');
$resource = $this->getPluginResource('multidb');
$databases = Zend_Registry::get('config')->resources->multidb;
foreach ($databases as $name => $adapter)
{
$db_adapter = $resource->getDb($name);
Zend_Registry::set($name, $db_adapter);
}
}
protected function _initLog()
{
$db = Zend_Registry::get('config')->resources->multidb->as400;
$columnMapping = array('ILGID' => 'id', //1 numeric
'ILGLVL' => 'priority', //2 numeric
'ILGDTE' => 'date', //yymmdd
'ILGTME' => 'time', //hhmmss
'ILGPGM' => 'program', //40 alnum
'ILGURL' => 'url', //2100
'ILGUSR' => 'user', //30
'ILGMSG' => 'message'); //1000
$writer = new Zend_Log_Writer_Db($db, 'dwhlib.intralog', $columnMapping);
$logger = new Zend_Log($writer);
$date = new Zend_Date();
date_default_timezone_set('America/Chicago');
$logger->setEventItem('id' , 1);
$logger->setEventItem('date' , $date->get('Ymd'));
$logger->setEventItem('time' , $date->get('Hms'));
$logger->setEventItem('program' , 'testProgramName'); $logger->setEventItem('url' , $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
$logger->setEventItem('user' , gethostbyaddr($_SERVER['REMOTE_ADDR']));
Zend_Registry::set('logger', $logger);
}
}
application.ini
resources.multidb.as400.adapter = "db2"
resources.multidb.as400.host = "i5"
resources.multidb.as400.username = "removedUsername"
resources.multidb.as400.password = "removedPassword"
resources.multidb.as400.dbname = "*LOCAL"
resources.multidb.as400.default = true
IndexController.php
include("/www/zendserver/htdocs/development/application/models/as400.php");
class IndexController extends Zend_Controller_Action
{
public function init()
{
Zend_Registry::get('logger')->info("this is a test message");
}
public function indexAction()
{
// action body
}
}
as400.php
Class default_Model_As400 extends Zend_Db {
public static function ExecuteSelect($sql, $mode = Zend_Db::FETCH_ASSOC, $log = false)
{
$stmt = self::getStmt($sql);
$stmt->setFetchMode($mode);
$stmt->execute();
if($log === true) {
Zend_Registry::get('logger')->info($sql);
}
$rows = $stmt->fetchAll();
return $rows;
}
private static function getStmt($sql){
$db = Zend_Registry::get('config')->resources->multidb->as400;
$abstractAdapter = new Zend_Db_Adapter_Db2($db);
return new Zend_Db_Statement_DB2($abstractAdapter, $sql);
}
public function insert($libAndFile, $arrData){
echo "this was hit!!";
}
}
db.php
class Zend_Log_Writer_Db extends Zend_Log_Writer_Abstract
{
public function __construct($db, $table, $columnMap = null)
{
$this->_db = $db;
$this->_table = $table;
$this->_columnMap = $columnMap;
}
protected function _write($event)
{
if ($this->_db === null) {
require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception('Database adapter is null');
}
if ($this->_columnMap === null) {
$dataToInsert = $event;
} else {
$dataToInsert = array();
foreach ($this->_columnMap as $columnName => $fieldKey) {
$dataToInsert[$columnName] = $event[$fieldKey];
}
}
$this->_db->insert($this->_table, $dataToInsert);
}
}
What is happening: you are calling a method called insert() on a Zend_Config instance.
What you want: call a method insert() through a Zend_Db_Adapter.
There is something wrong in your _initLog() bootstrap method:
$db = Zend_Registry::get('config')->resources->multidb->as400;
$writer = new Zend_Log_Writer_Db($db, 'dwhlib.intralog', $columnMapping);
Zend_Log_Writer_Db expects a Zend_Db adapter as a first constructor parameter. To fix this, since you already registered your database adapter in the registry, you should do something like this :
$dbName = Zend_Registry::get('config')->resources->multidb->as400;
$db = Zend_Registry::get($dbName);
$writer = new Zend_Log_Writer_Db($db, 'dwhlib.intralog', $columnMapping);
Related
I've got a PHP class which contains different methods:
namespace App\Controllers;
class SuperAdminController extends Controller {
public function name1Action($wanted = ''){
$o = new name1Controller();
self::routeWanted($wanted,$o,$this);
}
...
public function name10Action($wanted = ''){
$o = new name10Controller();
self::routeWanted($wanted,$o,$this);
}
private function routeWanted($wanted,$o,$that){
switch($wanted){
do something...
}
}
}
How can I group all my public function as one function like
public function name1Action ... name10Action($wanted = ''){
$o = new name1Controller();
self::routeWanted($wanted,$o,$this);
}
You probably want __call Magic.
class SuperAdminController extends Controller {
public function __call($name, $args){
// list of method names
$mNames = [
'name1Action' => 1,
'name2Action' => 2,
'name3Action' => 3,
/* ... */
];
if (isset($mNames[$name])) {
$o = new {$name}();
return $this->nameAction($args[0], $o);
}
}
protected function nameAction($wanted = '', $o){
self::routeWanted($wanted,$o,$this);
}
}
You could use variable variables to solve this:
function Action($controller, $wanted = '') {
$c = "{$controller}Controller";
$o = new $c();
// ...
}
then you could use:
$s = new SuperAdminController();
$s->Action('name1');
Demo on 3v4l.org
change your code like the below:
namespace App\Controllers;
class SuperAdminController extends Controller {
// public function name1Action($wanted = ''){
// $o = new name1Controller();
// self::routeWanted($wanted,$o,$this);
// }
...
// public function name10Action($wanted = ''){
// $o = new name10Controller();
// self::routeWanted($wanted,$o,$this);
// }
public function beforeRouteWanted($wanted, $number) {
$class = 'name' . $number . 'Controller';
$o = new $class();
self::routeWanted($wanted, $o, $this);
}
private function routeWanted($wanted,$o,$that){
switch($wanted){
do something...
}
}
}
I am making a web export from our program to OpenCart. I am trying to log in, but i get this error message:
PHP Fatal error: Call to a member function get() on null in /home/key2demo/domains/key2datafeed.com/public_html/ocdemoshops/oc23/system/engine/controller.php on line 10
We find out that the constructor in child class overwrites the one in parent. So parent constructor does not run and does not set this->registry.
The code in the controller is:
<?php
abstract class Controller {
protected $registry;
public function __construct($registry) {
$this->registry = $registry;
}
public function __get($key) {
return $this->registry->get($key);
}
public function __set($key, $value) {
$this->registry->set($key, $value);
}
}
This is The code i made:
define("VERSION", "1.0");
define("LANGUAGE", "1");
if (is_file('./../admin/config.php')) {
require_once('./../admin/config.php');
}
require_once(DIR_SYSTEM . 'startup.php');
$application_config = 'admin';
$registry = new Registry();
$loader = new Loader($registry);
$registry->set('load', $loader);
$config = new Config();
$config->load('default');
$config->load($application_config);
$registry->set('config', $config);
$registry->set('request', new Request());
$response = new Response();
$response->addHeader('Content-Type: text/html; charset=utf-8');
$registry->set('response', $response);
$registry->set('cache', new Cache($config->get('cache_type'), $config-
>get('cache_expire')));
$registry->set('url', new Url($config->get('site_ssl')));
$language = new Language($config->get('language_default'));
$language->load($config->get('language_default'));
$registry->set('language', $language);
$registry->set('document', new Document());
$event = new Event($registry);
$registry->set('event', $event);
if ($config->get('db_autostart')) {
$registry->set('db', new DB($config->get('db_type'), $config-
>get('db_hostname'), $config->get('db_username'), $config-
>get('db_password'), $config->get('db_database'), $config-
>get('db_port')));
}
if ($config->get('session_autostart')) {
$session = new Session();
$session->start();
$registry->set('session', $session);
}
if ($config->has('action_event')) {
foreach ($config->get('action_event') as $key => $value) {
$event->register($key, new Action($value));
}
}
if ($config->has('config_autoload')) {
foreach ($config->get('config_autoload') as $value) {
$loader->config($value);
}
}
if ($config->has('language_autoload')) {
foreach ($config->get('language_autoload') as $value) {
$loader->language($value);
}
}
if ($config->has('library_autoload')) {
foreach ($config->get('library_autoload') as $value) {
$loader->library($value);
}
}
if ($config->has('model_autoload')) {
foreach ($config->get('model_autoload') as $value) {
$loader->model($value);
}
}
class K2P_API_OCWRITER extends Controller
{
private $errors;
private $admin;
private $adminValidated;
private $adminShops;
public function __construct()
{
$this->errors = array();
}
public function doLog($message)
{
file_put_contents('./key2_log.txt', $message, FILE_APPEND);
}
public function login($usr, $pwd)
{
if ($this->user->login($usr, $pwd)) {
return true;
$this->doLog('logged in');
} else {
$this->doLog('Failed to login, please supply a valid
username/password and check your webshop url');
die;
}
}
public function getLanguages()
{
}
}
$db = new DB(DB_DRIVER, DB_HOSTNAME, DB_USERNAME, DB_PASSWORD, DB_DATABASE);
$registry->set('db', $db);
$registry->set('user', new Cart\User($registry));
$registry->set('tax', new Cart\Tax($registry));
$myAPI = new K2P_API_OCWRITER($registry);
$myAPI->config->set("config_language_id",LANGUAGE);
$command = $myAPI->cleanPost($_POST['command']);
$steps = $myAPI->cleanPost($_POST['steps']);
$page = $myAPI->cleanPost($_POST['page']);
$usr = $myAPI->cleanPost($_POST['usr']);
$pwd = $myAPI->cleanPost($_POST['pwd']);
//$myAPI->doLog(PHP_EOL . 'pages: ' . $page);
//$myAPI->doLog(PHP_EOL . 'steps: ' . $steps);
$totalProducts = $myAPI->getProductCount();
if ($myAPI->checkInput($usr,$pwd,$command,$page,$steps)) {
if ($myAPI->login($usr, $pwd)) {
switch($command){
case "getCategoryCount":
echo json_encode($myAPI->getCategoryCount(),JSON_FORCE_OBJECT
| JSON_UNESCAPED_SLASHES);
break;
case "getProductCount";
echo json_encode($myAPI->getProductCount(),JSON_FORCE_OBJECT |
JSON_UNESCAPED_SLASHES);
break;
case "getCategories":
echo json_encode($myAPI->getCategories($steps, $page,
JSON_FORCE_OBJECT | JSON_UNESCAPED_SLASHES));
break;
case "getProducts":
echo json_encode($myAPI->getProducts($steps, $page,
JSON_FORCE_OBJECT | JSON_UNESCAPED_SLASHES));
break;
default:
echo "Invalid command!";
break;
}
}
}
If i add parent::__construct(); to it. It still don't work. I didn't know by which one I had to add it, so i tried both.
When i added parent::__construct(); to the controller like this:
<?php
abstract class Controller {
protected $registry;
public function __construct($registry) {
parent::__construct();
$this->registry = $registry;
}
public function __get($key) {
return $this->registry->get($key);
}
public function __set($key, $value) {
$this->registry->set($key, $value);
}
}
Then i get this error message:
PHP Fatal error: Call to a member function get() on null in /home/key2demo/domains/key2datafeed.com/public_html/ocdemoshops/oc23/system/engine/controller.php on line 11
And if i add it to my made code like this:
public function __construct()
{
parent::__construct();
$this->errors = array();
}
Then i get this error messages:
PHP Warning: Missing argument 1 for Controller::__construct(), called in /home/key2demo/domains/key2datafeed.com/public_html/ocdemoshops/oc23/key2publish/k2p_api_OCwriter.php on line 95 and defined in /home/key2demo/domains/key2datafeed.com/public_html/ocdemoshops/oc23/system/engine/controller.php on line 5
PHP Notice: Undefined variable: registry in /home/key2demo/domains/key2datafeed.com/public_html/ocdemoshops/oc23/system/engine/controller.php on line 6
PHP Fatal error: Call to a member function get() on null in /home/key2demo/domains/key2datafeed.com/public_html/ocdemoshops/oc23/system/engine/controller.php on line 10
Does anyone know how to fix this? I would like to hear.
Thanks!
Constructor of your Controller class takes $registry as argument. So when you call __construct of Controller class, you need to call it like:
parent::__construct($registry);
So, your constructor for K2P_API_OCWRITER which Controller can be:
class K2P_API_OCWRITER extends Controller
{
public function __construct($registry)
{
// pass `$registry` to parent `__construct`
parent::__construct($registry);
$this->errors = array();
}
}
And instantiating an object of K2P_API_OCWRITER is still:
$myAPI = new K2P_API_OCWRITER($registry);
And btw there's no need to write parent::__construct(); in Controller constructor, as it does not extend any classes, so it does not have parent.
I have this code:
class Service {
public function get_session($token) {
foreach ($this->config->sessions as $session) {
if ($token == $session->token) {
$session->last_access = date('r');
return $session;
}
}
return null;
}
public function mysql_connect($token, $host, $username, $password, $db) {
if (!$this->valid_token($token)) {
throw new Exception("Access Denied: Invalid Token");
}
// will throw exception if invalid
$this->mysql_create_connection($host, $username, $password, $db);
$session = $this->get_session($token);
$id = uniqid('res_');
if (!isset($session->mysql)) {
$session->mysql = new stdClass();
}
$mysql = &$session->mysql;
$mysql->$id = array(
'host' => $host,
'user' => $username,
'pass' => $password,
'name' => $db
);
return $id;
}
public function mysql_close($token, $res_id) {
if (!$this->valid_token($token)) {
throw new Exception("Access Denied: Invalid Token");
}
$session = $this->get_session($token);
if (!(isset($session->mysql->$res_id))) {
throw new Exception("Invalid resource id");
}
unset($session->mysql->$res_id);
if (empty((array)$session->mysql)) {
unset($session->mysql); // this don't work, don't know why
throw new Exception('isset($session->mysql) == ' .
(isset($session->mysql) ? 'true' : 'false'));
}
}
}
I call unset($session->mysql); if it's empty but the object is not removed, the exception throw true, How can I delete $session->mysql object? I've tried to add & in get_session but this didn't help.
Whole code can be found here.
You really should have posted your Session class in your post instead of linking to your GitHub repo... that's why the comments are confusing. You are using magic methods on your session class.
1 change I made: adding the magic __unset method.
Also, I had thought the constructor needed to be public but on further looking at it I was wrong about that (so my test code will not work unless the constructor is public... anyway...).
Here is the code below with the updated class:
<?
class Session {
public $storage;
public $token;
public $username;
public $browser;
public $start;
public $last_access;
private function __construct($u, $t, $s = null, $b = null, $d = null) {
$this->storage = $s ? $s : new stdClass();
$this->username = $u;
$this->token = $t;
$this->browser = $b ? $b : $_SERVER['HTTP_USER_AGENT'];
$this->start = $d ? $d : date('r');
}
function &__get($name) {
return $this->storage->$name;
}
function __set($name, $value) {
$this->storage->$name = $value;
}
function __isset($name) {
return isset($this->storage->$name);
}
function __unset($name) {
echo "Unsetting $name";
unset($this->storage->$name);
}
static function create_sessions($sessions) {
$result = array();
foreach ($sessions as $session) {
$result[] = new Session($session->username,
$session->token,
$session->storage,
$session->browser,
$session->start);
}
return $result;
}
static function cast($stdClass) {
$storage = $stdClass->storage ? $stdClass->storage : new stdClass();
return new Session($stdClass->username,
$stdClass->token,
$storage,
$stdClass->browser,
$stdClass->start);
}
static function new_session($username) {
return new Session($username, token());
}
}
And some test code:
$session = new Session('joe', '1234');
$session->mysql = 1234;
var_dump($session->mysql);
unset($session->mysql);
var_dump($session->mysql);
This is code of the added method:
function __unset($name) {
echo "Unsetting $name";
unset($this->storage->$name);
}
Check out the documentation to about the magic __unset method you need to add to your class:
http://php.net/manual/en/language.oop5.overloading.php#object.unset
__unset() is invoked when unset() is used on inaccessible properties.
User::updatemain($set, $where);
This gives Fatal error: Using $this when not in object context
My user class extends from Dbase class and here is user class function:
public static function activate($set, $where) {
return $this->updatemain($set, $where);
here is dbase class (some part of):
private function query($sql = null, $params = null) {
if (!empty($sql)) {
$this->_last_statement = $sql;
if ($this->_db_object == null) {
$this->connect();
}
try {
$statement = $this->_db_object->prepare($sql, $this->_driver_options);
$params = Helper::makeArray($params);
$x = 1;
if (count($params)) {
foreach ($params as $param) {
$statement->bindValue($x, $param);
$x++;
}
}
if (!$statement->execute() || $statement->errorCode() != '0000') {
$error = $statement->errorInfo();
throw new PDOException("Database error {$error[0]} : {$error[2]}, driver error code is {$error[1]}");
exit;
}
//echo $sql;
return $statement;
} catch (PDOException $e) {
echo $this->formatException($e);
exit;
}
}
}
public function updatemain($set, $where) {
return $this->query($sql, $params);
}
this is part of Dbase class
You are calling static method so there is no $this in that context.
If you want to call other static method from given class then use self::method() but if you want to call non-static method you've got problem. First you have to create new object.
When you use static methods, you can't use $this inside
public static function activate($set, $where) {
return self::updatemain($set, $where);
}
Or you have to use singelton design
EDIT
Best solution - rewrite your class to one point access to DB object. And create Model classes to DB access. See my example code below:
core AppCore
<?php
class AppCore
{
public static $config = array();
public static $ormInit = false;
public static function init($config)
{
self::$config = array_merge(self::$config, $config);
}
public static function db($table)
{
// ORM - see http://idiorm.readthedocs.org/en/latest
if (!self::$ormInit) {
ORM::configure(self::$config['db']['connection']);
ORM::configure('username', self::$config['db']['username']);
ORM::configure('password', self::$config['db']['password']);
self::$ormInit = true;
}
return ORM::for_table($table);
}
}
User model
<?php
class UserModel
{
const TABLE = 'user';
public static function findById($u_id)
{
$result = AppCore::db(self::TABLE)->where('u_id', $u_id)->find_one();
return $result ? $result->as_array() : null;
}
}
AppCore init section
AppCore::init(array(
'db' => array(
'connection' => "mysql:dbname={$db};host={$host}",
'username' => $user,
'password' => $pass
),
));
i hope it help make your code better
I am having some problem with scope i assume, but i cannot for the life of me figure out what that problem is...
I keep getting a function undefined error for the following three functions whenever they are called; addUser, removeUser, updatePlayer. Anyone have any idea what's wrong? full code below (it is a pocketmine plugin):
<?php
/*
__PocketMine Plugin__
name=X
description=X
version=0.0.1
author=X
class=X
apiversion=10
*/
class X implements Plugin {
private $api;
public $continents = array();
public $allContinents = array("NA" => 0, "SA" => 0, "AF" => 0, "AS" => 0, "OC" => 0, "EU" => 0);
public function __construct(ServerAPI $api, $server = false){
$this->api = $api;
}
public function init(){
//Initialize the on player join event handler
$this->api->addHandler("player.spawn", array($this, "onPlayerJoin"));
$this->api->addHandler("player.quit", array($this, "onPlayerQuit"));
//Setup Config
$this->path = $this->api->plugin->configPath($this);
$this->msgs = new Config($this->path . "config.yml", CONFIG_YAML, array("AuthToken" => "", "Delay" => "5"));
$this->msgs = $this->api->plugin->readYAML($this->path . "config.yml");
}
// <--- updatePlayer --->
public function updatePlayer($user) {
}
// <--- Country Handler --->
public function addUser($user, $continents, $allContinents) {
$ip = $user->ip;
$username = $user->username;
$gi = geoip_open($this->path ."GeoIP.dat",GEOIP_STANDARD);
$continent = geoip_continent_code_by_name($gi, $ip);
array_push($continents, $username);
$continents[$username] = $continent;
$allContinents[$continent] += 1;
return $continents;
return $allContinents;
}
public function removeUser($user, $continents, $allContinents) {
$username = $user->username;
$continent = $continents[$username];
unset($continents[$username]);
$allContinents[$continent] -= 1;
return $continents;
return $allContinents;
}
// <--- Rquest Ad --->
public function requestAd() {
}
/*public function send() {
while(true) {
sleep(240);
}
}
}*/
//On player join event handler
public function onPlayerJoin($user){
$username = $user->username;
addUser($user);
updatePlayer($user);
//Check if plugin is setup
if ($this->api->ban->isOp($username) && $this->msgs["AuthToken"] == "") {
$this->api->chat->sendTo(false, "Please visit X to setup X.", $username);
}
}
public function onPlayerQuit($user){
removeUser($user);
}
public function __destruct(){
}
}
?>
If you're calling them from the same class or an extended class then you need to use $this.
public function onPlayerJoin($user){
$username = $user->username;
$this->addUser($user);
$this->updatePlayer($user);
}
Unless it's a static function, then you would use self::.
You need to instantiate an instance of class X, then call the functions as members of that object. For example:
$myX = new X();
$myX->addUser();
Cheers