I have a project working and I have simply cloned the repo and run composer install and then composer dumpautoload -o but the project can not see my classes.
compose.json
"autoload": {
"psr-4":{
"App\\": "app",
"Framework\\" : "framework"
},
"files": [
"helpers/global.php"
]
},
...
index.php
<?php
require_once __DIR__ .'/../vendor/autoload.php';
$container = new League\Container\Container;
// Auto wiring, container will load type hinted dependencies into controllers
$container->delegate(new \League\Container\ReflectionContainer());
// Get the config provider so we can get all the other providers from the config
$container->addServiceProvider(new \App\Providers\ConfigServiceProvider());
This is where the code fails with:
Class 'App\Providers\ConfigServiceProvider' not found
configserviceprovider.php
<?php
namespace App\Providers;
use Framework\Config\Config;
use Framework\Config\Loaders\ArrayLoader;
use League\Container\ServiceProvider\AbstractServiceProvider;
class ConfigServiceProvider extends AbstractServiceProvider
{
protected $provides = [
'config'
];
public function register()
{
$this->getContainer()->share('config', function(){
$loader = new ArrayLoader([
'app' => base_path('config/app.php'),
'cache' => base_path('config/cache.php')
]);
return (new Config)->load([$loader]);
});
}
}
My folder structure is like so:
app
Controllers
Providers
ConfigServiceProvider.php
Views
public
index.php
This code all works on another project so I guess I'm missing a command to make composer see these classes?
Related
I'm trying to load my custom classes for the model on Slim 3 (using the skeleton) so I made this:
In app/composer.json:
"autoload": {
"psr-4": {
"App\\Classes\\": "/src/classes"
}
},
In routes.php I have this setting:
<?php
use Slim\Http\Request;
use Slim\Http\Response;
use Slim\Container;
// Routes
$app->get('/sugiere', function (Request $request, Response $response, array $args) {
// Sample log message
$this->logger->info("Slim-Skeleton '/' route");
$cat_mapper = new \App\Classes\CategoryMapper($this->db);
$comuna_mapper = new \App\Classes\ComunaMapper($this->db);
$lang_mapper = new \App\Classes\LanguageMapper($this->db);
$netw_mapper = new \App\Classes\NetworkMapper($this->db);
$com_list = $com_mapper->getComunaList();
$cat_list = $cat_mapper->getCategoryList();
$lang_list = $lang_mapper->getLangList();
$netw_list = $netw_mapper->getNetworkList();
By the way I added to all classes a namespace App\Classes on top.
Your path /src/classes looks incorrect. It's unlikely your src directory is in the filesystem root.
Change your composer.json file to
"autoload": {
"psr-4": {
"App\\Classes\\": "src/classes/"
}
}
and run
composer dump-autoload
to re-generate the autoload.php file.
See https://getcomposer.org/doc/01-basic-usage.md#autoloading
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.
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.
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.
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.