CodeIgniter - Private functions - codeigniter

I have started playing with CodeIgniter now.
And I use their user guide and other third-party tutorials available for learning. I'm a bit stuck at the naming of private functions. Based on the user guide, I have to prefix a _ in the name of private functions. But in this tutorial, check the Add Logout section. In it, there is a private function: private function check_isvalidated(). Here, it is not prefixed with the character _.
So that's also an accepted naming convention ?
At the same time, there is another one called _output(): Processing Output.
It's a public function with the naming convention of a private function !
It's a bit of confusing when I try to learn in a systematic manner.

The _ prefix is a convention for functions defined in the CONTROLLER.
The user guide says:
In some cases you may want certain functions hidden from public access. To make a function private, simply add an underscore as the name prefix and it will not be served via a URL request.
http://www.codeigniter.com/user_guide/general/controllers.html#private-methods
Adding an _ is CodeIgniter's own way of declaring functions in the controller (only in the controller) that cannot be called directly by the user:
Controller functions are mapped to parts of the URL (controller/function)
there are functions in the controller which should NOT be mapped to the URL
- they are declared as `private` (available since PHP5)
OR
- their names start with `_` (works also for PHP4)
Regarding _output function, it is public, but it cannot be called directly since it contains _.
Why is public?
The function is called by the system, so it needs to be accessible from outside the class, it is not a private function. But, it contains _ to make sure it is not called via the URL.
To sum up, if you have functions in your controller which you don't want to be called directly via the url, add _ prefix OR use the private access operator. Either one of them is good enough.
FYI, other frameworks like Yii or Zend framework, use the action prefix for all controller functions which CAN be called via the URL (are mapped).

While the user guide does say that you have to prefix the function name for private functions inside a controller with an underscore, it is not mandatory to do so. Although, it might be a good idea to follow the convention and it is recommended that you do so.
The noticeable effect when prefixing the function name with an underscore can be seen if the access modifier is public. In this case, if you try to access the function via URL will give you a 404 error. But in the case, that you have the access modifier set to private it does not matter whether if you prefix the function name with an underscore.
But in this tutorial, check the Add Logout section. In it, there is a
private function: private function check_isvalidated(). Here, it is
not prefixed with the character _.
In that tutorial, the function name is not prefixed with an underscore, but it is a private function because it is declared to be one. Thus, trying to access it via URL will not work.
At the same time, there is another one called _output(): Processing
Output. It's a public function with the naming convention of a private
function!
I've already explained this, but I want to point out that the _output() function is one of those special functions that will be called at a certain point during a script execution. In this case, CodeIgniter will call this function at the end of the function, right when it's time to output something to the browser.

Related

Dynamically get the public path for a workbench package in laravel

I'd like to get the path to a package public directory (css etc) based on the package alias.
Is there anything already built into the laravel framework?
In other words something like:
public_path('myalias');
When I'm talking about alias, you would typically "alias" a module by adding the following within your service provider's boot method:
$this->package('namespace/package','alias_name');
For those wondering why someone might want to do this:
We are running a multi domain/subdomain application that makes use of a central piece of code for all of the domains and then specific packages per domain (I'll refer to them as funnels).
Each funnel has its own controllers that can possibly extend base controllers to implement their own functionality while re-using code where they can. They also have their own views.
The funnel refers to its own views by way of something like:
View::make('funnel::path.to.view')
The way we accomplish this is by doing some business logic on page load to only load the FunnelServiceProvider related to that particular domain and aliasing it to "funnel". This way our base controllers can also refer to funnel and not be tied to a particular packages views,includes,blocks etc.
My hope is to do something similar on the views so that I can simply call something like get_funnel_path() to get the path to the funnel that is currently being loaded.
The value could then be used to load css,js,images etc without worrying about the funnel path.
This would allow us to simply copy and paste views from one domain to the next without having to modify all of the paths in potentially multiple files. We could also make use of globally included files in all/most of the views.
An example of this might be the head. The head section should be the same for 99% of the files, however the path where it loads its resources should change based on the funnel.
We use the same naming conventions for css files as well as use sass, imports, merging for all of the funnels; so only the path needs to change.
You can do something like this although it will only work with your own packages and require a bit of work. Because the alias is not really stored somewhere you can easily access you have to do that yourself.
First create some kind of class to store your package names in. I called mine PackageManager:
class PackageManager {
private $packages = array();
public function addPackage($fullName, $alias){
$this->packages[$alias] = $fullName;
return $this;
}
public function getPublicPath($alias){
if(!isset($this->packages[$alias])) return public_path();
$path = 'packages/' . $this->packages[$alias];
return public_path($path);
}
}
Now let's register that class as a singleton in a service provider:
$this->app->singleton('packagemanager', function(){
return new PackageManager();
});
Then, in every package you want to register, add this call in the boot method right next to $this->package():
$this->app['packagemanager']->addPackage('vendor/package', 'alias');
After that you can do this anywhere in your application:
app('packagemanager')->getPublicPath('alias');
If you want a shorter syntax, add this helper function somewhere:
function public_package_path($alias){
return app('packagemanager')->getPublicPath($alias);
}
And just do:
public_package_path('alias');

Correct naming structure for CodeIgniter

I'm starting my 1st CodeIgniter project and want to get some advice before i start. I'm a little confused with how the name of the controller and models work.
If i want the url to my company page to be http://example.com/Company/view
the controller needs to be called Company.php correct?
inside the company controller it would look like this:
public function viewAll()
{
$this->load->model('Companymodel');
$this->load->view('templates/header');
$data['result'] = $this->Companymodel->viewAll();
$this->load->view('company/viewAll', $data);
$this->load->view('templates/footer');
}
ok im confused here, on line 4 above:
$this->load->model('Companymodel');
this call to the company model page needs to have 1st letter capital with the rest lower case?
if that's correct, does the model file need to be called Companymodel.php and placed inside the application/models folder?
is it bad practice to call the controller and model the same
example: Company.php and place it inside /application/controller/
and then have the model called Company.php and place it inside the application/model or should the model be called Companymodel.php
I guess my ultimate question is the naming convention of the controller and model files, and whether they can be upper case or not.
URLs
Your URLs should typically be all lowercase letters. If you expect capital letters, there's a chance you could accidentally exclude their lowercase counterparts, even though they're the same URL. Example: www.example.com/controller/method/param
Controllers
Controller class names should be all lowercase, except the first letter.
If your URL is www.example.com/gallery, the controller name is Gallery.
If your URL is www.example.com/admin_folder, the controller name is Admin_folder.
Controller file names should match the class name, but be all lowercase.
Gallery :: gallery.php
Admin_folder :: admin_folder.php
Controller methods should be all lowercase as well. There is some flexibility with uppercase, but similar to URLs, there are opportunities where it can goof something up (here's an example where capital letters interfered with a form validation callback method).
Models
Models follow most of the same conventions as controllers. The only difference is with model method names, which can use your preference of capitalization. Since these methods are not tied to URLs, and are called using normal PHP OOP, you can name them as you please.
It is recommended to load models using the all lowercase version. While it is not required by CI, it can confuse some users if they load it with a capital letter, but then attempt to access it as all lowercase (this is due to native PHP being case sensitive with class properties [and variables in general], not CodeIgniter).
Model class name: Users_model (the _model suffix is also not required, but some people may use it as a personal preference, or to prevent naming conflicts with a Users controller).
Model file name: users_model.php
Model loading: $this->load->model('users_model')
Model method names (all okay): $this->users->getAll(), $this->users->find_by_name($name), etc.
Libraries
Libraries follow the same conventions except for the file name. In their case, file names should match the class name.
Similar to models, it's recommended to load libraries using the lowercase name.
These rules are the same for CI's libraries (located in application/core and application/libraries, as well as custom or third-party libraries.
Special note: when extending default CI libraries, the prefix as defined in application/config.php comes into play. This prefix typically should be all uppercase, followed by an underscore. The default is MY_.
Library class name: Photos
Library file name: Photos.php,
Library load: $this->load->library('photos')
Helpers
Helper names and loading are all lowercase. The filename consists of the helper name with _helper appended after.
Helper name: url
Helper file name: url_helper.php
Helper load: $this->load->helper('url')
Notes
CodeIgniter is somewhat inconsistent in their naming conventions, but there really aren't too many rules, so they are easy to get used to and memorize. I very rarely have issues with naming and loading in CI, and when I do, it's usually because I was just working on a Composer-related project so I got into a different habit.
The rules in this answer are for CodeIgniter 2.1.x as of this writing. There is discussion on Github for 3.0 to better and add more consistency to naming conventions, which you can read about and contribute to if you'd like.
models/admin.php
<?php
class Admin extends CI_Model {
...etc
controllers/company.php
will include the admin model with
function galleryView()
{
$this->load->model('Admin');
$numRows = $this->Admin->getPhotoNum();
... etc
To browse to galleryView the URL would be mysite.com/company/galleryView
There is very good documentation and examples on the CodeIgniter site

CodeIgniter - where to put functions / classes?

Am having problems understanding where classes should be kept in CI. I am building an application that describes / markets mobile phones.
I would like for all of my functions (i.e. getphone, getdetails etc.) to reside in one class called Mobile - I understand that this file should be called Mobile.php and reside in the controllers folder.
Can I then have multiple functions inside Mobile.php? E.g.
public function getphone() {
xxx
xx
xx
}
public function getdetails() {
xxx
xx
xx
}
Or do I need to put each function in its own class?
I'd really appreciate looking at some sample code that works. I've been going through the documentation and google for a few hours, and tried all sorts of variations in the URL to find a test class, but without much luck! I've even messed around with the routes and .htaccess...
All I am trying to achieve is the following:
http:///model/HTC-Desire/ to be re-routed to a function that accepts HTC-Desire as a parameter (as I need it for a DB lookup). The default controller works fine, but can't get anything to work thereafter.
Any ideas?
Thanks
Actually it works like this:
Controllers and Models go to their perspective folders as you know it
If you want to create functions that are not methods of an object, you must create a helper file. More info here :
http://codeigniter.com/user_guide/general/helpers.html
Now if you want to create your own datatypes (classes that don't extend Models and Controllers), you add them to the library folder. So if let's say you want to create a class "Car" you create this file:
class Car{
function __construct(){}
}
and save it in the libraries folder as car.php
To create an instance of the Car class you must do the following:
$this->load->library('car');
$my_car = new Car();
More information on libraries here:
http://codeigniter.com/user_guide/general/creating_libraries.html
Yes, you can have as many functions in a controller class as you'd like. They are accessible via the url /class/function.
You can catch parameters in the class functions, though it's not advisable.
class Mobile extends CI_Controller{
public function getPhone($phoneModel=''){
echo $phoneModel;
//echo $this->input->post('phoneModel');
}
}
http://site.com/mobile/getPhone/HTC-Rad theoretically would echo out "HTC-Rad". HOWEVER, special characters are not welcome in URL's in CI by default, so in this example you may be met with a 'Disallowed URI characters" error instead. You'd be better off passing the phone model (or any other parameters) via $_POST to the controller.
Classes can exist both as Controllers and Models, as CodeIgniter implements the MVC pattern. I recommend reading more about that to understand how your classes/functions/etc. can best be organized.
Off the top of my head, Pyro CMS is an application built with CodeIgniter and the source code is freely available. I'm sure there are others.
I think it's best you handle it from one perspective, that is; create a utility class with all your functions in it.
The answer to the question of where to put/place the class file is the "libraries" folder.
This is clearly stated in the documentation. Place your class in the libraries folder.
When we use the term “Libraries” we are normally referring to the
classes that are located in the libraries directory and described in
the Class Reference of this user guide.
You can read more on creating and using libraries Creating Libraries — CodeIgniter 3.1.10 documentation
After placing the newly created class in the libraries folder, to use just simply load the library within your controller as shown below:
$this->load->library('yourphpclassname');
If you wish to receive several arguments within you constructor you have to modify it to receive an argument which would be an array and you loading/initialization would then be slightly different as shown below:
$params = array('type' => 'large', 'color' => 'red');
$this->load->library('yourphpclassname', $params);
Then, to access any of the functions within the class simply do that as shown below:
$this->yourphpclassname->some_method();
I hope this answers your question if you have further question do leave a comment and I would do well to respond to them.

How to navigate to a page inside another class library in Windows Phone 7?

There are a set of common pages that I want to use in multiple projects. Hence, I want to build a class library with those pages. The problem is I am not able to pass objects using NavigationService.Navigate(new Uri("/Common;component/SomeName.xaml", UriKind.Relative)); method.
I know I can pass querystring. What I would like to know is...
Is there any limit to the number of strings you can pass in the querystring?
Is there any length limitation of the querystring?
Or better still,
Is there a better way of passing objects from an application to the pages inside a different class library?
About the question "is there a better way". In addition to the solution you've mentioned some people like to use the app's state to pass parameters between objects. For example:
PhoneApplicationService.Current.State["parameter"] = param;
var parameter = PhoneApplicationService.Current.State["parameter"];
Another option is to use a shared class. With complex objects I find it often easiest to use a static public member in a class which can be accessed from both of the projects.
Note that if you choose to use the query string navigation, some special characters in the query string may cause problems. If you can't control the content of the data which is passed between the pages, the shared class -solution is probably better for you. For example in one of our applications we're passing a web site's name in the query string. There's situations where those names can contain a '&' -character (like H&M) and if it does, the query string will break.
When navigating, if building the query strings gets cumbersome, you may check out the Caliburn.Micro and the Uribuilder class in it. It allows you to navigate with a rather nice (and fluent) syntax:
navigation.UriFor<CandidateDetailsPageViewModel>()
.WithParam(x => x.CandidateId, candidate.Id)
.Navigate();
After navigation, the TryGetValue-method can be rather useful when parsing the parameters:
String parameter;
NavigationContext.QueryString.TryGetValue("Parameter", out parameter)
More details for NavigationContext.QueryString is available from MSDN.
To answer your questions:
No there is no limit to the number of strings you can pass in a qyerystring
I believe the answer to this may be yes. I believe the standard is to have a url of < 2000 characters
For small items I usually just pass a query string to my pages. For more complex cases I have a shared static Domain class that both libraries reference. Then I can just access this variable statically really easily.

Codeigniter: Use of load_class

I am writing my own logging class to save data in a DB. As I looked how CI is doing I noticed there is a log_message() function which handles the logging. There is a load_class function I can't assign to anything in the CI user guide.
1 Why do they put this into an extra function?
2 What/where loads this function files from?
Hope there are some CI guys how can answer :-)
Short answer:
You can write your own log class to override the default CI class:
<?php
// this file is /application/libraries/MY_Log.php
class MY_Log extends CI_Log {
public function write_log($level = 'error', $msg, $php_error = FALSE)
{
// Put your own logging function in here.
// If you want it to still log to a file as usual, use this:
parent::write_log($level, $msg, $php_error);
}
}
Long answer:
The load_class() function is basically a singleton loader. If the class has already been loaded, return a previous instance; otherwise, load it and create the singleton. It is very important in a framework like CI. You have to know that every time you call, say, a database function, it is applying it to the same object, not instantiating a new one (that would get really messy). All CI libraries function this way by default.
An important note: they changed how this functions significantly in version 2.0. Previously, it would only load from the /libraries folder, but now, it will load from /core or wherever you specify when calling the function.
Here's the process for loading, say, the Log class (from your example):
$_log =& load_class('Log');
$_log->write_log($level, $message, $php_error);
This runs the following checks, in sequence:
If the Log class already exists, we're done. Return the singleton.
If not, first check the /system/libraries folder for a "Log.php" file
If no file existed for step #2, now check /application/libraries for a "MY_Log.php" file (or whatever your subclass prefix is set to in your configuration)
If it loaded the default CI class (from the /system folder), but you DO have an extended class under /application, load that class too.
Return a new instance of the class (YOURS if it exists; otherwise, it's the CI_* class)
I've actually never needed to use the load_class() function, as it allows extension fairly seamlessly. However, it's good to know how it works.
So, to override a class, first find where the original resides (usually /system/libraries or /system/core). Put your extending file in the corresponding /application folder (this is important! If it's under /system/core, the extension MUST be under /application/core). Prefix both the filename and the class name with MY_ (or whatever you set in your configuration), and have it extend the CI_ base class.

Resources