PHP autoloading class not found - php

let me first explain what I have done to reach this point. There is a tutorial on github called no-framework here it is https://github.com/PatrickLouys/no-framework-tutorial very good tutorial! I have completed it and am now wanting to add more libraries. I have composer setup with autoloading and the file looks like this.
{
"name": "xxx/no-framework",
"description": "no framework",
"authors": [
{
"name": "xxx",
"email": "xxx#gmail.com"
}
],
"require": {
"php": ">=5.5.0",
"filp/whoops": ">=1.1.2",
"patricklouys/http": ">=1.1.0",
"nikic/fast-route": "^0.7.0",
"rdlowrey/auryn": "^1.1",
"twig/twig": "~1.0",
"illuminate/database": "*"
},
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
and In my src folder I have made a folder called Models and in there a Books.php and in the Books.php I have this
<?php
class Book extends \Illuminate\Database\Eloquent\Model{
protected $table = 'books';
}
and in my Bootstrap.php file I've included this line after requiring the composer autoloader
include('Database.php');
The Database.php file is also in the src and looks like this
<?php
use \Illuminate\Database\Capsule\Manager as Capsule;
$capsule = new Capsule;
$capsule->addConnection(array(
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'test',
'username' => 'test',
'password' => 'l4m3p455w0rd!',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => ''
));
$capsule->bootEloquent();
And now the error. When I try to use to Book class by trying to use it in one of my controller like this
<?php
namespace App\Controllers;
use Http\Request;
use Http\Response;
use App\Template\Renderer;
use App\Models\Book as Book;
class Pages{
private $request;
private $response;
private $renderer;
public function __construct(Request $request, Response $response, Renderer $renderer){
$this->request = $request;
$this->response = $response;
$this->renderer = $renderer;
}
public function index(){
$book = new Book;
$book->title = 'test';
$book->save();
$html = $this->renderer->render('index');
$this->response->setContent($html);
}
}
I get an error saying "Class 'App\Models\Book' not found" I'm asuming im not autoloading something correctly, but the alias thing is there in the composer.json or maybe something else is wrong idk. help?
The tutorial uses a dependency injector library called Auryn, maybe I'm missing something in there? idk doubt it though.
EDIT: If i change the use statement to to an include like so
include('../src/Models/Book.php');
and put a \ in front of the class instantiation like so
$book = new \Book;
and then it works, BUT this is clearly not the right way.

I believe the Composer classmap merely tells the system where to find the files for a given class. PHP still needs to know the namespaces. Pages is in the App\Controllers namespace. Book is not given one, so it will exist in the global namespace at \Book. Your Books.php (names of files usually match the class they contain, so would be Book.php) should include a namespace declaration. I suggest namepsace App\Models;. You could also change your use statement to use \Book.
Notice you don't need to alias it. It's the only Book class you're using so just as you did with Request the class can be referenced by the last segment of it's fully namespaced designation.

Related

How to create a method able for use everywhere in Laravel [duplicate]

This question already has answers here:
How to create custom helper functions in Laravel
(23 answers)
Closed 7 months ago.
I want to make some changes to dates, for example, I want to explode it do some operation and implode it again, and I want to use it all around my app so here is my code :
$divided_date = explode('/', $request->point_date);
$converted_date = Verta::getGregorian($divided_date[0], $divided_date[1], $divided_date[2]); // [2015,12,25]
$begindate = implode('/', $converted_date);
I want to make a function called DateConvertor() for example, and anywhere that I want to convert the date I use something like below.
$request->somedate()->DateConvertor();
or for example
Dateconvertor($request->someday);
And it returns the converted date so now I don't know to use the static method or no, and I don't know where to define it so I can use it in all of my app not just a single model.
You can create a Helper.php file and in composer.json include that file as
"files": [
"app/Helpers/Helper.php",
]
or may add a helper class like
<?php
namespace App\Helpers;
class Helper
{
public static function foo()
{
return 'foo';
}
}
and config/app.php
'aliases' => [
....
'Helper' => App\Helpers\Helper::class,
]
and then use as Helper::foo();
or add a service provider like
php artisan make:provider HelperServiceProvider
in register method
public function register()
{
require_once app_path() . '/Helpers/Custom/Helper.php';
}
In config/app.php
providers =
[
'CustomHelper' => App\Helpers\Custom\Helper::class,
]
and
'aliases' => [
'CustomHelper' => App\Helpers\Custom\User::class,
]
then use as
CustomHelper::foo();
create a function in a php file and add it in composer.json file inside "autoload" attribute, like this:
"autoload": {
"psr-4": {
"App\\": "app/"
},
"classmap": [
"database/seeds",
"database/factories"
],
"files": [
"app/Helpers/CustomHelper.php"
]
}
and run composer dump-autoload command, Here - CustomHelper.php is the file, i want to autoload and their function can be used anywhere in your project
CustomHelper.php
<?php
if (! function_exists('getOTP')) {
function getOTP()
{
return str_pad(rand(0, pow(10, 4) - 1), 4, '0', STR_PAD_LEFT);
}
}
?>
now you can call getOTP() function anywhere in your project

Elastic search configurations not working in laravel v5.3

I have setup new laravel v5.3 project and install elastic search driver to implement elastic search via composer. But when I reload my page then I always receive This page isn’t working even the elastic search is running on my system below is my complete code that I code.
composer.json
"require": {
"php": ">=5.6.4",
"elasticsearch/elasticsearch": "^6.0",
"laravel/framework": "5.3.*"
},
web.php
Route::get('/',array('uses' => 'ElasticSearch#addPeopleList'));
Controller
<?php
namespace App\Http\Controllers;
class ElasticSearch extends Controller
{
// elastic
protected $elastic;
//elastic cliend
protected $client;
public function __construct(Client $client)
{
$this->client = ClientBuilder::create()->build();
$config = [
'host' =>'localhost',
'port' =>9200,
'index' =>'people',
];
$this->elastic = new ElasticClient($config);
}
public function addPeopleList(){
echo "<pre>";
print_r($this->$elastic);
exit;
}
}
But when I refresh the page then This page isn’t working i received this message and page not loaded one thing that I want to let you know that I made no changes in app.php file of configuration. Please eduacate to solve this issue.
if You want to instantiate an elastic client with some configuration, You should use method ClientBuilder::fromConfig(array $config).
In your case it should be
<?php
$client = ClientBuilder::fromConfig([
'hosts' => [ 'localhost:9200' ]
]);
As You can notice above hosts must be provided as array.
Also I'm not sure that Elasticsearch client that You use have ElasticClient class.
Also if You provided actual code from your controller than it contains an error. You should call class properties like that: print_r($this->client) (without $ near the property name).
Finaly your controller should looks like this:
<?php
namespace App\Http\Controllers;
use Elasticsearch\ClientBuilder;
class ElasticSearch extends Controller
{
/**
* #var \Elasticsearch\Client
*/
protected $client;
public function __construct()
{
$this->client = ClientBuilder::fromConfig([
'hosts' => [
'localhost:9200',
],
]);
}
public function addPeopleList(){
echo "<pre>";
print_r($this->client);
exit;
}
}
And to add a document to the index You need to call this command according to the official documentation
$params = [
'index' => 'my_index',
'type' => 'my_type',
'id' => 'my_id',
'body' => ['testField' => 'abc']
];
$response = $client->index($params);
print_r($response);
Official documentation can be found here https://github.com/elastic/elasticsearch-php
P.S. Sorry for my English. It is far from perfect.

Monolog in Silex application

I try to use Monolog in my Silex application, according to the doc
http://silex.sensiolabs.org/doc/master/providers/monolog.html
I declare MonologServiceProvider in the app.php file as follow:
use Silex\Provider\MonologServiceProvider;
$app->register(new MonologServiceProvider(), array(
'monolog.logfile' => __DIR__ . '/../files/logs/log.log',
));
And I try to write in my log.log file on the controler:
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
// In a controler
$app['monolog']->info("test");
$app['monolog']->debug("test");
$app['monolog']->warning("test");
$app['monolog']->error("test");
I don't have any error, but it is not working at all.
I just wan't to put my "test" message in my log.log file, how can I do that ?
Thanks for help
I can't really answer your question based on the info you've given, but it's a slow-news day here, so strummed-up a working Silex site with working logging. All the files are on Github, but I'll repeat them here for ease of reading.
composer.json
{
"require" : {
"silex/silex" : "^2.0",
"monolog/monolog" : "^1.0"
},
"autoload" : {
"psr-4" : {
"community\\" : "src/"
}
}
}
public/index.php
<?php
use \community\app\Application;
require_once realpath(__DIR__ . '/../vendor/autoload.php');
$app = new Application();
$app["debug"] = true;
$app->run();
src/app/Application.php
<?php
namespace community\app;
use \Silex\Application as SilexApplication;
use Silex\Provider\MonologServiceProvider;
class Application extends SilexApplication {
function __construct() {
parent::__construct();
$this->registerServices();
$this->mountControllers();
}
function registerServices(){
$this->register(new MonologServiceProvider(), [
"monolog.logfile" => realpath(__DIR__ . "/../../log") . "/general.log"
]);
}
function mountControllers() {
$this->get('/testLog', 'community\controller\TestLogController::doGet');
}
}
src/controller/TestLogController.php
<?php
namespace community\controller;
use community\app\Application;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class TestLogController {
public function doGet(Request $request, Application $app) {
$app["monolog"]->info("hi!");
return new Response("All good", Response::HTTP_OK);
}
}
That writes to log/general.log as follows:
[2016-12-28 13:58:05] app.INFO: hi! [] []
One thing I noticed is that if the path to the log file is bung, then Monolog just seems to swallow it (which is not exactly ideal). This could well be your issue.
Anyway, grab the code above and mess around with it. Hopefully you'll be able to work out the differences between yours and mine, and get yours working.

Slim Framework and Eloquent ORM

I'm using Slim Framework together with Laravel's Eloquent ORM and this is my code:
User.php
class User extends \Illuminate\Database\Eloquent\Model
{
protected $table = 'accounts';
}
index.php
require_once 'vendor/autoload.php';
// Models
include 'app/models/User.php';
$app = new \Slim\Slim();
// Database information
$settings = array(
'driver' => 'mysql',
'host' => '127.0.0.1',
'database' => 'photo_mgmt',
'username' => 'root',
'password' => '',
'collation' => 'utf8_general_ci',
'prefix' => '',
'charset' => 'utf8',
);
$container = new Illuminate\Container\Container;
$connFactory = new \Illuminate\Database\Connectors\ConnectionFactory($container);
$conn = $connFactory->make($settings);
$resolver = new \Illuminate\Database\ConnectionResolver();
$resolver->addConnection('default', $conn);
$resolver->setDefaultConnection('default');
\Illuminate\Database\Eloquent\Model::setConnectionResolver($resolver);
$app->get('/', function () use ($app) {
$users = \User::all();
echo $users->toJson();
});
$app->run();
As you can see in my code, I have to include the User.php file in my index.php. But what if I have multiple models? Can I just include a folder and all models will also be included so that it won't look messy including every model file in my index.
Thank you in advance.
UPDATE:
I'm using this piece of code I saw
foreach (glob("app/models/*.php") as $filename)
{
include $filename;
}
Is there a cleaner looking way?
You can use Composer to automatically include classes from your project. Let's say your composer.json file lives in app. Then you can use the classmap attribute in your composer.json to automatically include all classes in models:
...
"require": {
"php" : ">=5.4.0",
"slim/slim" : "2.*",
"illuminate/database" : "5.0.33",
...
},
"autoload": {
"classmap" : [
"models"
]
}
The classmap tells Composer to map all classes in the specified directory(ies). Then, all you need to do is run composer update to update Composer's list of includes whenever you add a new file to this directory.
Yes, there is a much cleaner way to do this, namely autoloading.
It boils down to the use of spl_autoload_register() and of a custom class loader.
The principle is to mimic the namespace with the file hierarchy and load these accordingly to the namespace:
$loader = function load($class)
{
include __DIR__."/app/$class.php";
}
spl_autoload_register($loader);
$user = new models\User();
This will automatically include the file located at app/models/User.php. It is a good practice to respect uppercases in your namespace; if you namespace is Model\User, the directory should respect the casing (app/Model/User.php)
The problem with your current solution:
foreach (glob("app/models/*.php") as $filename)
{
include $filename;
}
is that it will load all classes, even if the script will not use them. Registering an autoloader will prevent that, only loading the necessary code.

Instantiating twig in a namespaced class

I'm running into some issues trying to figure out how to use Twig in a specific way. I'm trying to write a view class that I can use in my application regardless of what template system is installed, that way the only things I would have to change would be the templates themselves and the view class.
However, when I try and create the twig objects in the class, I get Fatal error: Class 'Template\Twig_Loader_Filesystem' not found errors, and I'm not really sure what I'm missing.
Can someone point me in the right direction?
Here's what I've got so far...
composer.json
{
"name": "Movies",
"description": "Find movies",
"require": {
"ext-curl": "*",
"twig/twig": "~1.0"
},
"autoload": {
"classmap": [
"app/classes"
]
}
}
index.php
require_once 'app/app.php';
use Template\Template;
echo Template::render('hello.html', array('name' => 'bob', 'age' => '33'));
app/app.php
define('APP_DIRECTORY', __DIR__ . '/..');
require_once APP_DIRECTORY . '/vendor/autoload.php';
app/classes/Template.class.php
namespace Template;
class Template {
static function render($template_name, $template_data = array()) {
$loader = new Twig_Loader_Filesystem(APP_DIRECTORY . '/app/templates');
$twig = new Twig_Environment($loader);
return $twig->render('hello.html', array('name' => 'lisa', 'age' => '33'));
}
}
Ok, it turned out whenever I would try and include the twig namespaces on my Template class, I was doing it wrong. Looking at other projects my organization has put together, it turns out just adding
use Twig_Environment;
use Twig_Loader_Filesystem;
to the class is enough. I wasn't sure if I actually had to add anything, since the Autoloader was included, or if I had to include part of the path, like Twig_Twig/Loader/Filesystem or something like that. Obviously neither of those was working.

Categories