Zend framework form helper - php

I'm trying to work out how below works...
Where does Jobs_Form_Report_Productivity() come from?
public function productivityAction(){
$this->view->headTitle('Number of Unique Jobs by Portfolio');
$this->view->form = new Jobs_Form_Report_Productivity();
if($this->view->form->isValid($_POST))
{
$report = new Model_Users();
$this->view->results = $report->reportProductivity(
$this->view->form->getStartDate('yyy-MM-dd'),
$this->view->form->getEndDate('yyy-MM-dd')
);
}
}
Is this some form of Model class?

ZF1 uses PEAR namespacing (note the underscores), each underscore becomes a directory separator and the last part of the classname is usually the name of the file typically something like 'Productivity.php', so Jobs_From_Report_Productivity should be located in Jobs/Form/Report in a file called 'Productivity.php'.
Since the classname you are looking for does not start with 'Application_', my suggestion is that it is a module namespace called 'jobs', so you are probably looking for 'application/modules/jobs/forms/report/Productivity.php,
otherwise it could be in the library directory as library/jobs/forms/report/Productivity.php.
Of course, its completey possible to do some weird and wonderful things with the locations that ZF1 uses to locate classes.

Zend Framework use Zend_Loader_Autoloader to load classes that are called but not found in the script scoope. When a class that isn't found is called the autoloader kicks in and find and include the class file in few simple steps.
1) Converts all the _ (underscore sign) into / (slash) in the class name.
Example: Zend_Loader_Autoloade becomes Zend/Loader/Autoloader
2) The suffix .php is appended to the end of the converted string and it becomes: Zend/Loader/Autoloader.php
3) Checks if the "Zend_" name space (name space as class prefix and not PHP5.3 namespace) is registered with the autoloader. If the name space is registered then the autoloader will issue: include Zend/Loader/Autoloader.php.
4) If the class is found it returns it and the script continues. If class not found based on the configuration throws and exception or error.
PRE-CONDITION: The file Zend/Loader/Autoloader.php should be in the PHP include path for the current script.
Therefore, Jobs_Form_Report_Productivity will correspond to Jobs/Form/Report/Productivity.php and it will be found in one (or more) of the include paths. Find the include paths with PHP's: get_include_path(). Most of the times (in ZF1) the include path(s) is/are set in the index.php file in the public directory of the Zend Framework application.
See: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md as the guys from PHP-FIG made this autoloading approach a standard "PSR-O"
Hope this helps :)

Related

how include all classes by preg_match and autoload [duplicate]

I've set up a really basic autoloader in my index.php to grab a namespaced class within hello.php. My development environment is Ubuntu 12.04.
Why am I trying to do this? I'm trying to stick to the PSR-1 and PSR-2 coding standard, that includes:
Class names MUST be declared in StudlyCaps
Namespaces are as /Vendor/Class (note: capitals)
The following is my structure and code that works before making the changes to capitals.
Folder Structure
- web
-- index.php
-- core
--- hello.php
Autoloader
Within index.php, I have my autoloader:
set_include_path(__DIR__);
spl_autoload_extensions('.php,.class.php');
spl_autoload_register();
Class File
Within the core folder, I have hello.php
namespace core;
class hello {
public function __construct() {
echo 'Constructed!';
}
}
Code that works
If I run $obj = new \core\hello(); in my index.php, I get back "Constructed!". Great!
That which doesn't work
Renaming my core folder to 'Core' - note the uppercase C, and also the namespace in hello.php to namespace Core;.
Now let's try again with $obj = new \Core\hello();
Fatal error: Class 'Core\hello' not found in ...
So please tell me, why am I not able to use capital letters to keep inline with the PSR standards? What am I doing wrong?
When you run your PHP code on a Linux platform, it's important to remember that Linux is case sensitive with filenames.
This affects autoloaders because they typically use the namespace and the class name when building the filename to load.
If the folder is named core, then the namespace must be core, with the same capitalisation. If you change it to Core in the namespace, then you must do the same to the folder name. (and as a result, all other core classes must be changed to Core at the same time).
On Windows, this doesn't happen because the Windows filesystem isn't case sensitive. This can cause confusion when code is tested and works on a local Windows-based dev system, and then breaks when it is copied to a Linux-based server.
[EDIT]
Okay, so I missed that you had changed the dirname as well. But nevertheless, I still think this is an issue of the filename/dirname case.
I note that you're calling spl_autoload_register() without any params. This means that the default spl_autoload() function will be used as the autoloader.
If you read the documentation for spl_autoload(), you'll note that it uses the lowercased version of the class and namespace.
In other words, using the default autoloader, your classes can be mixed case, but the folder structure and filenames must be all lower case.
So in fact, for you, you need to keep your filenames lower case.
I've personally experienced it the other way round, as per my original answer, where I had a fully lower case filename, and my mixed case class name was breaking when I moved from Windows dev box to Linux server. The reason my experience is different from yours is because I'm using a custom-written autoload function, which doesn't do an auto-lowercase conversion, so the case of my filenames has to match that of my classnames.
I think you have shown us some good ambiguity.Correct me if I am wrong.
According to the specification you have to use the lowercased name of the class (and namespace) being instantiated.(http://www.php.net/manual/en/function.spl-autoload.php)
But PSR tells us to use the capital letters. If you want to stick with PSR then we have to overwrite the default spl_autoload to our own.
For anyone else having issues with this, why not make use of ucfirst() or strtolower() ?
So the code below would try all lowercase and also try first letter uppercase files
e.g: somename.class.php or Somename.class.php
The is_readable() checks first as to not display the php error for file not found.
spl_autoload_register(function($name) {
if (is_readable(strtolower($name).'.class.php')) {
require_once(strtolower($name).'.class.php');
}
elseif (is_readable(ucfirst($name).'.class.php')) {
require_once(ucfirst($name).'.class.php');
}
});

Autoload namespaces based on directory structure

According to the top comment on the PHP page spl_autoload_register( ) :
Good news for PHP 5.3 users with namespaced classes:
When you create a subfolder structure matching the namespaces of the >containing classes, you will never even have to define an autoloader.
<?php
spl_autoload_extensions(".php"); // comma-separated list
spl_autoload_register();
?>
However, when I have the following structure:
* classes/someclass.php
* index.php
Where someclass.php contains the following:
<?php
class someclass {
function __construct( ) {
echo 'It works!';
}
}
?>
and index.php contains:
<?php
spl_autoload_extensions(".php");
spl_autoload_register();
new classes\someclass;
?>
Then I get the following error:
Fatal error: spl_autoload(): Class classes\someclass could not be
loaded
Am I getting this wrong? How can I make this work?
From the comments
This doesn't work either for the class:
<?php
namespace classes;
class someclass {
function __construct( ) {
echo 'It works!';
}
}
?>
In your someclass.php file you must define the namespace at the begginning.
<?php
namespace classes;
TLDR; It works, but:
namespace classes; is missing in classes/someclass.php
set_include_path(__DIR__); is missing in index.php
(spl_autoload_extensions(".php") is not necessary)
Include Path
The SPL autoload implementation is include path based. Using a dot as include path is relative to the working directory (!) which is independent from script file location. __DIR__ names the exact directory that is needed if the classes folder lies next to the index.php file as in the scenario.
Directory Separator mapping
Next the autoloader implementation does map the class namespace separator properly on Unix systems. In case that got lost in the o/p, the PHP source code clearly has this.
Case Sensitivity of File Names
What the source code also shows is that file-names to load are made lowercase. That is, if your file system is case sensitive, the file and directory names must be in lower case.
Refernces:
https://lxr.room11.org/xref/php-src%407.1/ext/spl/php_spl.c#spl_autoload
https://lxr.room11.org/xref/php-src%407.1/ext/spl/php_spl.c#307
PHP - most lightweight psr-0 compliant autoloader
The user, SedaSoft, who had posted the Good news comment you which you refer, had subsequently posted another comment, due to a revision of ideas:
What I said here previously is only true on Windows. The built-in
default autoloader that is registered when you call
spl_autoload_register() without any arguments simply adds the
qualified class name plus the registered file extension (.php) to each
of the include paths and tries to include that file.
Example (on Windows):
include paths:
- "."
- "d:/projects/phplib"
qualified class name to load:
network\http\rest\Resource
Here's what happens:
PHP tries to load
'.\\network\\http\\rest\\Resource.php'
-> file not found
PHP tries to load
'd:/projects/phplib\\network\\http\\rest\\Resource.php'
-> file found and included
Note the slashes and backslashes in the file path. On Windows this
works perfectly, but on a Linux machine, the backslashes won't work
and additionally the file names are case-sensitive.
That's why on Linux the quick-and-easy way would be to convert these
qualified class names to slashes and to lowercase and pass them to the
built-in autoloader like so:
<?php
spl_autoload_register(
function ($pClassName) {
spl_autoload(strtolower(str_replace("\\", "/", $pClassName)));
}
);
?>
But this means, you have to save all your classes with lowercase file
names. Otherwise, if you omit the strtolower call, you have to use the
class names exactly as specified by the file name, which can be
annoying for class names that are defined with non-straightforward
case like e. g. XMLHttpRequest.
I prefer the lowercase approach, because it is easier to use and the
file name conversion can be done automatically on deploying.
Note that this commenter had actually posted an answer here on SO today, containing the above links (along with a short explantation), but it was subsequently deleted, whilst in the review queue - presumably due to its brevity. I have reinstated the commenter's answer, along with the content of the link. Their answer was as follows:
I wrote that comment on php.net some time ago when I was working on a
Windows system. Later, I had to partially revoke what I wrote in that
comment on the very same page in another comment, which also contains
a possible solution to the problem that is the easiest I could think
of (apart from using Composer).
Here is a screenshot of the original answer:
Do not roll your own autoloading, but use composer instead.
Create a composer.json in the root of your project:
{
"autoload": {
"psr-4": {
"classes\\": "classes/"
}
}
}
Install composer, then run
composer dump-autoload
In your index.php, require the autoloader:
require __DIR__ . '/vendor/autoload.php';
For reference, see
https://getcomposer.org/doc/00-intro.md#installation-linux-unix-osx
https://getcomposer.org/doc/01-basic-usage.md#autoloading
http://www.php-fig.org/psr/psr-0/
http://www.php-fig.org/psr/psr-4/
Do not use the spl_autoload_extensions () function if the files to load only have the php extension.
In my case, I create a class called autoload .. something similar to this:
<?php
class Autoload
{
private static $_extensions = array(
0 => '.inc',
1 => '.lib.php',
2 => '.class.php',
);
public function __construct()
{
self::set_include_path();
spl_autoload_extensions(implode(',', self::$_extensions));
spl_autoload_register(__CLASS__, 'load_class');
}
public static function set_include_paths()
{
set_include_path(implode(PATH_SEPARATOR, array(
realpath('classes');
realpath('system');
...
get_include_path();,
)));
}
public function load_class($class)
{
if (!empty($class)) {
spl_autoload($class);
}
return false;
}
}
The use of ?> At the end of the file is not necessary.

PHP - Symfony2.4 Can I have multiple classes in single file?

I am using Vzaar's PHP Library for uploading videos from my website to their server space.
Now point is - in their library there are some PHP files in which more than one class exists and no class with same file name exists in same file.
i.e. have a look at OAuth.php, there is no class with name OAuth in that file.
Question raised in my mind is
When I create any PHP class file, can I create multiple classes in side one file, and later I can use that file in my code or I can use that reusable code in other project as well.
Should creating such files is good practice?
If the class is of 15 to 20 lines long, then should I create a separate file or I should include that in one file only, like OAuth.php.
Please guide with exact reason, if I will get links of wiki where proper explanation is given, then it will be best.
Putting more than one class in one file in general is a bad practice, and in Symfony2 even more because of the way class autoloader works.
When autoloader is looking for Acme\DemoBundle\SomeClass class it expects it will be in Acme\DemoBundle\SomeClass.php file. So in case you have a second class in the same file it won't work.
Check also PSR standards for class autoloading.
Despite I don't like to define more than one class per file I would like to point it out that PSR-4 is not against this practice if the class scope is private.
Quoting Symfony2 coding standards resource (http://symfony.com/doc/current/contributing/code/standards.html)
Define one class per file - this does not apply to private helper
classes that are not intended to be instantiated from the outside and
thus are not concerned by the PSR-0 and PSR-4 autoload standards;
In this other example (Thanks to Xavi Montero) you can see that the class Psr4AutoloaderClassTest has a helper class MockPsr4AutoloaderClass defined in the same file. So in general you should not, but for a "private helper" it's okey.
https://www.php-fig.org/psr/psr-4/examples

Is it required to include the namespace file?

This is what I have at hand:
//Person.php
namespace Entity;
class Person{
}
User file:
//User.php
use Entity\Person;
$person = new Person;
Here, it fails if I don't include the Person.php file. If I include it, the everything works fine. Do I absolutely require to include the file even when using namespaces? If at all we need to include/require files, then how can namespaces be effectively used? Also, can we maintain folder structure by nesting namespaces?
The answer to your question is "yes and no".
Indeed the code implementing class Person has to be included, otherwise the class is not defined and cannot be used. Where should the definition come from, when the code is not included? The php interpreter cannot guess the classes implementation. That is the same in all programming languages, by the way.
However there is something called Autoloading in php. It allows to automatically include certain files. The mechanism is based on a mapping of class names to file names. So in the end it boils down to php searching through a folder structure to find a file whos name suggests that it implements a class currently required in the code it executes.
But don't get this wrong: that still means the file has to be included. The only difference is: the including is done automatically, so without you specifying an explicit include or require statement.
Yes, you need to include every file.
A very good example can be found here on effective usage of namespaces.
With PSR-0 autoloading, the namespace has to be the same as the folder in which the class is, file the filename has to be the same as the classname. This gives you very simple and effective autoloading with composer for example.

PHP - spl_autoload and namespaces - doesn't work with capital letters

I've set up a really basic autoloader in my index.php to grab a namespaced class within hello.php. My development environment is Ubuntu 12.04.
Why am I trying to do this? I'm trying to stick to the PSR-1 and PSR-2 coding standard, that includes:
Class names MUST be declared in StudlyCaps
Namespaces are as /Vendor/Class (note: capitals)
The following is my structure and code that works before making the changes to capitals.
Folder Structure
- web
-- index.php
-- core
--- hello.php
Autoloader
Within index.php, I have my autoloader:
set_include_path(__DIR__);
spl_autoload_extensions('.php,.class.php');
spl_autoload_register();
Class File
Within the core folder, I have hello.php
namespace core;
class hello {
public function __construct() {
echo 'Constructed!';
}
}
Code that works
If I run $obj = new \core\hello(); in my index.php, I get back "Constructed!". Great!
That which doesn't work
Renaming my core folder to 'Core' - note the uppercase C, and also the namespace in hello.php to namespace Core;.
Now let's try again with $obj = new \Core\hello();
Fatal error: Class 'Core\hello' not found in ...
So please tell me, why am I not able to use capital letters to keep inline with the PSR standards? What am I doing wrong?
When you run your PHP code on a Linux platform, it's important to remember that Linux is case sensitive with filenames.
This affects autoloaders because they typically use the namespace and the class name when building the filename to load.
If the folder is named core, then the namespace must be core, with the same capitalisation. If you change it to Core in the namespace, then you must do the same to the folder name. (and as a result, all other core classes must be changed to Core at the same time).
On Windows, this doesn't happen because the Windows filesystem isn't case sensitive. This can cause confusion when code is tested and works on a local Windows-based dev system, and then breaks when it is copied to a Linux-based server.
[EDIT]
Okay, so I missed that you had changed the dirname as well. But nevertheless, I still think this is an issue of the filename/dirname case.
I note that you're calling spl_autoload_register() without any params. This means that the default spl_autoload() function will be used as the autoloader.
If you read the documentation for spl_autoload(), you'll note that it uses the lowercased version of the class and namespace.
In other words, using the default autoloader, your classes can be mixed case, but the folder structure and filenames must be all lower case.
So in fact, for you, you need to keep your filenames lower case.
I've personally experienced it the other way round, as per my original answer, where I had a fully lower case filename, and my mixed case class name was breaking when I moved from Windows dev box to Linux server. The reason my experience is different from yours is because I'm using a custom-written autoload function, which doesn't do an auto-lowercase conversion, so the case of my filenames has to match that of my classnames.
I think you have shown us some good ambiguity.Correct me if I am wrong.
According to the specification you have to use the lowercased name of the class (and namespace) being instantiated.(http://www.php.net/manual/en/function.spl-autoload.php)
But PSR tells us to use the capital letters. If you want to stick with PSR then we have to overwrite the default spl_autoload to our own.
For anyone else having issues with this, why not make use of ucfirst() or strtolower() ?
So the code below would try all lowercase and also try first letter uppercase files
e.g: somename.class.php or Somename.class.php
The is_readable() checks first as to not display the php error for file not found.
spl_autoload_register(function($name) {
if (is_readable(strtolower($name).'.class.php')) {
require_once(strtolower($name).'.class.php');
}
elseif (is_readable(ucfirst($name).'.class.php')) {
require_once(ucfirst($name).'.class.php');
}
});

Categories