I have a controller which have a function test(). I want to make this function inaccessible when access by the URL and I can't make private or protected because I want the same function to used by other controllers.
How can I achieve this, any suggestions?
If the function file is brought in by include or require functions to the controller file then you could have something like this at the start of your function file:
defined("CONTROLLER") or die();
Then, before the include function calls the function file in, use:
define("CONTROLLER", true);
That way, the function file is killed by the die() command when accessed directly but runs as normal on any page you specifically included it in.
Related
Hi I have a class which includes two methods.
One of which is to initialize session , another one is for redirect the web page
I ve written the class such that it can be called repeatedly.
$obj->setSession(key,value)->redirect(url);
In this mode , the session is firstly initialized and then it redirects to the next page.
But if it's written like this
$obj->redirect(url)->setSession(key,value);
It just redirects to the defined location qnd the session is not initialized anymore ..
It s cuz when the resirect method is called, the page changes promptly and it causes the second method not to be called ..
Is there any way to be able to call methods repeatedly without the need of considering their order ?
When I usually face that issue, I add a method in the $obj object called render() or done() or something to that effect that checks all the flags I might have defined previously. One of those flags might be a header flag, which is what a redirect method usually does header(Location: $yourDestUrl).
So you end up with something like:
$obj->redirect(url)->setSession(key,value)->render();
When you call a method such as redirect or setSession, put those actions in a "stack" as a property of you class.
Then, when all your methods are called, call a method called exec (for example) that will execute all the actions in the "stack".
Here is a base class based on this idea using magic methods:
class Stack {
private $_stack = array();
public function __call($method, $args) {
// Adding method to stack
$this->_stack[$method] = $args;
return $this;
}
public function __isset($name) {
// Checks if method is in stack
return isset($this->_stack[$name];
}
public function exec() {
// setSession is executed first
if (isset($this->setSession))
call_user_func_array('setSessionMethod', $this->_stack['setSession']);
// redirect is executed second
if (isset($this->redirect))
call_user_func_array('redirectMethod', $this->_stack['redirect']);
}
}
To use this class, you would do:
$stack = new Stack;
$stack->redirect('arg')
->setSession('arg1', 'arg2')
->exec();
How do I get the path to a script that is calling a method of a class defined in another script, from within the class?
That is, I'd like to make a call to a class method - defined in b.php - from a.php as:
PHP code
# a.php
require 'b.php';
$obj = new AsyncDecorator('ClassName');
$obj->Call('methodName');
... with, as previously mentioned, the class being defined in b.php similarly to this snippet:
PHP code
# b.php
class AsyncDecorator
{
public function Call($method)
{
# Currently equals to b.php - I need it to be 'a.php'
$require = __FILE__;
}
}
That is, I need to know that the calling script was a.php, and I need to do it dynamically. If I'm creating and using the AsyncDecorator class in c.php, then $require should equal to 'c.php'.
A possible solution to this problem is making either the Call() method, or the initialization of the decorator to accept a $file_path parameter in which __FILE__ is passed:
PHP code
$obj = new AsyncDecorator('ClassName', __FILE__);
$obj->Call('methodName');
This has the minor downside of requiring the file path to be passed each time this object is created, which might add unnecessary parameters and not keep its use as simple and seamless as possible.
There is a gist here with a function to get the calling class.
Hi I want to execute a function via cronjob to start an csv import. At the moment the import is triggered by accessing a controller in the browser tld.de/Update
The controller has this code http://pastie.org/8351266
How can I execute the function init() via Cronjob?
Thx!
In SilverStripe you can access any route that is accessible via HTTP also by running cli-script.php in the command line
There also is sake which is just a bash wrapper around cli-script.php (but sake needs to be installed)
so, from your project directory, you can run both commands which will perform the same action (in this case, run a dev/build):
php framework/cli-script.php dev/build
sake dev/build
see the docs for commandline ussage of silverstripe: http://doc.silverstripe.org/framework/en/topics/commandline
the 2nd part of your question (how to call a method from a controller) is actually more a question of routing in silverstripe and has nothing to do with how it is called (cronjob)
I assume that your controller is a Page_Controller or a subclass of that (so bound to a SiteTree Model), then routing is done for you (it takes the URLs you set in the CMS).
so lets see some example code and lets assume you have a page with the URLSegment about:
class Page_Controller extends ContentController {
private static $allowed_actions = array('something');
public function init() {
// the init method will run before every action
// this means this code will run, no matter if you visit /about or /about/something
}
public function index() {
// this is the default action (this code is optional and can be removed),
// and will be called if you visit website.com/about
return $this;
}
public function something() {
// this is the somethingaction,
// and will be called if you visit website.com/about/something
// do something here
return $this;
}
}
you can then call run to get the result of the index():
php framework/cli-script.php about
and this to get the result of something():
php framework/cli-script.php about/something
NOTE: the init method itself is not accessable via URL, it is the "setup" that runs before an action
NOTE: all actions other than index() have to be allowed by adding them to $allowed_actions (also note that you need to ?flush=1 after adding to $allowed_actions to reload the config cache)
EDIT: this was actually the response to your first question, after seeing your code example, this addition:
for standalone controllers it works the same way, just that you have to define the routes, and make sure that you have $Action in the route so that something() can be called
You could do this without Silverstripe sake. Install curl and call the URL via a cronjob, ie:
0 0 * * * curl --silent http://tld.de/Update
The proper way to do this would be to write a Silverstripe task, and invoke your controller from within the task. I haven't tested this code but it would go something like this:
class YourTask extends BuildTask {
public $description = "...";
//...
public function run($request) {
YourController::init();
}
}
You can invoke it over sake using:
0 0 * * * /path/to/framework/sake dev/tasks/YourTask
why not create a build task ? which is specially designed for such requirements (at-least that's how I consider build tasks)
<?php
class ArticleCsvUpdateTask extends BuildTask {
protected $title = 'Article Csv Update';
protected $description = 'Build task for article Csv update';
public function run($request) {
$loader = new ArticleCsvBulkLoader('Color');
if($loader->load('import-new.csv')) {
$loader->load('import-new.csv');
}
}
}
Which can be assess both from browser using "yoursite/dev/tasks/ArticleCsvUpdateTask" and from command line using "php framework/cli-script.php dev/tasks/ArticleCsvUpdateTask" OR using "sake dev/tasks/ArticleCsvUpdateTask" (if you have sake installed).
May be I am not getting your exact requirement but I believe this is much cleaner and nicer way of running a cron job with silverstripe.
See Zauberfisch's answer for a complete solution
I'm not familiar with Silverstripe, but if I understand correctly, this controller init function can be called with a HTTP request.
As the silverstripe docs say, you can call any url from the command line:
php framework/cli-script.php Update/init
More information is available here, and consider using sake for this task.
I think the right way do this is create a php file console like:
#!/usr/bin/env php
<?php
require_once "/path/to/your/class/Update.php";
$class = new Update();
$class->init();
Add right perms to this file
chmod 755 consolefile
And finally run this script with cronjob
I'm having trouble with accessing the session in an external .php script located in webroot.
Thought I'd write a function getSession() in one of my controllers and try to call it in the .php file.
So in steps:
I have file.php
In a controller I have a function getSession().
How to call the controllers function in the file.php?
Thank you.
EDIT
Meanwhile I fixed my bug, but still am curious how this is done and want other stack users to find a good answer to this so:
Its exactly like this:
In UsersController I have a function:
public function getSession() {
return $_SESSION['Auth']['User']['user_id'];
}
That I want to let's say print (for example) like this: print_r(Users.getSession) in the file test.php located in webroot/uploadify/test.php.
This file is not a class, but if it is required, then it shall be :)
#CaboOne: Maybe your answer was correct, I just wasnt sure what code to call (and enter) where :)
Supposed I have the following php file in webroot folder:
<?php
class TestingClass {
function getName(){
return "Test";
}
}
?>
I would do the following:
// This would bring you to your /webroot folder
include $_SERVER['DOCUMENT_ROOT'].'/another_file.php';
// Initializing the class
$example = new TestingClass;
// Call a function from the initialized class
$a_value = $example->getName();
// If you want to use $a_value in the view, you can then set
$this->set('a_value', $a_value);
Are functions inside of models directly accessible by users?
Can a user pass arguments directly to a function in a model? Or, do arguments have to be passed through php?
In otherwords:
I have a model called notifications and in there a function called get_notifs($user)... I use the controller to call the function like the get_notifs($_SESSION['user_id']) (which is encrypted). I don't want someone to be able to call get_notifs() with anything but their $_session as a argument. What is the best solution?
Am I already okay?
Should I rename get_notifs() to
_get_notifs()?
Should I check the
$_SESSION['user_id'] in the method
itself?
Or, is there another better solution
than any of these?
I have a controller: ajax.php which loads the model notification
function __construct()
{
parent::__construct();
$this->load->helper('url');
$this->load->library('tank_auth');
$this->load->model('notification');
$this->load->model('search');
}
function get_notifs()
{
$me = $this->session->userdata('user_id');
if ($e = $this->notification->get_notif($me))
{
...........
}
else{
echo "nothing was found wtf?";
}
.........................................................
model: notification.php
function get_notifs($user){
......
}
Your code is perfectly fine!
Am I already okay?
I Think so
Should I rename get_notifs() to _get_notifs()?
No, it's a public method so no need to make it look private.
Should I check the $_SESSION['user_id'] in the method itself?
No, this is the controller's job
Or, is there another better solution than any of these?
You only need a solution to a problem, and i don't see a problem here
it sounds liek your application may be used by people other then yourself, i.e the public developers, why would you want enforce developers to code things your way, that's going to make them upset at your application.
CI Only routes requests to a controller, the user cannot access a model or library or any other class, the route goes like so: /controller/method/param
the first segment will only ever load a controller file, the second will call the method in the param, passing any other variables such as param to that method.
Source: http://codeigniter.com/user_guide/overview/appflow.html
As you can see from the flow chart above, only the controller has access to the model's
If you'll only use it while in a session the best way would be this:
function get_notifs(){
if(!isset($_SESSION['user_id'])){
return false;
}
$user = $_SESSION['user_id'];
/* Your code here */
}
There's no point of requiring an argument when you'll only use the function with one specific variable which is also available globaly.
Edit: I don't know why you're using functions in your models. Doesn't make any sense, do you mean methods?