I'm currently working on api jwt based authentication off a boiler plate on SitePoint. So far I've gotten everything working but I'm stuck on this point.
My Controller looks like this:
namespace App\Api\V1\Controllers;
use Illuminate\Http\Request;
use Dingo\Api\Routing\Helpers;
use Symfony\Component\HttpKernel\Exception\HttpException;
use JWTAuth;
use App\Http\Controllers\Controller;
use App\Order;
// use App\Api\V1\Requests\LoginRequest;
use Tymon\JWTAuth\Exceptions\JWTException;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
in the body I have this function:
public function checkThis()
{
$currentUser = JWTAuth::parseToken()->authenticate();
$orders = App\Order::first();
echo $orders;
function() {
echo "stll here";
};
}
Under my api route I have this in a middleware:
$api->get('orderlist', 'App\\Api\\V1\\Controllers\\OrderController#checkThis');
When I run this in postman I get the following error: "message": "Class 'App\Api\V1\Controllers\App\Order' not found",
I've tried everything I can think of and it still keeps happening. When I take it out of the controller and run it directly in the routes it works. I'm a newbie to Laravel and PHP so I'm kinda of stuck.
All thing below assusing that you want to invoke the App\Order::first();
In function checkThis , you can replace App\Order::first() by
Order::first() //aliasing version
or replace App\Order::first() by
\App\Order::first(); //fully qualified Name version
By php manual
Example #1 importing/aliasing with the use operator
<?php
namespace foo;
use My\Full\Classname as Another;
// this is the same as use My\Full\NSname as NSname <-- very important
use My\Full\NSname;
Notice that
// this is the same as use My\Full\NSname as NSname <-- very important
use My\Full\NSname;
another php manual
and Inside a namespace, when PHP encounters an unqualified Name in a
class name, function or constant context, it resolves these with
different priorities. Class names always resolve to the current
namespace name. Thus to access internal or non-namespaced user
classes, one must refer to them with their fully qualified Name
php manual : fully qualified Name
Fully qualified name
This is an identifier with a namespace separator that begins with a namespace separator, such as \Foo\Bar. The namespace \Foo is also a
fully qualified name.
So if you want to invoke the function App\Order::first ,just Order::first,for the reason that
use App\Order;
equal
use App\Order as Order ;
the aliasing is Order instead of App\Order . And the Fully qualified name is \App\Order instead of App\Order.
On the other hand , when you invoke App\Order::first();
it means that you are invoking
App\Api\V1\Controllers\App\Order::first();
So it can't not find the class;
Here is my demo
file1.php
<?php
namespace App;
class Order{
public static function first(){
echo "i am first";
}
}
file2.php
<?php
namespace App\Api\V1\Controllers;
include 'file1.php';
use App\Order ;
\App\Order::first();
// and you can do it by
// Order::first(); they are equal in this place
when i run command php file2.php
it echo i am first
Related
I thought this would be easy. For troubleshooting, I wish to call my _logger() function from anywhere in my application.
function _logger(?string $msg=null, int $offset=0, bool $time=false):void
{
$d1 = debug_backtrace()[$offset+1];
$d2 = debug_backtrace()[$offset+2];
syslog(LOG_INFO, sprintf('_logger%s: %s::%s(%s) called by %s::%s on line %s%s', $time?'('.date("Y-m-d H:i:s").')':'', $d1['class'], $d1['function'], json_encode($d1['args']), $d2['class'], $d2['function'], $d2['line'], $msg?' | '.$msg:''));
}
First, I tried adding it to index.php. When added directly in the main body, I got a server error and either with error reporting, couldn't get any info about it (just curious, but anyone know why?). I then placed it into the closure function and it works for HTTP requests only.
<?php
use App\Kernel;
// Added my logger() function here resulted in unexplained server error.
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
return function (array $context) {
// Added my logger() function here works
return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
};
Then I tried adding it to to Kernal.php, and it seems to work, but must be called as \App\_logger().
<?php
declare(strict_types=1);
namespace App;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
class Kernel extends BaseKernel
{
use MicroKernelTrait;
}
if(!function_exists('_logger')) {
// Added my logger() function here works but must be called as \App\_logger()
}
So, then I created a new file called _logger.php which I located in src, and it works sometimes but other times the get the below error and need to clear cache to get it working again.
<?php
declare(strict_types=1);
if(!function_exists('_logger')) {
// Added my logger() function sometimes works but other times doesn't
}
Expected to find class "App_logger" in file
"/var/www/src/_logger.php" while importing services from resource
"../src/", but it was not found! Check the namespace prefix used with
the resource in /var/www/config/services.yaml (which is being
imported from "/var/www/src/Kernel.php"). (500 Internal Server Error)
So, I went back to locating it in Kernel.php, and all is kind of good, but would really know the correct way to add a global function and what are the implications of Symphony's caching when I tried my various approaches.
Design decisions aside, you can achieve this by overriding the namespace in the Kernal.php file:
<?php
declare(strict_types=1);
namespace App {
// Must use bracket notation in order to use global namespace in the same file
// See https://www.php.net/manual/en/language.namespaces.definitionmultiple.php#example-295
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
class Kernel extends BaseKernel
{
use MicroKernelTrait;
}
}
namespace {
// Begin the global namespace
if(!function_exists('_logger')) {
// Added my logger() function here works but must be called as
\App\_logger()
}
}
Note: this code is untested.
Sources:
Define global function from within PHP namespace
https://www.php.net/manual/en/language.namespaces.definitionmultiple.php#example-295
I am converting from c# to php and I'm having trouble transitioning in some places. Particularly namespaces. The problem I am having is I have to fully qualify every namespace when calling a class from another namespace. Is this normal?
<?php
namespace Lib\Things;
class TheThings
{
}
then in the other class
<?php
namespace App;
use Lib\Things;
class DoStuff
{
public function doStuff()
{
$things = new TheThings();
}
}
That doesn't work... I end up having to do
new Lib\Things\TheThings();
Or
<?php
namespace App;
use Lib\Things as T;
class DoStuff
{
public function doStuff()
{
$things = new T\TheThings();
}
}
I've also got this in my composer.json file
"psr-4": {
"App\\": "app/",
"Lib\\": "lib/"
}
Is that normal or am I doing something wrong here?
In the PHP manual the use keyword is referred to as importing or aliasing.
This means that
use Lib\Things;
and
use Lib\Things as Things;
are the same. This results that you don't have to use the fully qualified names to instantiate classes from a namespace, you can use only the alias of the imported namespace. So in your case, the following would have worked:
<?php
namespace App;
use Lib\Things;
// same as:
// use Lib\Things as Things; // explicit alias
class DoStuff
{
public function doStuff()
{
$things = new Things\TheThings();
}
}
(Note that this is the same as your second example, the only difference is that the alias is not explicitly set here to T (and defaults to Things).
To be able to use the class name without any namespace prefix, you will have to set the alias of the actual class:
<?php
namespace App;
use Lib\Things\TheThings;
// same as:
// use Lib\Things\TheThings as TheThings; // explicit alias
class DoStuff
{
public function doStuff()
{
$things = new TheThings();
}
}
In conclusion, if you start thinking about the use operator as setting an alias for a namespace or class (or other), you will get the hang of it.
PS 1:
Before PHP 7, if you wanted to import multiple classes from the same namespace, you had to write:
use some\namespace\ClassA;
use some\namespace\ClassB;
use some\namespace\ClassC as C;
From PHP 7.0 onwards, classes, functions and constants being imported from the same namespace can be grouped together in a single use statement:
use some\namespace\{ClassA, ClassB, ClassC as C};
PS 2:
composer helps in automagically including/loading the actual php files, based on some PSR* rule, it does not have any role in how namespaces work in bare PHP.
When you do:
$things = new TheThings();
Class is searched on the current namespace (App in your example), thats why not worked.
So, you need to specify full class namespace, so interpreter know which class are you refering, you could also have a namepsace2/TheThings and this/is/another/namespace/TheThings classes.
Just include full class namespace
use Lib\Things\TheThings;
I am new in laravel and importing a existing php site.
I created a controller named "List" then i need to create a object of a class, coded in a file which is been include by include_once() as shown,
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
$INCLUDE_ROOT = 'path/to/file';
include_once($INCLUDE_ROOT . "ServiceDetails.class.php");
class Lists extends Controller
{
public function show()
{
$objServiceDetails= new ServiceDetails;
.........
........
}
}
But i am getting an error like
Fatal error: Class 'App\Http\Controllers\ServiceDetails' not found
I dont have much idea of namespace "use" and "as".
May be that's why i am not able to solve this problem.
When creating a new object it is searching class in namespace location only, but it should also look in included files, i think.
If there's a namespace in current file, PHP will try to find class in current namespace and if it won't find it, you'll get fatal error. You should open ServiceDetails.class.php class to verify if there is namespace ...; at the beginning of the file (after <?php). If not you can simple add in your Lists file after:
use App\Http\Controllers\Controller;
the following line:
use ServiceDetails
and if it is, you should copy that namespace and add the following line:
use namespaceyoucopied\ServiceDetails;
of course in namespaceyoucopied place you need to put the correct copied namespace so it could look like this:
use A\B\C\ServiceDetails;
You can also look at How to use objects from other namespaces and how to import namespaces in PHP or PHP namespaces manual
You just need to add a use statement for that class so the class in the current file can "see" it.
<?php
namespace App\Http\Controllers;
$INCLUDE_ROOT = 'path/to/file';
include_once($INCLUDE_ROOT . "ServiceDetails.class.php");
use App\Http\Controllers\Controller;
use Namespace\To\ServiceDetails;
class Lists extends Controller
{
public function show()
{
$objServiceDetails= new ServiceDetails;
.........
........
}
}
However, if you are using Laravel and doing this, then you are not using the autoloading feature to its fullest. I recommend you put this file in a namespaced directory in your application and have it follow PSR-4. Then Laravel will load this for you, and it will keep your class file looking clean.
Put the file in a path like the following: /path/to/projectRoot/app/Lib/ServiceDetails.php. Then make the file look like below so it follows PSR-4:
<?php namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Lib\ServiceDetails;
class Lists extends Controller
{
public function show()
{
$objServiceDetails= new ServiceDetails;
.........
........
}
}
Have encountered an issue I can't seem to figure out now by myself.
Using Symfony autoload module.
Here's my factory:
namespace Core\Factories;
use \Core\Gateway;
class DatabaseAccessFactory {
// Define client type
const DEF = 'mongo';
public function createObject($type) {
switch($type) {
case self::DEF:
return new MongoClientGateway();
break;
default:
return false;
}
}
}
Example of /Core/Gateway/MongoClientGateway.php
<? namespace Core\Gateway;
class MongoClientGateway implements MongoDbGateway {
public function setUp(){
}
public function query(){
}
public function save(){
}
}
So, basically I'm using "use" keyword to load gateway namespace into my current one, and then I try to instantiate a class that is under \Core\Gateway namespace, but it says class is not found. Am I missing something?
You need to specifcy the class as well
use Core\Gateway\MongoClientGateway
or access the class with the namespace you used
new Gateway\MongoClientGateway
Btw, there's no need for the first "\" in use \Core\Gateway
It's use Foo\Bar, without leading backslash.
use Foo\Bar does not mean that every Class implicitly resolves to Foo\Bar\Class now. use Foo\Bar is shorthand for use Foo\Bar as Bar, so you can reference the namespace Foo\Bar using merely Bar. use is not "importing a namespace", it's aliasing a namespace to a shorter name.
Therefore you need to write Gateway\MongoClientGateway, or use Core\Gateway\MongoClientGateway explicitly if you want to be able to write just MongoClientGateway.
you used "use" wrong.
waht "use" does, is to tell your code where class comes from.
sample code:
use \my\namespace\className
new ClassName();
this will make the className accassible without a namespace.
I am working on a php sdk rewrite project and the client wants to get PSR standards done. I am looking at the standards page here
https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
One thing what i am not able to understand, if i use name spaces in my class do i still need to use include or require or use. I mean the whole reason of autoload beats the purpose right ?
For example, say i have a class this way,
namespace Employee\Department;
Class Department
{
//code
}
and i have another class which uses this class by extending it,
namespace Employee\community;
Class Community extends Department
{
//code
}
so does the above code make it to psr-0 standard considering that i have an autoload function exactly thats on the link above.
The second example is going to assume Department is in the Community namespace so in this case you would need a use statement. Also both of your examples would use the namespace Employee not Employee\Whatever for example lets assume the following layout:
Employee/
Community.php
Community/
Manager.php
Department.php
Department/
Manager.php
Then we would see the class/namespaces like the following
namespace Employee;
class Department {
}
///////////
namespace Employee;
class Community extends Department {
}
/////////////
namespace Employee\Department;
class Manager {
}
/////////////
namespace Employee\Community;
use Employee\Department\Manager as BaseManager;
Class Manager extends BaseManager {
}
For your understanding, autoloading works by registering the autoload function in the autoload stack via spl_autoload_register; this allows the function to be invoked whenever a new Class() statement is executed (more info).
On the other hand, the FIG standard for autoloading, PSR-0, defines how a namespace will be translated into a filename by a PSR-0 autoloader function. For example, given the namespace Vendor\Foo, the autoloader will look for the file Vendor/Foo.php having the following code
namespace Vendor;
class Foo
{
public function do()
{
echo "Foo";
}
}
Therefore, following the mandatory requirements, a PSR-0 compliant namespace resolves to the correct PHP file which could otherwise have been included using a require or include.
If I read your intentions correctly, you just need the following namespace in both code snippets:
namespace Employee;
Of course, this is not a PSR-0 namespace because there is no vendor name (unless your vendor name is 'Employee'). Anyway, using this namespace in your two code snippets will work fine.
However, if you intended to keep them in separate namespaces, then the autoloader won't figure out Department in extends Department in the second snippet. You will have to either import the namespace or explicitly specify it as so:
namespace Employee\community;
class Community extends Employee\Department\Department
{
//code
}
I imagine that you did not expect the full class names from your snippets to be Employee\Department\Department, and that is why I first suggested keeping the same namespace for your purposes.