Fatal Error while Importing Class/Interface from the Same Namespace - php

I have a Duck Interface (abstract class in this case) and Class MallardDuck is implementing it. I'm trying to autoload files from the Duck name space but gets a fatal error.
PHP Fatal error: Interface 'Duck\Duck' not found in /var/www/HeadFirstDesignPattern/MallardDuck.php on line 11
I'm used to of working in Laravel which loads files for me, but I want to do it myself using composer. I know it's not a very big issue but when you don't know something then it's considered as a really big problem. Anyways here is the code of my classes and composer.json
Duck class code:
<?php namespace Duck;
//Duck.php
/**
* Description of Duck
*
* #author me
*/
abstract class Duck {
public abstract function display();
public function quack() {
echo 'quack';
}
public function swim() {
echo 'swim';
}
}
Mallard Duck Code
//MallardDuck.php
use Duck\Duck;
/**
* Description of MallardDuck
*
* #author mkhuram
*/
class MallardDuck implements \Duck{
public function display() {
echo __NAMESPACE__;
echo "\n".__CLASS__;
}
}
$md = new MallardDuck();
$md->display();
Compser.json File
{
"name": "vendor/head-first-design-pattern",
"description": "Description of project HeadFirstDesignPattern.",
"authors": [
{
"name": "me",
"email": "my#email.com"
}
],
"require": {},
"autoload": {
"psr-4":{
"Duck\\": ""
}
}
}
"Duck\\": "" is pointing to root of my app. Here is my app directory structure:
vendor
autoload.php
app
Duck.php
MallardDuck.php

You cannot implement an abstract class, you can only extend it.

Related

PHP Class not found using namespaces

I can't find out why my classes won't load. I am using Composer for psr-4 autoloading and have been using it successfully. Here's how I have my classes setup:
/project
/classes
/feeds
/pull
/factory
composer.json
testMyFactory.php
feeds/factory/FeedFactory.php
namespace MyClasses\Feeds\Factory;
interface FeedFactory
{
public function build($provider);
}
feeds/factory/PullFeedFactory.php
namespace MyClasses\Feeds\Factory;
use MyClasses\Feeds\Factory\FeedFactory;
use MyClasses\Feeds\Pull\Providers\One;
/**
* Class FeedFactory
*/
class PullFeedFactory implements FeedFactory
{
public function __construct(){}
/**
* Build provider object for factory
* #param string $provider Type of feed provider to return
* #return Object Provider object
*/
public function build($provider) {
switch ($provider) {
case 'one':
$provider = new One();
break;
default:
$provider = new One`();
break;
}
return $provider;
}
}
project/feeds/pull/One.php
namespace MyClasses\Feeds\Pull\Providers;
class One
{
public function pull() {
echo 'Pull One';
}
}
project/testMyFactory.php
require __DIR__ . '/vendor/autoload.php';
use MyClasses\Feeds\Factory\PullFeedFactory;
$feed = new PullFeedFactory();
$feed->build('one');
$feed->pull();
project/composer.json
{
"require": {
//Remove for example
},
"config": {
"preferred-install": "dist"
},
"require-dev": {
},
"autoload": {
"psr-4": {
"MyClasses\\": "./classes",
}
}
}
This is the error I keep getting Class 'MyClasses\Feeds\Factory\PullFeedFactory' not found in /var/www/html/testPullFactory.php on line xx
I have other classes that work in the Classes directory with autoload but for some reason cannot get this to work. I feel like it's something glaringly obvious but have been stuck on this for hours now.
UPDATE:
Updated to include my vendor/autoload.php file. Stil getting an error, although it's different now Class 'MyClasses\Feeds\Pull\Providers\One' not found in /var/www/html/classes/Feeds/Factory/PullFeedFactory.php
in your composer.json, change to
"autoload": {
"psr-4": {
"MyClasses\\": "classes/",
}
}
Then, execute composer dump-autoload.

Why isn't the "user" class found?

I'm building a PHP web application with Laravel and am trying to pass a name and email from a form to my database, but it displays this error:
Fatal error: Uncaught Error: Class 'user' not found in
C:\xampp\htdocs\MVC\app\controller\home.php:20 Stack trace: #0
C:\xampp\htdocs\MVC\app\core\app.php(43): home->create('hala',
'hala#yahoo') #1 C:\xampp\htdocs\MVC\public\index.php(4):
app->__construct() #2 {main} thrown in
C:\xampp\htdocs\MVC\app\controller\home.php on line 20
This is the code I'm using for the home page:
class home extends controller
{
public function index($name = '')
{
$this->view('home/index', ['name'=>$user->name]);
}
public function create($username = '', $email = '')
{
user::create([
'username' => $username,
'email'=> $email
]);
}
}
and the model:
use Illuminate\Database\Eloquent\Model as Eloquent;
class user extends Eloquent
{
public $name;
protected $fillable = ['username','email'];
}
What am I doing wrong and how can I fix it?
In your controller code, you need to include the user class:
require_once("user.class.php"); /* or whatever the file is named */
If this is done automatically and the class is in a different namespace, you need to declare your intent to use it in the controller:
use \my\namespace\user;
Or just use the fully qualified class name in your code:
\my\namespace\user::create();
If you use illuminate/database then chances are you are using composer. Why not add a PSR-4 auto load rule and structure your code accordingly. Eg. composer.json might look like this:
{
"name": "acme/acme",
"description": "Acme is this and that",
"type": "project",
"require": {
"php": "^7.2",
"illuminate/database": "^5.7"
},
"autoload": {
"psr-4": {
"Acme\\": "src"
}
},
"license": "proprietary"
}
Runing composer install makes you an vendor/autoloader.php and it is the only file you need to require. You put your own code un the Acme (or whatever you chose) namespace. Eg. You put your user model under src/Model/User.php and add your namespace:
<?php
namespace Acme\Model;
use Illuminate\Database\Eloquent\Model as Eloquent;
class User extends Eloquent
{
public $name;
protected $fillable = ['username','email'];
}
Your main file might look like this..
<?php
// entry point file
require_once('vendor/autoload.php');
use Acme\Model\User;
$user = new User();
// ...
Obviously you would make most logic in some class so this should be quite short.
This might seem obvious to people working on recent projects, but I have seen too many projects that still have a static file including all the classes like we did in the olden days. Move your projects to the 2010s now!

PHP Composer - php-sql-query-builder

I just figured out how to install and use PHP composer and used it to instal php-sql-query-builder to my project. The system created the vendor folder, etc. however I am having issues using classes within the package. It gives me the following error, any suggestions on how I can fix this?
Fatal error: Uncaught Error: Class 'NilPortugues\Sql\QueryBuilder\Builder\GenericBuilder' not found in D:\Documents\CadetPortal\php\lib\login.class.php on line 15
Login.class.php
require_once ("core.class.php");
require_once ("../../vendor/autoload.php");
use NilPortugues\Sql\QueryBuilder\Builder\GenericBuilder;
class LoginSystem {
private $core;
private $builder;
private $config;
function __construct(){
$this->core = new coreFunctions();
$this->builder = new GenericBuilder();
$this->config = require('core.config.php');
}
//....
}
EDIT
fncregister.php
require_once "../../vendor/autoload.php";
$LoginManager = new \ThomasSmyth\LoginSystem();
echo $LoginManager->Register($_POST["StrSurname"], $_POST["StrForename"], $_POST["StrEmail"], $_POST["StrPassword"], $_POST["DteDoB"], $_POST["StrGender"], $_POST["StrToken"]);
composer.json
{
"require": {
"nilportugues/sql-query-builder": "^1.5"
},
"autoload": {
"psr-4": {
"ThomasSmyth\\": "php/lib/"
}
}
}
Your class source files shouldn't have any require_once statements at all in them. Follow the PSR-4 spec for naming. Put your classes in a namespace to avoid collision with other classes you might include via composer. Then put one class in one file, named the same as the class. For example, the LoginSystem class should be in a file named LoginSystem.php.
namespace MyNamespace;
class LoginSystem
{
...
}
Then set your composer.json to point your namespace to your source directory:
"autoload": {
"psr-4": {
"MyNamespace\\": "src/"
}
},
Now, your main app invoker or front controller should be the only place that includes the autoloader:
require_once 'vendor/autoload.php';
$login = new \MyNamespace\LoginSystem();
...

How to call view from an other file than controller

I am creating a laravel 5.2 package, following are my files:
packages/
-Shreeji/
--Ring/
---composer.json
---src/
----Ring.php
----RingModel.php
----RingServiceProvider
----Views/
-----ringslist.blade.php
composer.json
{
"name": "shreeji/ring",
"description": "Simple",
"license": "MIT",
"authors": [
{
"name": "author",
"email": "email#gmail.com"
}
],
"autoload": {
"psr-4": {
"Shreeji\\Ring\\": "src/"
}
},
"minimum-stability": "dev",
"require": {
"Illuminate/support": "~5"
}
}
Ring.php
namespace Shreeji\Ring;
use Illuminate\Http\Response;
Class Ring {
function __construct() {
}
public function get_all()
{
return view("ring::ringlist");
}
}
RingServiceProvider.php
namespace Shreeji\Ring;
use Illuminate\Support\ServiceProvider;
Class RingServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind('ring', function($app){
return new Ring;
});
}
public function boot()
{
$this->loadViewsFrom(__DIR__ . '/Views', 'ring');
}
}
ringlist.blade.php
<!DOCTYPE html>
<html>
<body>
<h1>Welcome</h1>
</body>
</html>
And in app/Http/Controllers I have created a test file like this:
Ringcontroller.php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Shreeji\Ring\Ring;
class RingController extends Controller
{
public function index()
{
$ring = New Ring();
$ring->get_all();
}
}
When I call the controller, browser keeps loading and crashed systematically. I don't know if I can use view outside any controller class like such.
Let me know if I did any mistake in calling view from Ring.php file.
Couple issues I see:
You want to use views, but your package does not require the illuminate/view package. You need to update your composer.json file to require "illuminate/view": "~5".
The view() function is a helper method included at Illuminate\Foundation\helpers.php. Unless you want to depend on the entire Laravel framework just for this function, you will need to create your own view() function. The code is below, where you put it is up to you.
if (! function_exists('view')) {
/**
* Get the evaluated view contents for the given view.
*
* #param string $view
* #param array $data
* #param array $mergeData
* #return \Illuminate\View\View|\Illuminate\Contracts\View\Factory
*/
function view($view = null, $data = [], $mergeData = [])
{
$factory = app(ViewFactory::class);
if (func_num_args() === 0) {
return $factory;
}
return $factory->make($view, $data, $mergeData);
}
}
Once you get the view stuff working, you can make views all day long, but if you don't return anything from your controller, you're not going to see anything. Make sure you return something from your controller methods.
You can use somethin like view composer Docs
In your RingServiceProvider register a composer
use Illuminate\Contracts\View\Factory as ViewFactory;
public function boot(ViewFactory $view)
{
$view->composer('*', 'App\Http\ViewComposers\SomeComposer');
}
And in App\Http\ViewComposers\SomeComposer
use Illuminate\Contracts\View\View;
public function compose(View $view)
{
$view->with('count', '1');
}
Play around with it, basically I am using it share $variables on particular views but maybe this can help you achieve what you want.
Or u can just use Illuminate\Contracts\View\View; to load your view that you need!

Laravel : Calling functions defined in base_controller from view

In using the laravel framework, how can I call a function defined in base_controller, in a view. For exacmple:
class Base_Controller extends Controller {
public static function format_something()
{
return something;
}
}
How can i call format_something() in a view file?
Usually the error I get looks something like this:
Method [link_to_action] is not defined on the View class.
Probably a silly question, but thanks in advance!
Edit
Okay! First the correct place to do something like this is in the libraries folder.
Second, problem is that your class cannot have underscores.
So in application/libraries I made file AppHelper.php with class
class AppHelper {
public static function format_something()
{
return something;
}
}
And can call it like:
$formated = AppHelper::format_something;
Thanks for the help and the good forum find Boofus McGoofus.
For me is working:
Create directory "helpers" or whatever and file:
// app/helpers/AppHelper.php
class AppHelper {
public static function format_something()
{
return something;
}
}
Add path to composer.json
// composer.json
"autoload": {
"classmap": [
"app/helpers" // <-------- add this line
]
},
Run: (reload the autoload)
composer dump-autoload
Now you can call:
$formated = AppHelper::format_something();
This answer was written for Laravel 3. For Laravel 4 and after, Lajdák Marek's answer using Composer's autoloader is better.
Functions like format_something() don't belong in the controller. The controller should just be about collecting data from various sources and passing it to the view. It's job is mostly just routing.
I've created a folder called "helpers" in the application folder for all my little helpery functions. To make sure all my controllers, views, and models have access to them, I've included the following in my start.php file:
foreach(glob(path('app').'helpers/*.php') as $filename) {
include $filename;
}
I suspect that there's a better way to do that, but so far it has worked for me.
You can inspire yourself from Laravel framework itself.
I will take your example of a formatter and refer to url helper in Laravel Framework.
Start by creating your own helpers.php file:
<?php
if (! function_exists('format_that')) {
/**
* Generate something
*
* #param string $text
* #return string
*/
function format_that($text)
{
return app('formatter')->format_that($text);
}
}
And add it to your composer.json file:
"autoload": {
"files": [
"app/helpers/helpers.php"
]
}
Run this command to recreate the autoload php file:
$ composer dumpautoload
Create your service provider app/Providers/FormatterServiceProvider.php:
<?php
namespace Illuminate\Routing;
use Illuminate\Support\ServiceProvider;
use App\Helpers\FormatGenerator;
class FormatterServiceProvider extends ServiceProvider
{
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
$this->app['formatter'] = $this->app->share(function ($app) {
return new FormatGenerator($app['request']);
});
}
}
Register your service provider. Laravel framework invokes register method but you only need to add it to your app config file config/app.php:
'providers' => [
/*
* Application Service Providers...
*/
App\Providers\AppServiceProvider::class,
// other providers...
App\Providers\FormatterServiceProvider::class,
]
Finally, create your actual generator class app/Helpers/FormatGenerator.php
<?php
namespace App\Helpers;
use Illuminate\Http\Request;
class FormatGenerator
{
protected $request;
/**
* Create a new URL Generator instance.
*
* #param \Illuminate\Routing\RouteCollection $routes
* #param \Illuminate\Http\Request $request
* #return void
*/
public function __construct(Request $request)
{
$this->request = $request;
}
public function format_that($text){
if ($request->path() == "home"){
return mb_strtoupper($text);
}
else{
return $text;
}
}
}
You can optionally create a Facade app/Facade/Formatter.php, to be able to do Formatter::format_that($text):
<?php
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
/**
* #see \App\Helpers\FormatGenerator
*/
class Formatter extends Facade
{
protected static function getFacadeAccessor() { return 'formatter'; }
}
You could ask yourself:
Why the facade? You can reuse the component somewhere else by simply calling Formatter::format_that($text) instead of app('formatter')->format_that($text). Sugar syntax really.
Why the Service provider? Dependence injections. If you need to use Request or want to build a complex object, the Service provider will take care of that for you and make it available in your $app object.

Categories