Shared Functions in CI2: Helper? Library? - function

I'm still quite new to OOP, and have been learning-as-I-go with CodeIgniter2+Doctrine2.
I have a couple of shared functions that are handy in various areas of my project, so I'd like to call them. In procedural PHP I'd just stick them in a library file and call them. But that's not working for me now..
include 'function_library.php';
$name = $this -> function_library -> generate_male_name();
Message: Undefined property: Turn::$function_library
I even read somewhere that you needed to use call_function(), but that only got me:
Fatal error: Call to undefined method Turn::call_function()
So I figured maybe I should load it as a helper.
$this->load->helper('character_helper');
echo generate_male_name();
Fatal error: Using $this when not in object context in
/PATH/systemFolder/helpers/character_helper.php
on line 19
Line 19:
$query = $this->doctrine->em->createQuery("select max(u.id) from ORM\Dynasties2\Malenames u");
I considered setting it up as a Library, but honestly that begins to get a little over my head in terms of Classes and such. I have not tried it.
Here is the entirety of that function:
function generate_male_name() {
$query = $this->doctrine->em->createQuery("select max(u.id) from ORM\Dynasties2\Malenames u");
$result = $query->getSingleResult();
//echo $result2[1];
$highval = $result[1];
$random_name = rand(1,$highval);
//echo $random_name;
$name = $this->doctrine->em->find('ORM\Dynasties2\Malenames', $random_name);
return $name->getName();
}
How can I do this?
Edit:
Tried a few additional things, still no success.
I put my function_library in third_party, and did:
$this->load->add_package_path(APPPATH.'third_party/function_library/');
$name = $this -> generate_male_name();
Fatal error: Call to undefined method Turn::generate_male_name()
or $name = $this -> function_library -> generate_male_name();
Message: Undefined property: Turn::$function_library
I'm not crazy about calling it in autoloader, I don't need it everywhere, and that seems less than efficient.
I've read up on libraries, but as I said, Classes are quickly over my head and creating a new library seems more than a little daunting to me.
*What's the best solution here? How do I share a few functions? Is a library the way I need to go, or am I just missing something minor in trying to make a helper or shared_functions thing work?*

May be not an answer, only talking about CodeIgniter
Fatal error: Using $this when not in object context in
/PATH/systemFolder/helpers/character_helper.php on line 19
This happens when you try to use CI instance with $this keyword outside of object context (when CI is not instantiated). Observing the error above I can guess that you are using $this inside the helper character_helper.php that is located inside the helpers folder but outside of CI object context. To use CI object you must instantiate the CI using
$ci = & get_instance();
and use $ci instead of $this in your helper.
If you want to use your helper inside any controller then you can load it normally inside your controller as usual, i.e.
$this->load->helper('character_helper');
and if your helper has a function generate_male_name then you can call it inside your controller as follows
generate_male_name();
$this, however, only works directly within your controllers, your
models, or your views.
Creating CodeIgniter Libraries.

Related

AS3: Not getting typeError when calling a function

I'm writing my own language from ActionScript as a personal project (yeah, I guess AS3 is not the best language to build a language from, but never mind that).
NOTE: I have checked several times, and my compiler's option 'Enable Strict Mode' is set to True. I have tried setting it to False to try, but I didnt get a different result.
At any rate, I have a this:
package NodyCode.Classes
{
public class NCString
{
var value:String;
public function NCString(expression:String = "") {
value = expression;
}
public function rindex(substr:NCString, startIndex:int = 0x7fffffff):uint {
//code here
}
}
}
Since I'm writing my own language, I need to make sure functions and methods can take un unlimited number of arguments. For this reason, I'm using an anonymous function so that I can use the apply method. Like so:
//This code is in a class named ClassMethods
public static var StringMethods:Object = {
rindex: function(substr:NCString, startIndex:int = 0x7fffffff):uint {
return this.rindex(substr, startIndex);
}
}
And, somewhere else in my code, I do the call:
return ClassMethods.StringMethods["rindex"].apply(ncstr1, [ncstr2, [5]]);
I would like an error to be thrown whenever the user uses the wrong type of argument.
So, in this case, I call the rindex method on ncstr1, with arguments: substr = ncstr2 and startIndex = [5]. Notice that, according to my anonymous function's definition, startIndex is supposed to be an int, not an Array.
So, I expected an error to be thrown. Instead, though, rindex is called with startIndex = 5.
Why is [5] converted to 5, and is there any way for me to prevent that? If there isn't, I can always work around this problem, but I'd rather not if I can do otherwise.
EDIT: Finally understood that I did not mention I was using an anonymous function.
Are you compiling with strict mode set to false? (See here also.)
The strict option: "Prints undefined property and function calls; also performs compile-time type checking on assignments and options supplied to method calls".
It defaults to true, but if it got set to false somehow, compile-time checks might be disabled. I'd check your compiler settings (whether in an IDE or if you're compiling on the command-line) and make sure they're correct.
Okay, so here's what was said in the comments:
I did have my compiler on strict mode. The reason for which I was not getting an error is because I was using the apply method of an anonymous function. The type checks are loosened when using the apply method. That's why [5] was coerced to 5.
There is apparently no way to prevent this.

PHPStorm Intellisense Does Not Recognize Constants Defined in Class

Is there a way to get PhpStorm intellisense to pick up these dynamically defined constants? Given the code below, PhpStorm gives the "Undefined constant SAMPLE_CONSTANT_THAT_WAS_DYNAMICALLY_DEFINED" error message.
class ExampleConfiguration
{
private $configurationMapping;
...
public function DefineConfigConstants()
{
foreach ($this->configurationMapping as $key => $value)
define($key, $value);
}
}
class ExampleClass
{
public function Test()
{
print SAMPLE_CONSTANT_THAT_WAS_DYNAMICALLY_DEFINED;
}
}
This issue can be tracked here: https://youtrack.jetbrains.com/issue/WI-11390, what I'm looking for is suggestions for workarounds.
IDE needs to know about such constants in order to not to complain about them. This means that they have to be defined in "normal" way (actual values do not matter, as long as they are not used for file names/paths in include/require statements).
Suggestion: write custom script that create such myconstants.php file where they will be defined in a normal way (since all such constants defined by users and stored in DB, you have to fetch them from DB yourself) .. and run this script (to update generated file) before working with the code in PhpStorm.

PHP namespace behaviour gives FATAL error with spl_autoload_register

I want to use namespace and spl_autoload_register together but failed with different error each time.
Please See complete code files on github.
Below are the files
a base file where create a class with namespace class.alpha.php
an include file where I define spl_autoload_register include.php
an example file which instantiate the class object eg.php
Now when I create object from eg.php it gives FATAL error but when I comment namespace line in class.alpha.php then it's working
Please see the code below.
alpha.class.php
<?php
//namespace Alpha; //<< comment and uncomment this to regenerate the error
class Alpha
{
// public static $baseDir_;
public $dir = __DIR__;
public static $baseDir_;
public function __construct()
{
echo __FILE__."=>".__METHOD__;
var_dump(self::$baseDir_, $this->dir);
$firstDir = !empty(self::$baseDir_) ? self::$baseDir_ : $this->dir;
}
}
include.php
<?php //namespace Alpha\config;
spl_autoload_extensions(".php");
spl_autoload_register('loadclass');
function loadclass($class)
{
try {
if (is_readable(strtolower($class).".class.php")) {
include_once strtolower($class).".class.php";
}
} catch (Exception $e) {
print "Exception:". $e;
}
}
//#link http://php.net/manual/en/function.spl-autoload-register.php
// spl_autoload_register(__NAMESPACE__.'Alpha\Alpha()' );
eg.php
<?php
require_once 'include.php';
/** below code works by commenting 1st line on alpha.class.php
if we un comment then below code gives Fatal error: Class 'Alpha' not found */
Alpha::$baseDir_ = '/opt/lampp/archive/';
$obj_ = new Alpha();
var_dump(get_included_files());
var_dump($obj_);
/** now we define namespace Alpha on alpha.class.php */
// $ns_ = new Alpha\Alpha(); // Fatal error: Class 'Alpha\Alpha' not found
// var_dump($ns_);
/** not working even with use statement */
// use Alpha;
// use Alpha;
// $fn = new Alpha\Alpha();
// var_dump($fn);
Please help me out to solve this issue.
Thanks
Your autoloader is receiving a request for a class of "Alpha\Alpha" if you uncomment the namespace in alpha.class.php and place the use Alpha\Alpha in eg. This means that the location it's expecting to find your class in would be alpha\alpha.class.php.
Unless you're on Windows, directory separators are typically forward slash (/). So there's a number of possible solutions.
**Possible Solution #1 - Leave all files in the same place **
If you want to leave everything where it is now, you'll need to remove the namespace from the class names in the autoloader. If you add these lines to the top of your autoloader, that will make it behave that way:
$classParts = explode("\\", $class);
$class = $classParts[count($classParts) - 1];
I would not recommend this solution though since it means that you can no longer provide the same class name in a different namespace.
Possible Solution #2 - Put namespaces in subdirectories
For this solution, you'd create a new directory "alpha" and move "alpha.class.php" into it. For autoloader changes, you can add the following lines to the top of your autoloader:
$class = str_replace("\\", "/", $class);
This will change the namespace separators from backslashes to file path separators with forward slash. This will work on windows as well as mac and linux.
Possible Solution #3 - Follow an established autoloading standard
There are already a number of standard PHP autoloading standards. PSR-0 (now deprecated) works, but PSR-4 would be recommended:
PSR-0: http://www.php-fig.org/psr/psr-0/
PSR-4: http://www.php-fig.org/psr/psr-4/
One big upside of following one of these standards is that there are already plenty of implementations for them and there's been a lot of thought put into how they should work and maintain compatibility with other libraries you may end up wanting to use. Composer (http://getcomposer.org) will allow you to set up and use both PSR-0 and PSR-4 style autoloaders based on a very simple configuration.
Anyway, for the TL;DR crowd, the issue is that the autoloader receives the entire namespaced path in order to know how to load the class. The fatal error was because the autoloader wasn't properly mapping from that namespaced class to a file system location, so the file containing the class was never being loaded.
Hope this helps.

Doctrine 2 namespace issue

I'm using Zend Framework 1 with the Bisna library to integrate Doctrine 2. I generated my Entities from my database model with the Doctrine 2 CLI. This is all working fine, except for the setter methods for associated records. The argument they accept must be of a specific namespace (\Category here).
class Article
{
public function setCategory(\Category $category = null) {
$this->category = $category;
return $this;
}
}
However, when I do this:
$article = $this->em->getRepository('\Application\Entity\Article')->find(1);
$category = new \Application\Entity\Category();
$category->SetName('New Category');
$article->setCategory($category);
I get the following fatal error: Argument 1 passed to Application\Entity\CategoryField::setCategory() must be an instance of Category, instance of Application\Entity\Category given.
When I change the setter method to accept \Application\Entity\Category objects, it's working of course. Should I do this for every generated method, or are there other options? This is the first time I'm using namespaces, so it might be something simple.
You can always add this to the top of your class file: use \Application\Entity\Category; and then simply reference it later like so: public function setCategory(Category $category = null)
Check out: http://php.net/manual/en/language.namespaces.importing.php for more info about use
Otherwise you would have to reference the full namespace otherwise your application does not know that \Category is a reference to \Application\Entity\Category

creating functions in CodeIgniter controllers

I have a CodeIgniter application, but one of my controllers must call a data processing function that I have also written myself. The only problem is I can't seem to figure out how to do this. Looking through the user guide it seems that I should put my function inside the class declaration, and prefix it with an underscore (_) so that it cannot be called via the url. However, this is not working. Here's an example of what I mean:
<?php
class Listing extends Controller
{
function index()
{
$data = "hello";
$outputdata['string'] = _dprocess($data);
$this->load->view('view',$outputdata);
}
function _dprocess($d)
{
$output = "prefix - ".$d." - suffix";
return $output
}
}
?>
The page keeps telling me I have a call to an undefined function _dprocess()
How do I call my own functions?
Thanks!
Mala
Edit:
I've gotten it to work by placing the function outside of the class declaration. Is this the correct way of doing it?
This line is creating problem for you:
$outputdata['string'] = _dprocess($data);
Replace with:
$outputdata['string'] = $this->_dprocess($data);