How does CakePHP connect files in different directories? - php

This is probably very trivial but because I'm new I just don't get it.
I can see the notion of App::uses at the beginning of every file but how does the file know where App is?
There are no includes anywhere and to my understanding there is one autoloader somewhere in lib, does that mean that one autoloader in one file is responsible for loading all the classes (if instantiated)?
I tried reading this part of the manual but still failed to understand how it works.
Also read some material on the spl_autoload_register function itself but no avail.
I'd really appreciate it if someone could help me understand how the files communicate with eachother.

Look at App::load(), it's doc block explains it:
Method to handle the automatic class loading. It will look for each
class' package defined using App::uses() and with this information it
will resolve the package name to a full path to load the class from.
File name for each class should follow the class name. For instance,
if a class is name MyCustomClass the file name should be
MyCustomClass.php.
And look at the frameworks core file lib/Cake/basics.php:
spl_autoload_register(array('App', 'load'));
It registers that method as auto loader.

Related

Loading PHP classes by just putting files into PSR-4 directory

In my current lib, I have classes with static code outside the class definition, that I would like to execute when browsing a index.php file that has autoloading (with properly putting the class files into a PSR-4 folder structure, and calling composer install before).
It's not such a bad deal. For instance, in my custom Error.php class I could for instance call set_error_handler function outside the class so warnings could be catchable. And putting this file in a PSR-4 autoloading could ease the pain for not having to call any Error.php code in index.php to enable this catching. Every source that just uses my namespace and autoloads my lib would have that for granted.
I tried to include use \MyNamespace\Error; in the index.php file, but the code in Error.php, outside the Error class definition, isn't automatically executed.
The code outside the class is only executed when I call a class method inside my index.php file (the one that has the autoloading).
Can this be done ? Thanks for your time.
use \MyNamespace\Error; does not trigger autoloading, it just allows you to use shorter class name in code - new Error() instead of new \MyNamespace\Error(). If you want to include Error.php file, you need to use this class. Probably the safest way would to use class_exist():
class_exists(Error::class);
But honestly you should rethink your design, implicit registering error handler in file with class declaration is against PSR-1 and may be really annoying in big project.
Files SHOULD either declare symbols (classes, functions, constants, etc.) or cause side-effects (e.g. generate output, change .ini settings, etc.) but SHOULD NOT do both
https://www.php-fig.org/psr/psr-1/#23-side-effects
It would be less magical if you create separate method for registering error handler and call it explicitly in index.php:
Error::registerErrorHandler();

Difficulty instantiating classes in psysh

I am having difficulty getting psysh to instantiate classes.
I am trying to use PSR-4 namespaces, and have registered a psr-4 autoload in composer like this:
"autoload": {
"psr-4": {
"System\\": "phpclasses/"
}
},
There is a class in phpclasses\Test.php, class name Test with a static method called hello().
I open a command shell, start psysh, and psysh appears to be working normally.
If I try to run Test::hello(); it will fail, unless I call it like this first: echo System\Test::hello();
This actually fails with the message:
PHP Fatal error: Class 'System\Test' not found in eval()'d code on line 1
but then I can successfully run: echo Test::hello();
echo System\Test::hello(); will never work
I tried Use System; and use System\Test; has no beneficial effect.
Every class I use, I have to go through this routine, which is kind of a drag because some of the classes uses static methods, and each of those will only work if each class has gone through that fail first routine.
Basically the same technique must be used for static or non-static methods.
I am running psysh in a command shell in windows 10, xampp (php 5.6), composer (current) installed.
Any suggestions for what I am doing wrong or need to do differently?
The trouble here is that you're not following PSR-4. With the config you provided, it's expecting to find classes in the System namespace inside your phpclasses folder. So, for example, the file Test.php would have the class System\Test.
To just fix it, either change the prefix in your autoload settings to "", or add namespace System; to your Test.php file. If you want to understand why it's acting like it is, you have to understand a bit about how autoloading works in PHP:
PHP lets you register an autoloader to find classes which haven't been encountered yet. The autoloader is handed a class name, and given a chance to find it. Usually they work by mapping class names to files in some way. When they're asked for an unknown class, they translate the class name to a file name, and try to require the file.
PSR-4 is a standard for setting up such an autoloader, and Composer comes with a PSR-4 compliant autoloader for free. For it to work right, you have to lay out your classes and namespaces like PSR-4 expects. If you don't, you can run into strange issues like you're encountering.
When you first tried calling Test::hello(), the class wasn't defined. Your PSR-4 autoloader translated that to a file name, but per your config, there's nowhere defined for non-namespaced classes to live, so it couldn't find a file to load, and it ended up loading nothing. After the autoloader had a chance, PHP still didn't know about that class, so it threw an error.
When you tried calling System\Test::hello(), your PSR-4 autoloader looked it up in the config and translated it to a filename (phpclasses/Test.php), which did exist this time, so it loaded that file. PHP then tried calling the method, but it didn't know about that class, so it threw an error.
The third time, it had already loaded your file and discovered the non-namespaced Test class. So when you tried calling it again, it didn't even bother with the autoloader, and just executed your method.

CodeIgniter PHPWord template not found

I'm facing trouble when using PHPWord with CodeIgniter in loadTemplate always return error "Template Not Found".
I'm using phpword in third party and create Word.php class in library to call it.
My CodeIgniter not a pure one. It already injected like some homemade cms from previous programmer.
My Question is how to I know where is the path of loadTemplate?
Any info needed you can ask me I will provide for you
Thanks,
Hendra
I'm not sure if I understood your scenario, but in any case there is no magic in how the path of loadTemplate works - it works exactly the same as you would access any file with php, i.e. either you place your template file under the phpunit library and use a relative path or you place your file somewhere else and use a full path (or some alias if you have some defined in your server (apache/nginx/..) configuration).

How to include external PHP classes in Joomla

I have few PHP classes and files that I want to include in Joomla so that I can call those classes. I tried doing require_once config.php to include a PHP file which also includes all the classes that I would want to use in Joomla.
But each time I execute the page I receive the error below:
Fatal error: Class 'SomeClassName' not found
is there any other way to include external PHP classes or files in Joomla?
Thanks in advance!
Please use Joomla autoloader. Is better.
<?php
// Register an adhoc class.
JLoader::register('AdhocClass', '/the/path/adhoc.php');
// Register a custom class to override as core class.
// This must be done before the core class is loaded.
JLoader::register('JDatabase', '/custom/path/database_driver.php', true);
Edit:
Load classes with autoload instead of require/include have a better performance, because PHP will only read (require access to the disk) and compile (require memory and CPU usage) if you really use your class.
To do the same with require/include you have to be sure to only use if will really use the class.
Source:
http://developer.joomla.org/manual/ch01s04.html
require_once should work just fine within Joomla. Make sure the class you want to use is really loaded within your file, and the file is properly referenced in the require_once. Something is going wrong there and it has nothing to do with Joomla itself :-)

Symfony function available in all models

I want to use a function in all models class (in project folder and in plugins folder).
Where should I declare it?
Depending on what your function does, you can create a file in the lib folder and then call it from every where in your app. This is useful in a Symfony project to define common functions (like a toolbox).
For example, in the Jobeet tutorial, they define a method called slugify in /lib/Jobeet.class.php (be sure to name the file with .class.php at the end so Symfony will automatically load it). Then, you can call Jobeet::slugify() every where in your app/model/plugin/view.
This solution works with Symfony 1.4:
You create a new file in which you declare the function you want to be available everywhere.
You load that file with the auto prepend file settingin the php.ini file.
If done correctly, that function is available in all your scripts, regardless of model, plugin or something else from your project.

Categories