Using Restler 3.0.0-RC6, which internally packages swagger-ui, I have an API method defined like so:
<?php
namespace v1:
class PostgreSQL {
public function fetchArray($sql, $args = null) {
And then all of my classes that I include via Restler's addAPIClass extend that PostgreSQL class. That means when swagger runs, every single API shows a fetchArray function. I'd like to have that method not appear in the swagger documentation as it's not really part of the API. Other 'things' on the website also use the class though so I can't change the modifier from public.
What's the proper syntax to hide that method from swagger-ui's webpage?
There are two ways to achieve this,
One is to mark the fetchArray method as private with #access private comment. This will remove fetchArray from all api urls while keeping the fetchArray still accessible for PHP
Problem in your case is that you don't want to modify the PostgreSQL as its part of a framework that is maintained by composer. Instead of directly extending it from the base class use an intermediary class which adds the comment and then extend that class as shown below
class Base {
public function fetchArray(){
return array();
}
}
class Intermediary extends Base {
/**
* #access private
*/
public function fetchArray(){
return array();
}
}
class MyApi extends Intermediary { //instead of extends Base
//other api methods here
//see in the explorer to note that fetchArray is no longer listed
}
Another way is to just exclude it on Explorer with
use Luracast\Restler\Explorer;
Explorer::$excludedPaths = array('myapi/fetcharray','another/fetcharray');
You should not extend your API layer class from a data layer class. Just use the data layer class.
class DataLayer
{
public function fetchArray()
{
return array();
}
}
class ApiLayer
{
private $dl;
function __construct()
{
$this->dl = new DataLayer();
}
public function getAll()
{
return $this->dl->fetchArray();
}
}
Related
I was just wondering if there is a way to use codeigniter model in other non Codeigniter classes... Let me give you an example.
I have this MyTestClassTests class which extends PHPUNIT_Framework_testCase
<?php
require_once '../../vendor/autoload.php';
use Facebook\WebDriver\Remote\WebDriverCapabilityType;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\WebDriverBy;
use Facebook\WebDriver\Interactions\WebDriverActions;
use Sunra\PhpSimple\HtmlDomParser;
class MyTestClassTests extends PHPUnit_Framework_TestCase
{
public function testDoSomething()
{
// Do some test
// get results
// Store results via Codeigniter Model, if possible?
$results = 'some results';
$this->load->model('results');
$this->results->import($results);
}
}
Now once test is finished i would like to store test results in to the database. Is there a way to call/initialize CodeIgniter model in current class to use it and store data? This file is located in the Codeigniters controllers folder.
If you need any additional information's please let me know and i will provide. Thank you!
Since you appear to be unit testing you should consider using ci_phpunit-test which makes it much easier to use PHPUnit with CodeIgniter 3.x.
Because you're unit testing the following may not apply. These examples only work within an fully instantiated CI framework. Within that context there are a couple ways to give a stand-alone class access to the CI object.
One approach is to capture the CI instance in a class property.
class MyTestClassTests extends PHPUnit_Framework_TestCase
{
protected $CI;
public function __construct()
{
// Assign the CodeIgniter super-object
$this->CI = & get_instance();
}
public function testDoSomething()
{
// Do some test
// get results
// Store results via Codeigniter Model, if possible?
$results = 'some results';
//use the class property to access CI classes and methods
$this->CI->load->model('results');
$this->CI->results->import($results);
}
}
A second approach uses the PHP magic method __get. The advantage is it's much easier to write the code. The disadvantage is it's a tiny bit less efficient because extra code is executed each time you access the CI instance.
class MyTestClassTests extends PHPUnit_Framework_TestCase
{
/**
* Enables the use of CI super-global without having to define an extra variable.
*
* #param $var The CI property or method to access
* #return mixed
*/
public function __get($var)
{
return get_instance()->$var;
}
public function testDoSomething()
{
// Do some test
// get results
// Store results via Codeigniter Model, if possible?
$results = 'some results';
//you get to write code as if you were part of the CI object.
//IOW, you write code normally
$this->load->model('results');
$this->results->import($results);
}
}
In order to use codeigniter model in your non codeigniter class you have to instantiate CI first.
In your case below code will work.
$CI = & get_instance()
$CI->load->model('results');
$CI->results->your_function();
I have a class that contains methods used globally, and am using them by extending the class:
App.php
final class App extends Core {
// The app class handles routing and basically runs the show
}
Core.php
abstract class Core {
public function __construct() { // Here we bring in other classes we use throughout the app
$this->Db = new Db($this);
$this->Mail = new Mail($this);
}
// Then we define multiple methods used throughout the app
public function settings($type) {
// You see this used by the model below
}
}
index.php
$App = new App(); // This fires up the app and allows us to use everything in Core.php
Up until now, this is all great, because everything is handled throughout the site from within $App. However, within my MVC structure, the models need to pull data from the database, as well as retrieve other settings all contained in Core. We do not need the entire $App class to be used by the models, but we need Core to be.
MyModel.php
class MyModel extends Core {
public function welcome() {
return 'Welcome to '.$this->settings('site_name');
}
}
Once MyModel.php comes into play, the Core constructor is run a second time. How do I keep the Core constructor from being run twice?
you can use a static instance in the core class and reuse it.
abstract class Core {
public static $instance; //create a static instance
public function __construct() { // Here we bring in other classes we use throughout the app
$this->Db = new Db($this);
$this->Mail = new Mail($this);
self::$instance = $this; // initialise the instance on load
}
// Then we define multiple methods used throughout the app
public function settings($type) {
// You see this used by the model below
}
}
in the model class, use it like this
class MyModel extends Core {
public function welcome() {
$_core = Core::instance; // get the present working instance
return 'Welcome to '.$_core->settings('site_name');
}
}
you can take a look at this singleton reference
additionally you can check this answer explain-ci-get-instance
I'm tring to declare interfaces for my classes like this:
namespace Helpers\Interfaces {
interface Cache {
public static function getInstance($profile = null);
}
}
And then I apply them like this:
namespace Helpers {
class Cache implements Interfaces\Cache {
public static function getInstance($profile = null) {
/* ... */
}
}
}
So far, so good (apparently, at least). The problem I have is NetBeans gives me an error stating my class is not abstract and doesn't implement a certain method.
The method belongs to an object I created to gather the configuration parameters needed to operate certain methods without providing specific configuration options depending on the object (like host, port, API key, etc.).
This method is, in this example, called as \Configuration\Helpers\Cache::getConfiguration($profile);
The conflicting declaration comes from this interface:
namespace Configuration\Helpers\Interfaces {
interface Cache {
public static function getConfiguration($profile = null);
}
}
Which is applied as follows:
namespace Configuration\Helpers {
class Cache implements Interfaces\Cache {
public static function getConfiguration($profile = null) {
/* ... */
}
}
}
It's effectively mixing the interfaces, although they're namespaced!
Something I would like to note is both the interface and the class declaration implementing such interface are always in the same file, one file per object.
PHP version is 7.0.13 on NetBeans 8.2.
What am I doing wrong?
Your interfaces and classes are in different namespaces. You may need to add a use statement to your class. For example you can add: use Helpers\Interfaces as Interfaces. This line can go above the class definition: class Cache implements Interfaces\Cache.
See also: http://php.net/manual/en/language.namespaces.definitionmultiple.php
I am having some trouble with Symfony2. Namely in how to use the __construct() function. the Official Documentation is shockingly bad!
I want to be able to use the following:
public function __construct()
{
parent::__construct();
$user = $this->get('security.context')->getToken()->getUser();
}
How ever I get the following error:
Fatal error: Cannot call constructor in /Sites/src/DEMO/DemoBundle/Controller/Frontend/HomeController.php on line 11
Line 11 is "parent::__construct();"
I removed it and got the following, new error
Fatal error: Call to a member function get() on a non-object in /Sites/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php on line 242
I think I might need to set up the ContainerInterface DIC, but I have no idea how to do this (I tried and failed, miserably)
Any ideas folks?
Update - Tried changing to extend ContainerAware and got this error:
Fatal error: Class DEMO\DemoBundle\Controller\Frontend\HomeController cannot extend from interface Symfony\Component\DependencyInjection\ContainerAwareInterface in /Sites/src/DEMO/DemoBundle/Controller/Frontend/HomeController.php on line 43
Using the following code in the controller:
<?php
namespace DEMO\DemoBundle\Controller\Frontend;
use Symfony\Component\DependencyInjection\ContainerAware;
class HomeController extends ContainerAwareInterface
{
protected $container;
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
I'm assuming you are extending the default Symfony controller? If so, a look at the code will reveal the answer:
namespace Symfony\Bundle\FrameworkBundle\Controller;
use Symfony\Component\DependencyInjection\ContainerAware;
class Controller extends ContainerAware
{
Notice that there is no Controller::__construct defined so using parent::__construct will not get you anywhere. If we look at ContainerAware:
namespace Symfony\Component\DependencyInjection;
class ContainerAware implements ContainerAwareInterface
{
protected $container;
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
}
Again, no constructor and the container is not available until setContainer is called. So override setContainer and put your logic there. Or else just make a stand alone controller that does not extend the base controller class and inject your dependencies directly into the constructor.
Update Aug 2017
Still getting a few hits on this. If you really want to execute something before each controller then use a kernel controller listener. If all you need is the user then of course use getUser(). And please don't override setContainer(). In some cases it would work but it would just convolute your code.
I also frequently want an instance of the current User in most of my controllers. I find it is easiest to just do something like this:
class SomeController extends Controller
{
protected $user;
public function getUser()
{
if ($this->user === null) {
$this->user = $this->get('security.context')->getToken()->getUser();
}
return $this->user;
}
}
However, this is an overly simplistic example case. If you want to do more work before a Controller action is started, I suggest you define your Controller as a Service.
Also take a look at this article: Moving Away from the Base Controller
I have to retrieve the 'facade' manager for my rest api's resource. Not using the constructor and using a private function seems the easiest and simplest for me.
/**
* Class ExchangesController
* #RouteResource("Exchange")
*/
class ExchangesController extends Controller
{
/**
* Get exchange manager
* #return ExchangeManager
*/
protected function getExchangeManager()
{
return $this->get('exchange_manager');
}
/**
* #ApiDoc(
* description="Retrieve all exchanges",
* statusCodes={
* 200="Successful"
* }
* )
*/
public function cgetAction()
{
return $this->getExchangeManager()->findAll();
}
PS It's ok for me to use private/protected functions in my controller as long as it contains zero conditionals
You cannot call getUser() or get() for services in controller constructors. If you remember that, you will save lots of debugging time.
I know the question is very old, but I didn't found an answer until now. So I'll share it.
The goal here, is to execute a code everytime a action in our controller is called.
The __construct method doesn't work, because it's called before anything else, so you can't access the service container.
The trick is to overload each method automatically when they are called :
<?php
namespace AppBundle\DefaultController;
class DefaultController extends Controller {
private function method1Action() {
return $this->render('method1.html.twig');
}
private function method2Action() {
return $this->render('method2.html.twig');
}
public function __call($method, $args) {
$user = $this->get('security.tokenStorage')->getToken()->getUser();
// Do what you want with the User object or any service. This will be executed each time before one of those controller's actions are called.
return call_user_func_array(array($this, $method), $args);
}
}
Warning ! You have to define each method as a private method ! Or the __call magic method won't be called.
There are only two solutions to this problem:
Use a private method as pointed out by #Tjorriemorrie here. But this is a dirty method for purists. (I'm using this! :D );
Define the controller as a service, but this way you will lose all the shortcuts provided by Symfony\Bundle\FrameworkBundle\Controller\Controller. Here is the article that shows how to do this.
As told, personally, in my situation, I prefere a solution like this:
class MyController extends Controller
{
/** #var AwesomeDependency */
private $dependency;
public function anAction()
{
$result = $this->getDependency();
}
/**
* Returns your dependency.
*/
private function getDependency()
{
if (null === $this->dependency)
$this->dependency = $this->get('your.awesome.dependency');
return $this->dependency;
}
}
This is typically a class that I call MyManager where I put the code that I use in more than one action in the controller or that unusefully occupies lines (for example the code to create and populate forms, or other code to do heavy tasks or tasks that require a lot of code).
This way I mantain the code in the action clear in its purposes, without adding confusion.
Maybe the use of a property to store the dependency is an overoptimization, but... I like it :)
As i see, Controller extends ContainerAware, and if we take a look of ContainerAware it implements ContainerAwareInterface. So, ContainerAware must have declared the exact methods in it's interface. Add this line
public function __construct();
to the ContainerAwareInterface definition and it will be solved.
Intro
I'm developing an MVC framework, and I've run into a problem. It seems what I was trying to accomplish is known as the Singleton Design method -- initializing classes only once. Remember that I'm trying to put as less code in the controller "acontroller" as possible.
With that said, a final question remains: how can I add objects to an object that has already been instantialized?
It may help to have or at least see actual source instead of just example source, so I have pushed my source to my github. You can find that here: https://github.com/derekmaciel/uMVC
Code explanation
What's happening "under the hood" is first,
The Controller class loads a controller located in /application/controller, in this case "acontroller".
After, the acontroller class loads a model (called "amodel") using the Load class, using $this->load->model("amodel"), which was instantialized in the Controller __construct.
The final outcome of $this->load->model("amodel") is: $controller->amodel =& new Amodel(), where $controller is the Controller instance (not acontroller, because the controller loading the model will vary).
Step 4: Allow acontroller access to models that were loaded (amodel).
Code result
A copy of the current output of these scripts can be found here: http://pastebin.com/EJxuXaki
The first thing you'll notice is that I'm given a warning for using a deprecated assignment. I'm going to focus on the error for now.
The second thing you'll notice is that I first print_r()'d the Controller instance. Inside there is an amodel object, which is want to add to acontroller.
After that, I print_r()'d the $this (acontroller) object. It has everything it got from __construct(), but not amodel.
If I can get acontroller to "see" amodel, then my problem will be solved.
Also:
Is there anyway for me to remove "parent::init()" from the controller acontroller? I only did that so acontroller could have access to both the Load and Model class, but I'm trying to put as less code as possible in acontroller, so having the acontroller have access to Load and Model automatically would help a lot.
I hope I was clear. Thanks for any help
I personally do not think that singleton methods belong within an MVC Framework, the reason for this is because the main objects that are loaded are Models,Libraries and controllers, everything else such as the Router is usually hard coded.
The structure that i would do is create the following classes:
ModelLoader
LibraryLoader
and have them included during system boot, then within your main controller do the following:
class Controller
{
public $library;
public $model;
public function __construct()
{
$this->library = new LibraryLoader();
$this->model = new ModelLoader();
}
}
this would expose the 2 loaders to the child controller, your model/library should hold a private array storing the loaded objects, a little something like this:
class LibraryLoader extends ObjectLoader
{
protected $_path = "/app/library/";
protected $_ext = '.php';
}
class ModelLoader extends ObjectLoader
{
protected $_path = "/app/models/";
protected $_ext = '.php';
}
the object loader would look like so:
class ObjectLoader
{
protected $_path = "/app/";
protected $_ext = '.php';
public function __get($item)
{
/*
* Load item here, the paths above would be overwritten
* store the object in an array, make sure you check if its already loaded
*/
}
}
this is pretty basic, but within your child controllers such as index / home etc you can do the following:
class indexController extends Controller
{
public function index()
{
$this->model->users->getUser(22);
$this->library->security->validateInput("get","key");
//As the objectLoader manages whats loaded, any further calls to the above would
//use the same objects initiated as above.
}
}
This should get you started, its more streamline them using the singleton approach.
I guess you need to include Model.php in your controller.php to be able to use model class.
include 'Model.php';
include 'Load.php';
Since PHP 5.3 you can use the static keyword to instantiate a class
abstract class singleton
{
/**
* Holds an insance of self
* #var $instance
*/
protected static $instance = NULL;
/**
* Prevent direct object creation
*/
final private function __construct() { }
/**
* Prevent object cloning
*/
final private function __clone() { }
final public static function getInstance()
{
if(null !== static::$instance){
return static::$instance;
}
static::$instance = new static();
return static::$instance;
}
}
class myclass extends singleton
{
}
$myclass = myclass::getInstance();