My Controller :
<?php
namespace Admin\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Admin\Controller;
use Admin\Service;
class AdminController extends AbstractActionController
{
public function indexAction()
{
$CrudService = $this->getServiceLocator()->get('CrudService');
return new ViewModel(
array('list'=> $CrudService->getList())
);
}
}
Service Layer :
<?php
namespace Admin\Service;
use Admin\Dao;
class CrudService
{
public function getList()
{
$CrudDao=new Dao\CrudDao();
$list=$CrudDao->getList();
return $list;
}
}
Dao Layer :
<?php
namespace Admin\Dao;
class CrudDao
{
public function getList()
{
return
$this->getServiceLocator()->
get('doctrine.entitymanager.orm_default')->
getRepository('Admin\Entity\ProductEntity')
->findAll();
}
}
every things is good work But My Problem is Dao Layer. that give me This
Error : not Found get Service Locator Class
I want get data From Doctrine in Dao Layer and Call Dao Method in Service Layer And Next Call Service With getServiceLocator in Controller
You have to inject all dependencies and use the service manager to get the classes.
In you Module.php you have to register and inject the dependencies:
class Module
{
// ...
public function getServiceConfig()
{
$factories = [
'Admin\Dao\CrudDao' = function (ServiceManager $serviceManager) {
$entityManager = $serviceManager->get('Doctrine\ORM\EntityManager'),
return new CrudDao($entityManager);
},
'Admin\Service\CrudService' = function (ServiceManager $serviceManager) {
return new CrudService($serviceManager);
}
];
return $factories;
}
}
The Dao will receive the EntityManager:
<?php
namespace Admin\Dao;
class CrudDao
{
private $entityManager;
public function __construct($entityManager)
{
$this->entityManager = $entityManager;
}
public function getList()
{
return
$this->entityManager
->getRepository('Admin\Entity\ProductEntity')
->findAll();
}
}
Your CrudService will receive the Service manager, then you can get the CrudDao:
<?php
namespace Admin\Service;
use Admin\Dao;
class CrudService
{
public function __construct($serviceManager)
{
$this->serviceManager = $serviceManager;
}
public function getList()
{
$CrudDao= $this->serviceManager->get('Admin\Dao\CrudDao');
$list = $CrudDao->getList();
return $list;
}
}
And your controller:
<?php
namespace Admin\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Admin\Controller;
use Admin\Service;
class AdminController extends AbstractActionController
{
public function indexAction()
{
$CrudService = $this->getServiceLocator()->get('Admin\Service\CrudService');
return new ViewModel(
array('list'=> $CrudService->getList())
);
}
}
Related
I probably have some understanding problem with Laminas, or maybe I'm just too complicated :-)
hopefully someone can bring light in this...
I have an IndexController, an IndexController Factory and 2 Tables (User, Photos).
The Tables are all extensions of the AbstractTableGateway:
UserTable.php
<?php
declare(strict_types=1);
namespace Slideshow\Model\Table;
use Laminas\Db\Adapter\Adapter;
class UserTable extends AbstractTableGateway
{
protected $adapter;
protected $table = 'user';
public function __construct(Adapter $adapter)
{
$this->adapter = $adapter;
$this->initialize();
}
public function getUsersThatHaveAGallery()
{
// sql... select... from... where.....
}
}
PhotosTable.php
<?php
declare(strict_types=1);
namespace Slideshow\Model\Table;
use Laminas\Db\Adapter\Adapter;
class UserTable extends AbstractTableGateway
{
protected $adapter;
protected $table = 'photos';
public function __construct(Adapter $adapter)
{
$this->adapter = $adapter;
$this->initialize();
}
public function getPhotosFromUser($user_id)
{
// sql...select photos from user where id = ....
}
}
In my IndexController I'm creating an Instance of an Gallery-Class which needs the above mentioned UserTable and PhotosTable.
Is the correct way now to inject the UserTable and PhotoTable in the IndexControllerFactory.php and from the IndexController.php inject them both to the Gallery Class like this:
IndexControllerFactory.php
<?php
declare(strict_types=1);
namespace Slideshow\Controller\Factory;
use Slideshow\Model\Table\UserTable;
use Slideshow\Model\Table\PhotosTable;
use Interop\Container\ContainerInterface;
use Laminas\ServiceManager\Factory\FactoryInterface;
class IndexControllerFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestName, array $options = null)
{
return new IndexController(
$container->get(UserTable::class),
$container->get(PhotosTable::class),
$container->get('ApplicationConfig')
);
}
}
IndexController.php
<?php
declare(strict_types=1);
namespace Slideshow\Controller;
use Slideshow\Model\Table\UserTable;
use Slideshow\Model\Table\PhotosTable;
use Laminas\Mvc\Controller\AbstractActionController;
use Laminas\View\Model\ViewModel;
class IndexController extends AbstractActionController
{
private $userTable;
private $photosTable;
private $config;
public function __construct(UserTable $userTable, PhotosTable $photosTable, array $config)
{
$this->userTable = $userTable;
$this->photosTable = $photosTable;
$this->config = $config;
}
public function indexAction()
{
// At this Point now I have to inject the Tables again ?
$Gallery = new Gallery($this->userTable, $this->photosTable);
$html = $Gallery->renderUserListHtml();
var_dump($html);
}
}
Gallery.php
class Gallery {
private $userTable;
private $photosTable;
// At this point I have to inject the tables AGAIN to make them usable in the Gallery.php ?
public function __construct(UserTable $userTable, PhotosTable $photosTable)
{
$this->userTable = $userTable;
$this->photosTable = $photosTable;
{
public function renderUserListHtml()
{
$sqlResult = $this->userTable->getUsersThatHaveAGallery();
foreach($sqlResult as $k => $v) {
$html .= '<div>' . $v['user_name'] . '</div><br />';
}
return $html;
}
So my main question is: is the above written code correct ?
is it really necessary to inject the tables
from Factory to IndexController
from IndexController to Gallery Class
until I can finally "use them" in the methods of the gallery class.
It seems to be a lot of code until I finally can use them !?
A more correct way to do it would be to make a GalleryFactory class for the Gallery class which injects the UserTable and PhotosTable in to it and then inject the Gallery Object in to the IndexController in the IndexControllerFactory
in this way IndexController don't need to handle the table classes.
Like this, create a GalleryFactory that creates the Gallery object and injects the tables.
<?php
namespace Slideshow\Model\Factory;
use Slideshow\Model\Gallery;
use Slideshow\Model\Table\UserTable;
use Slideshow\Model\Table\PhotosTable;
use Interop\Container\ContainerInterface;
use Laminas\ServiceManager\Factory\FactoryInterface;
class GalleryFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestName, array $options = null)
{
return new Gallery(
$container->get(UserTable::class),
$container->get(PhotosTable::class)
);
}
}
And then change the indexControllerFactory to inject the
<?php
namespace Slideshow\Controller\Factory;
use Slideshow\Model\Gallery;
use Interop\Container\ContainerInterface;
use Laminas\ServiceManager\Factory\FactoryInterface;
class IndexControllerFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestName, array $options = null)
{
return new IndexController(
$container->get(Gallery::class),
$container->get('ApplicationConfig')
);
}
}
And change the indexController to rescive a Gallery object instead
<?php
namespace Slideshow\Controller;
use Slideshow\Model\Gallery;
use Laminas\Mvc\Controller\AbstractActionController;
use Laminas\View\Model\ViewModel;
class IndexController extends AbstractActionController
{
private $gallary;
private $config;
public function __construct(Gallary $gallery, array $config)
{
$this->gallery= $gallery;
$this->config = $config;
}
public function indexAction()
{
$html = $this->gallery->renderUserListHtml();
var_dump($html);
}
}
First, I apologize if this is a stupid question. I recently read an article about repository design pattern and I have a problem when making interface implementation for Laravel Query Builder (Illuminate\Support\Facades\DB).
DatabaseService.php
use Modules\Core\Interfaces\IDatabase;
use \DB;
class DatabaseService implements IDatabase
{
protected $db;
public function __construct(DB $db)
{
$this->db = $db;
}
public function select($str)
{
$this->db::select($str);
return $this->db;
}
public function table($tableName)
{
$this->db::table($tableName);
return $this->db;
}
...
}
IDatabase.php
<?php namespace Modules\Core\Interfaces;
interface IDatabase
{
public function select($str);
public function table($tableName);
public function raw($rawQuery);
public function transaction($callback);
public function first();
public function get();
}
CoreServiceProvider.php
...
public function register()
{
...
$this->app->bind('Modules\Core\Interfaces\IDatabase', function($app) {
$db = $app->make(DB::class);
return new DatabaseService($db);
});
...
}
MailboxRepository.php
<?php namespace Modules\Mailbox\Repositories;
use Illuminate\Database\Eloquent\Model;
use Modules\Core\Interfaces\IDatabase;
use Modules\Mailbox\Interfaces\IMailbox;
class MailboxRepository implements IMailbox
{
public function __construct(..., IDatabase $db)
{
...
$this->db = $db;
}
...
public function getBadges()
{
$badges = $this->db->table('mailbox as a')
->select($this->db->raw(
"SUM(a.type = 'inbox') as inbox,
SUM(a.is_read = 0 AND a.type = 'inbox') as unread,
SUM(a.type = 'sent') as sent,
SUM(a.type = 'draft') as draft,
SUM(a.type = 'outbox') as outbox,
SUM(a.type = 'spam') as spam,
SUM(a.type = 'trash') as trash,
SUM(a.is_starred = 1) as starred"
))
->first();
return $badges;
}
...
}
MailboxServiceProvider.php
<?php namespace Modules\Mailbox;
...
use Modules\Mailbox\Interfaces\IMailbox;
use Modules\Mailbox\Repositories\MailboxRepository;
use Modules\Core\Interfaces\IDatabase;
use Illuminate\Support\ServiceProvider;
class MailboxServiceProvider extends ServiceProvider
{
protected $defer = true;
public function register()
{
$this->app->bind(IMailbox::class, function($app) {
return new MailboxRepository(
..., $app->make(IDatabase::class)
);
});
}
public function provides()
{
return [IMailbox::class];
}
}
With error message :
[2018-01-31 13:45:04] local.ERROR: Call to undefined method Illuminate\Support\Facades\DB::select()
{"userId":1,"email":"info#narpandi.com","exception":"[object]
(Symfony\\Component\\Debug\\Exception\\FatalThrowableError(code: 0): Call
to undefined method Illuminate\\Support\\Facades\\DB::select() at
/var/www/personal-
website/app/Modules/Mailbox/Repositories/MailboxRepository.php:86)
How to do this correctly? Thank you for your kind help.
I don't think this is a common repository pattern, in repository pattern you try to create methods like:
Object get(Object id);
void create(Object entity);
void update(Object entity);
void delete(Object entity);
Edit, try to do something like docs: Database
use Modules\Core\Interfaces\IDatabase;
use Illuminate\Support\Facades\DB;
class DatabaseService implements IDatabase
{
public function select($str, $args)
{
return DB::select($str, $args);
}
}
But i say again this doesn't look like a repository.
After trial and error, I finally figure out how to do this. As mentioned in https://stackoverflow.com/a/26356144/3050636, you cannot use facade DB directly so instead you need to explicitly pass class that is behind the DB facade.
In my case, I use bridge pattern and fluent interface (CMIIW) so I will provide two versions:
Without bridge pattern
MailboxServiceProvider.php
<?php namespace Modules\Mailbox;
use Modules\Mailbox\Interfaces\IMailbox;
...
use Modules\Mailbox\Repositories\MailboxRepository;
use Illuminate\Support\ServiceProvider;
/* Use these instead of DB facade */
use Illuminate\Database\DatabaseManager;
use Illuminate\Database\Connectors\ConnectionFactory;
class MailboxServiceProvider extends ServiceProvider
{
protected $defer = true;
public function register()
{
$this->app->bind(IMailbox::class, function($app) {
return new MailboxRepository(
..., new DatabaseManager($app, new ConnectionFactory($app))
);
});
}
public function provides()
{
return [IMailbox::class];
}
}
MailboxRepository.php
<?php namespace Modules\Mailbox\Repositories;
use Illuminate\Database\DatabaseManager;
use Modules\Mailbox\Interfaces\IMailbox;
class MailboxRepository implements IMailbox
{
...
protected $db;
public function __construct(..., DatabaseManager $db)
{
...
$this->db = $db;
}
...
}
With bridge pattern and fluent interface
CoreServiceProvider.php
<?php namespace Modules\Core;
....
use Modules\Core\Services\DatabaseService;
use Modules\Mailbox\Repositories\MailboxRepository;
use Modules\Core\Interfaces\IDatabase;
use Modules\Mailbox\Interfaces\IMailbox;
/* Use these instead of DB facade */
use Illuminate\Database\DatabaseManager;
use Illuminate\Database\Connectors\ConnectionFactory;
use Illuminate\Support\ServiceProvider;
class CoreServiceProvider extends ServiceProvider
{
public function register()
{
...
$this->app->bind(IDatabase::class, function($app) {
return new DatabaseService(new DatabaseManager($app, new ConnectionFactory($app)));
});
$this->app->bind(IMailbox::class, function($app) {
return new MailboxRepository(
..., $app->make(IDatabase::class)
);
});
...
}
}
DatabaseService.php
<?php namespace Modules\Core\Services;
use Modules\Core\Interfaces\IDatabase;
use Illuminate\Database\DatabaseManager;
class DatabaseService implements IDatabase
{
protected $db;
public function __construct(DatabaseManager $db)
{
$this->db = $db;
}
public function select($str)
{
$this->db = $this->db->select($str);
return $this->db;
}
public function table($tableName)
{
$this->db = $this->db->table($tableName);
return $this->db;
}
...
}
MailboxRepository.php
<?php namespace Modules\Mailbox\Repositories;
use Modules\Core\Interfaces\IDatabase;
use Modules\Mailbox\Interfaces\IMailbox;
class MailboxRepository implements IMailbox
{
...
protected $db;
public function __construct(..., IDatabase $db)
{
...
$this->db = $db;
}
...
}
I'm building a Lumen app. I'm trying to use interface for my repositories. All my logic is wrapped in a composer package.
Here's my vendor/package/src/app/Providers/PackageServiceProvider.php:
<?php
namespace Vendor\Package\App\Providers;
use Illuminate\Support\ServiceProvider;
class SmsBackendCoreServiceProvider extends ServiceProvider
{
protected $defer = false;
public function register()
{
$this->app->bind(
'Vendor\Package\App\Repositories\Contracts\SmsService',
'Vendor\Package\App\Repositories\Services\SmsJson'
);
}
public function boot()
{
$this->app->group(
['namespace' => 'Vendor\Package\App\Http\Controllers'],
function ($app) {
require __DIR__.'/../../routes/web.php';
}
);
}
}
Here is my vendor/package/src/routes/web.php:
<?php
$app->get('/sms/send.json', 'JsonController#send');
Here is my vendor/package/src/app/Http/Controllers/JsonController.php:
<?php
namespace Vendor\Package\App\Http\Controllers;
use Vendor\Package\App\Http\Controllers\BaseController;
use Vendor\Package\App\Repositories\Contracts\SmsService;
class JsonController extends BaseController
{
public $service;
public function __construct(SmsService $service)
{
$this->service = $service;
}
public function send()
{
$response = $this->service->sendSms(1, 2, 3);
return $response;
}
}
Here is my vendor/package/src/app/Repositories/Contracts/SmsService.php:
<?php
namespace Vendor\Package\App\Repositories\Contracts;
class SmsService
{
public function sendSMS($from, $to, $text);
}
Finally, here is my vendor/package/src/app/Repositories/Services/SmsJson.php:
<?php
namespace Vendor\Package\App\Repositories\Services;
use Vendor\Package\App\Repositories\Contracts\SmsService;
class SmsJson implements SmsService
{
public function sendSMS($from, $to, $text)
{
echo 'success';
}
}
When I try to access http://mydomain.dev/sms/send.json, I get this error:
FatalErrorException in SmsService.php line 7: Non-abstract method
Mitto\SmsBackendCore\App\Repositories\Contracts\SmsService::sendSMS()
must contain body
Where did I go wrong?
Your contract is declared as a class, it must be an interface.
hello am new to phpunit test and am stuck here.
I've followed this tutorial: Zend Framework 2 : Centralize phpunit test
After that i created a module test
namespace ModulesTests\ServiceProvidersTest\Model;
use PHPUnit_Framework_TestCase;
use ModulesTests\ServiceManagerGrabber;
use User\Service\ServiceProvider;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorAwareTrait;
use Zend\Db\ResultSet\ResultSet;
use Zend\Db\Adapter\Adapter;
use Zend\Db\Sql\Sql;
class TestServiceProviders extends PHPUnit_Framework_TestCase
{
protected $serviceManager;
protected $serviceprovider;
public function setUp()
{
$serviceManagerGrabber = new ServiceManagerGrabber();
$this->serviceManager = $serviceManagerGrabber->getServiceManager();
$this->serviceprovider = new ServiceProvider() ;
}
public function testSPdetails()
{
$stack = array('1','2');
$this->serviceprovider->getDetails($stack);
}
}
In my ServiceProvider class
namespace User\Service;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorAwareTrait;
use Zend\Db\ResultSet\ResultSet;
use Zend\Db\Adapter\Adapter;
use Zend\Db\Sql\Sql;
class ServiceProvider implements ServiceLocatorAwareInterface
{
use ServiceLocatorAwareTrait;
public function getModel()
{
$em = $this->getServiceLocator()- >get('doctrine.entitymanager.orm_default');
return $em->getRepository('User\Entity\ServiceProvider');
}
public function getDetails($data = null,$fields='*')
{
$where = 1;
$company_ids = implode(',',$data);
if(isset($company_ids)){
$where = 'sp.id IN('.$company_ids.')';
}
if(isset($fields)){
}
$db = $this->getServiceLocator()->get('Zend\Db\Adapter\Adapter');
$query = 'some query';
.....Rest code.......
}
}
}
am getting this error :
Call to a member function get() on null in /opt/lampp/htdocs/project/module/User/src/User/Service/ServiceProvider.php
Please help what am missing here..??
So there are a few things I notice here:
1: You have not shown any code showing how you have hooked up your service to the service manager, so it is unclear if this will ever work
2: You directly instantiate your class when you need to be using the service manager grabber you have written
$this->serviceprovider = new ServiceProvider() ;
becomes
$serviceManagerGrabber = new ServiceManagerGrabber();
$this->serviceManager = $serviceManagerGrabber->getServiceManager();
$this->serviceprovider = $this->serviceManager->get('YOUR_SERVICE_KEY');
3: You probably should start with unit tests not these module integration tests being explained in that article. see https://framework.zend.com/manual/2.3/en/modules/zend.test.phpunit.html
4: The ServiceLocatorAwareInterface is deprecated you should probably use a factory and the factories key of service manager config to inject your dependencies
5: Your code seems to mix doctrine and zend db I don't know why you've done this, but my suggestion is ... it's be a bad idea
Here is an example of how you might put this together:
module.config.php
<?php
namespace Application;
return [
'service_manager' => [
'factories' => [
'ServiceProvider' => function ($serviceManager) {
// This shouldn't be in this anon function, it should be its own
// factory but I'm lazy and already writing loads of code for this example
// #see https://framework.zend.com/manual/2.4/en/in-depth-guide/services-and-servicemanager.html#writing-a-factory-class
$service = new \Application\Service\ServiceProvider(
$serviceManager->get('doctrine.entitymanager.orm_default')
);
return $service;
},
]
],
];
ServiceProvider.php
<?php
namespace Application\Service;
use Doctrine\ORM\EntityManager;
class ServiceProvider
{
protected $entityManager;
public function __construct(EntityManager $entityManager)
{
$this->entityManager = $entityManager;
}
public function getModel()
{
return $this->entityManager- >getRepository('User\Entity\ServiceProvider');
}
public function getDetails($data = null, $fields='*')
{
$serviceProviderRepository = $this->entityManager->getRepository('User\Entity\ServiceProvider');
return $data;
}
}
ModuleTest
<?php
namespace ModulesTests\Application\Service;
use PHPUnit_Framework_TestCase;
use ModulesTests\ServiceManagerGrabber;
class ServiceProvidersTest extends PHPUnit_Framework_TestCase
{
protected $serviceManager;
protected $serviceprovider;
public function setUp()
{
$serviceManagerGrabber = new ServiceManagerGrabber();
$this->serviceManager = $serviceManagerGrabber->getServiceManager();
$this->serviceprovider = $this->serviceManager->get('ServiceProvider');
}
public function testSPdetails()
{
$stack = array('1','2');
$this->serviceprovider->getDetails($stack);
}
}
unit test:
<?php
namespace ModulesTests\Application\Service;
use PHPUnit_Framework_TestCase;
use Application\Service\ServiceProvider;
use Prophecy\Argument;
class ServiceProvidersUnitTest extends PHPUnit_Framework_TestCase
{
protected $entityManager;
protected $serviceprovider;
public function setUp()
{
$this->entityManager = $this->prophesize("Doctrine\\ORM\\EntityManager");
$this->entityManager->getRepository(Argument::exact('User\Entity\ServiceProvider'))
->willReturn(true);
$this->serviceprovider = new ServiceProvider($this->entityManager->reveal());
}
public function testSPdetails()
{
$stack = array('1','2');
$this->serviceprovider->getDetails($stack);
$this->entityManager->getRepository(Argument::exact('User\Entity\ServiceProvider'))
->shouldHaveBeenCalledTimes(1);
}
}
sorry for my english.
stack: Slim 3 framework + Eloquent ORM.
Eloquent works as expected with Slim.
I want to use sort of a MVC pattern where thin controllers and fat models(all db queries and other heavy logic).
All I found is how to use it from routes like this:
$app->get('/loans', function () use ($app) {
$data = DB::table('loan_instalment')->get(); // works
$data = $this->db->table('loan_instalment')->get(); // works
...
}
What I want is ability to call public methods from choosen model, something like this:
use \src\models\Instalment;
$app->get('/loans', function () use ($app) {
$data = $this->model('Instalment')->getSomething(12);
...
}
and Model class is:
namespace src\models;
use Illuminate\Database\Eloquent\Model as Model;
use Illuminate\Database\Capsule\Manager as DB;
class Instalment extends Model
{
protected $table = 'loan_instalment';
public function getSomething($id)
{
return $this->table->find($id);
}
// bunch of other methods
}
My app looks like basic Slim skeleton, Eloquent settings:
$capsule = new \Illuminate\Database\Capsule\Manager;
$capsule->addConnection($container['settings']['db']);
$capsule->setAsGlobal();
$capsule->bootEloquent();
$container['db'] = function ($container) use ($capsule){
return $capsule;
};
Is it possible ?
If you want to use MVC pattern, you need to make base controller.
<?php
namespace App\Controller;
use Slim\Container;
class BaseController
{
protected $container;
public function __construct(Container $container)
{
$this->container = $container;
}
public function getContainer()
{
return $this->container;
}
public function __get($name)
{
return $this->container->{$name};
}
public function __set($name, $value)
{
$this->container->{$name} = $value;
}
}
And the container:
// Base Controller
$container[App\Controller\BaseController::class] = function ($c) {
return new App\Controller\BaseController($c);
};
$capsule = new \Illuminate\Database\Capsule\Manager;
$capsule->addConnection($container['settings']['db']);
$capsule->setAsGlobal();
$capsule->bootEloquent();
$container['db'] = function ($container) use ($capsule){
return $capsule;
};
Highly recommended to use static function on models
<?php
namespace App\models;
use Illuminate\Database\Eloquent\Model as Model;
use Illuminate\Database\Capsule\Manager as DB;
class Instalment extends Model
{
protected $table = 'loan_instalment';
public static function getSomething($id)
{
return Instalment::find($id);
}
}
And now you code become:
<?php
use App\models\Instalment;
$app->get('/loans', function ($request, $response, $args) {
$data = Instalment::getSomething(12);
...
}
The controller:
<?php
namespace App\Controller;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
use App\models\Instalment;
class HomeController extends BaseController
{
public function __invoke(Request $request, Response $response, Array $args)
{
$data = Instalment::getSomething(12);
// load the template
return $response;
}
}
And the route for the controller
<?php
$app->get('/', App\Controller\HomeController::class);
It looks cleaner, isn't it?
More tutorial:
My Blog
Rob Allen's Blog
You could use the abbility of Slim to use controllers.
Make a basic controller:
// BasicController.php
<?php
namespace src\Controllers;
class BasicController
{
public function model(string $model)
{
return new $model();
}
}
and then in your controllers extend this class and add it to the slim container
//SomeController.php
<?php
namespace src\Controllers;
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
use \src\models\Instalment as Instalment;
class SomeController extends BasicController
{
public function index(Request $request, Response $response, $args)
{
$this->model(Instalment::class)->getSomethingOutOfDB;
//do something else
}
}
...
//container.php
use \Slim\Container as Container;
$container[\src\Controllers\HomeController::class] = function(Container $container) {
return new \src\Controllers\Homecontroller();
}
...
...
//routes.php
$app->get('/someroute', \src\Controllers\HomeController::class . ':index');
...
Another possibility is to extend your \Slim\App by:
//newApp.php
namespace scr\App
class newApp extends \Slim\App
{
public function model(string $model)
{
return new $model();
}
}
I actually would advice against these both methods, and not load your models in this way, since this is considered bad practice.
It is better just to use:
//routes.php
...
use src\Models\Instalment;
...
...
$app->get('/someroute', function() {
$instalment = new Instalment();
// do something with it...
});