PHP how to pass a variable inside a class - php

I have tried the solutions indicated here on stackoverflow, the code below uses one of them, recommended and voted as the right way to do it, but it doesn't work for me, why?
In fact the href results empty.
<?php
//URLS LIST
$nameA = 'http://www.example.com';
$nameB = 'http://www.example.com';
$nameC = 'http://www.example.com';
class bannClass {
private $class_varA;
private $class_varB;
private $class_varC;
public $username = '';
public function __construct($nameA, $nameB, $nameC) {
$this->class_varA = $nameA;
$this->class_varB = $nameB;
$this->class_varC = $nameC;
}
public function check_userOne() {
$url = 'https://example.com/wp-content/uploads/sponsor/' . $this->username . '/sponsor1.jpg';
return '<img src="' . $url . '" alt="Sponsor"/>';
}
public function check_userTwo() {
$url = 'https://example.com/wp-content/uploads/sponsor/' . $this->username . '/sponsor2.jpg';
return '<img src="' . $url . '" alt="Sponsor"/>';
}
public function check_userThree() {
$url = 'https://example.com/wp-content/uploads/sponsor/' . $this->username . '/sponsor3.jpg';
return '<img src="' . $url . '" alt="Sponsor"/>';
}
}
Also how can i make those 3 variables at the top dynamic in php? instead of "name" something like $($this->username . 'A') , $($this->username . 'B') , etc.
EDIT: the above class is being instantiated in another php file like so:
<?php
require_once('myclass.php');
$bannClass = new bannClass();
$bannClass->username = $data['username'];
//etc.
and used like:
<?php echo $bannClass->check_userOne();?>

As it is written, you must inject 3 values when it is instantiated. If you have error reporting turned on in your development environment (and you really should), it would have complained when you instantiated it as $bannClass = new bannClass();
This is how this object should be instantiated:
$nameA = 'http://www.example.com';
$nameB = 'http://www.example.com';
$nameC = 'http://www.example.com';
$bannClass = new bannClass($nameA, $nameB, $nameC);
I would make a few suggestions:
Don’t mix logic and presentation. A good rule of thumb to follow is no html outside of the view. Objects are generally for logic, not formatting html. Leave html for helper functions and the “view” portion of the script (which should be the very last thing that happens)
Keep it DRY (don’t repeat yourself). If you have methods doing the same thing, it’s time to refactor. Pass in a variable or an array for the method to work with.
—-
Further ideas relating to your comment:
The collection of the urls would typically be the job of an object. (Look into the PDO object. Helpful reference )
In all my projects, I use an object (named Database) to wrap around php’s db access, similar to pdo. It includes the following 3 methods (code is omitted for brevity):
public function prepare(string $query) { ... }
public function execute(array $params) { ... }
public function nextRecord() {...}
In a procedural script, you would first do whatever initialization is needed, deal with any user input using the PRG pattern, and any other logic. Then you would output the html, using php only to loop and insert variables. In OOP terms, this roughly corresponds to the MVC pattern (which is well worth learning).
So, for the example, let’s say that we have a database of urls:
ID URL Image
1 foo.com Image1.com
2 bar.com Image2.com
3 baz.com Image3.com
A procedural script could go as follows:
<?php
require(‘database.php’);
// optionally deal with user input
$url = new Database; // example is assuming connection is handled in the object
$url->prepare(“select url, image from sometable”);
$url->execute();
// all logic is complete; now give the output
?>
<!— html stuff —>
<ul>
<?php while($row=$url->nextRecord() ): ?>
<li><img src="<?= $row->image ?>" alt="Sponsor"/></li>
<?php endwhile; ?>
</ul>
Admittedly, I haven’t explained my object; space does not permit. But this should give you an overview of what’s possible and how to display 150 urls without repeating yourself.

Just to add to excellent answer by Tim Morton: Let's suppose, that the three links are almost always the same, then you can do something like this:
class bannClass {
private $class_varA = 'https://example.com';
private $class_varB = 'https://example.com';
private $class_varC = 'https://example.com';
public $username = '';
public function __construct($nameA = null, $nameB = null, $nameC = null) {
if (!empty($nameA)) $this->class_varA = $nameA;
if (!empty($nameB)) $this->class_varB = $nameB;
if (!empty($nameC)) $this->class_varC = $nameC;
}
public function getVarA(){
return $this->class_varA;
}
public function getVarB(){
return $this->class_varB;
}
public function getVarC(){
return $this->class_varC;
}
}
What above does, that if the class is not called with any parameters = $foo = new bannClass(); it will default all three URLs to what was set as default. Obviously, you should arrange the variables in such manner, that first is possibly changed the most time:
$bar = new bannClass('https://stackoverflow.com');
echo $bar->getVarA(); // returns stackoverflow.com
echo $bar->getVarC(); // returns example.com
Because changing only third parameter looks kinda stupid:
$baz = new bannClass(null,null,'https://stackoverflow.com');
cho $baz->getVarA(); // returns example.com
echo $baz->getVarC(); // returns stackoverflow.com

Related

How does a php program decide what function is called first when I go to a php page?

I am trying to understand how a php application that is called with a POST to this URL works:
transliterator/romaji
The romaji.php looks like this:
<?php
namespace JpnForPhp\Transliterator;
class Romaji extends TransliterationSystem
{
private $latinCharacters = array();
public function __construct($system = '')
{
$file = __DIR__ . DIRECTORY_SEPARATOR . 'Romaji' . DIRECTORY_SEPARATOR . (($system) ? $system : 'hepburn') . '.yaml';
parent::__construct($file);
}
public function __toString()
{
return $this->configuration['name']['english'] . ' (' . $this->configuration['name']['japanese'] . ')';
}
TransliterationSystem looks like this:
<?php
namespace JpnForPhp\Transliterator;
use Symfony\Component\Yaml\Yaml;
abstract class TransliterationSystem
{
public $configuration = array();
public function __construct($file)
{
$this->configuration = Yaml::parse(file_get_contents($file));
}
public function transliterate($str)
{
$str = $this->preTransliterate($str);
foreach ($this->configuration['workflow'] as $work) {
if (!method_exists($this, $work['function'])) {
continue;
}
$params = array($str);
if (isset($work['parameters'])) {
$params[] = $work['parameters'];
}
$str = call_user_func_array(array($this, $work['function']), $params);
}
$str = $this->postTransliterate($str);
return $str;
}
Can someone explain to me the sequence of events for when I POST to romaji.php? Below is a link to the github if there is something that I should have included but didn't.
For reference here's the link to github
Normally a PHP file is read (and evaluated) from top to bottom. As pointed out in a comment above, these are just class declarations - there's no code there to actually instantiate the classes or do anything with them, so there's really nothing happening here as such.
For something to happen, there would need to be some code to make use of these classes, for example:
$r = new Romaji();
// Do something with $r ....
EDIT:
I just had a look at the GitHub link, and apparently this is a library; so you'll call it from your own code - it won't do anything by itself.
I'm the one who wrote this library :)
JpnForPhp exposes various helper and functions, that's why you don't see any instanciation like = new Romaji() ; the transliterator component doesn't call himself :)
If you want to see some sample to understand how to use it, please check the test files or the demo website source code
Hope this help.

using one public function inside another public function

The title may not make sense, not sure how to word it. Anyways, i'm practicing curl and OOP at the same time here with the riot games API. the API is kind of set up dumb where some info you want to request requires input that you wouldn't know off hand, so it requires another separate call to get the required info first.
class league
{
const URL = 'http://prod.api.pvp.net/api/lol/na/v1.1/';
const URL_2 = 'http://prod.api.pvp.net/api/lol/na/v2.1/';
const KEY = 'key';
public function summonerByName($summoner_name)
{
$request = 'summoner/by-name/' . $summoner_name . '?api_key =' . self::KEY;
return $this->fetch($request);
}
public function recentGamesByName($summoner_name)
{
//need to make two calls for this since you cant get recent games by name in the api
$id = summonerByName($summoner_name);
//now get recent games
$request = 'game/by-summoner/' . $id->id . '/recent';
return $this->fetch($request);
}
private function fetch($request)
{
$url = self::URL . $request . '?api_key=' . self::KEY;
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$data = curl_exec($curl);
curl_close($curl);
return json_decode($data);
}
}
this is returning Fatal error: Call to undefined function summonerbyname()
if i use all this extra code below in the public function recentGamesByName() instead of $id = summonerByName() it works fine, but it seems unnecessary, and i want to replace that with just the function.
$grg = self::URL . 'summoner/by-name/' . $summoner_name . '?api_key=' . self::KEY;
$placeholder = curl_init($grg);
curl_setopt($placeholder, CURLOPT_RETURNTRANSFER, 1);
$ph_result = curl_exec($placeholder);
curl_close($placeholder);
$ph_result = json_decode($ph_result);
$id = $this->summonerByName($summoner_name);
You may want to read up on OOP.
A couple of things to remember about OOP. When you're INSIDE the class and need to call another function, you use the the special $this variable.
So you would use:
$someVariable = $this->summonerByName($summoner_name);
to get the results from that function.
If you're OUTSIDE the class and need to access that function, then you need to assign the entire class to a variable like so:
$league = new league();
and then you can access any function within the class using that variable.
So you could do...
$someVariable = $league->summonerByName($summoner_name);
if you had already assigned the class to a variable name $league. By the way, that $league variable? It's called an object. Thus Object Oriented Programming. Objects are kinda like arrays, but use a different syntax. You can print_r an object just like you can print_r an array. When accessing an object's variable you use the $objectName->variableName syntax instead of $arrayName['variablename'] syntax that you use in arrays.

how to build a good router for php mvc

I'm experimenting with php mvc and I'm stucked with the following issue. My request and router classes are really simple and I would like to extend theme to can handle controller calls from sub folders and to controller classes functions should be able to pick up url variables send it threw get and post.
my router looks as it follows
class Router{
public static function route(Request $request){
$controller = $request->getController().'Controller';
$method = $request->getMethod();
$args = $request->getArgs();
$controllerFile = __SITE_PATH.'/controllers/'.$controller.'.php';
if(is_readable($controllerFile)){
require_once $controllerFile;
$controller = new $controller;
if(!empty($args)){
call_user_func_array(array($controller,$method),$args);
}else{
call_user_func(array($controller,$method));
}
return;
}
throw new Exception('404 - '.$request->getController().'--Controller not found');
}
}
and Request class
private $_controller;
private $_method;
private $_args;
public function __construct(){
$parts = explode('/',$_SERVER['REQUEST_URI']);
$this->_controller = ($c = array_shift($parts))? $c: 'index';
$this->_method = ($c = array_shift($parts))? $c: 'index';
$this->_args = (isset($parts[0])) ? $parts : array();
}
public function getController(){
return $this->_controller;
}
public function getMethod(){
return $this->_method;
}
public function getArgs(){
return $this->_args;
}
}
The problem is:when I try to send threw ajax, variables to a controller method this are not recognized because of its url structure.
For example
index/ajax?mod_title=shop+marks&domain=example
is accepted just if it look
index/ajax/shop+mark/example
Your code contains what is known as an LFI vulnerability and is dangerous in its current state.
You should whitelist your what can be used as your $controller, as otherwise an attacker could try to specify something using NUL bytes and possibly going up a directory to include files that SHOULD NOT be ever included, such as /etc/passwd, a config file, whatever.
Your router is not safe for use; beware!
edit: example on whitelisting
$safe = array(
'ajax',
'somecontroller',
'foo',
'bar',
);
if(!in_array($this->_controller, $safe))
{
throw new Exception(); // replace me with your own error 404 stuff
}
Since your Request class uses a URI segments approach for identifying controller, action and arguments, global variables such as $_GET or $_REQUEST are not taken into account from within your Request.
What you need to do is to make some additions to your Request code. Specifically:
Remove the line:
$this->_args = (isset($parts[0])) ? $parts : array();
And add the following:
$all_parts = (isset($parts[0])) ? $parts : array();
$all_parts['get'] = $_GET;
$this->_args = $all_parts;
This way, $_GET (ie variables passed via the url) variables will be available in the actions called, as they will be in $args (they will be available as $args['get'] actually, which is the array that holds the $_GET vars, so you will be able to have access to domain=example by using $args['get']['domain']).
Ofcourse, you can add one more method in your Request class (e.g. query) that might look like that:
public function query($var = null)
{
if ($var === null)
{
return $_GET;
}
if ( ! isset($_GET[$var]) )
{
return FALSE;
}
return $_GET[$var];
}
This way, you can get a single variable from the url (e.g. $request->query('domain')) or the whole $_GET array ($request->query()).
That's because php will put "?mod_title=..." in the $_GET array automatically. Your getArgs() function should check for $_GET, $_POST or $_REQUEST.
If you're trying for a minimal MVC approach, have a look at rasmus' example: http://toys.lerdorf.com/archives/38-The-no-framework-PHP-MVC-framework.html
If your use case is going to get more complex, have a look at how Zend (http://framework.zend.com/manual/en/zend.controller.html) or Symfony (https://github.com/symfony/symfony/tree/master/src/Symfony/Component/Routing) do their stuff.
Choose any popular MVC to see how they implement it under the hood. In addition, spl_autoload_register and namespace are your friends.

Issue with assigning class variable in PHP

I am trying to assign a variable to a class in PHP, however I am not getting any results?
Can anyone offer any assistance? The code is provided below. I am trying to echo the URL as shown below, by first assigning it to a class variable.
class PageClass {
var $absolute_path = NULL;
function get_absolute_path(){
$url = $this->absolute_path;
echo $url;
}
}
$page = new PageClass();
$page->absolute_path = "http://localhost:8888/smile2/organic/";
$page->get_absolute_path(); //this should echo the URL as defined above - but does not
It also works for me.
Take a look at a live example of your code here.
However, there are a few things you should change about your class.
First, Garvey does make a good point that you should not be using var. That's the older PHP4, less OOP conscious version. Rather declare each variable public or private. In fact, you should declare each function public or private too.
Generally, most classes have private variables, since you usually only want to change the variables in specific ways. To achieve this control you usually set several public methods to allow client functions to interact with your class only in restricted predetermined ways.
If you have a getter, you'd probably want a setter, since these are usually used with private variables, like I described above.
A final note is that functions named get usually return a value. If you want to display a value, it is customary to use a name like display_path or show_path:
<?php
class PageClass
{
private $absolute_path = NULL;
public function set_absolute_path($path)
{
$this->absolute_path = $path;
}
public function display_absolute_path()
{
echo $this->absolute_path;
}
}
$page = new PageClass();
$page->set_absolute_path("http://localhost:8888/smile2/organic/");
$page->display_absolute_path();
// The above outputs: http://localhost:8888/smile2/organic/
// Your variable is now safe from meddling.
// This:
// echo $this->absolute_path;
// Will not work. It will create an error like:
// Fatal error: Cannot access private property PageClass::$absolute_path on ...
?>
Live Example Here
There's a section on classes and objects in the online PHP reference.
class PageClass {
public $absolute_path = NULL;
function get_absolute_path(){
$url = $this->absolute_path;
return $url;
}
}
$page = new PageClass();
$page->absolute_path = "http://localhost:8888/smile2/organic/";
echo $page->get_absolute_path();
Works fine for me.
Have you checked that the script and esp. the code in question is executed at all?
E.g. add some unconditional debug-output to the script. Or install a debugger like XDebug to step through the code and inspect variables.
<?php
class PageClass {
var $absolute_path = NULL; // old php4 declaration, see http://docs.php.net/oop5
function get_absolute_path() { // again old php4 declaration
$url = $this->absolute_path;
echo "debug: "; var_dump($url);
echo $url;
}
}
$page = new PageClass();
$page->absolute_path = "http://localhost:8888/smile2/organic/";
echo "debug: page->get_absolute_path\n";
$page->get_absolute_path();

Is there a Symfony helper for getting the current action URL and changing one or more of the query parameters?

What I'd like to do is take the route for the current action along with any and all of the route and query string parameters, and change a single query string parameter to something else. If the parameter is set in the current request, I'd like it replaced. If not, I'd like it added. Is there a helper for something like this, or do I need to write my own?
Thanks!
[edit:] Man, I was unclear on what I actually want to do. I want to generate the URL for "this page", but change one of the variables. Imagine the page I'm on is a search results page that says "no results, but try one of these", followed by a bunch of links. The links would contain all the search parameters, except the one I would change per-link.
Edit:
Ok I got a better idea now what you want. I don't know whether it is the best way but you could try this (in the view):
url_for('foo',
array_merge($sf_request->getParameterHolder()->getAll(),
array('bar' => 'barz'))
)
If you use this very often I suggest to create your own helper that works like a wrapper for url_for.
Or if you only want a subset of the request parameters, do this:
url_for('foo',
array_merge($sf_request->extractParameters(array('parameter1', 'parameter3')),
array('bar' => 'barz'))
)
(I formated the code this way for better readability)
Original Answer:
I don't know where you want to change a parameter (in the controller?), but if you have access to the current sfRequest object, this should do it:
$request->setParameter('key', 'value')
You can obtain the request object by either defining your action this way:
public function executeIndex($request) {
// ...
}
or this
public function executeIndex() {
$request = $this->getRequest();
}
For symfony 1.4 I used:
$current_uri = sfContext::getInstance()->getRouting()->getCurrentInternalUri();
$uri_params = $sf_request->getParameterHolder()->getAll();
$url = url_for($current_uri.'?'.http_build_query(array_merge($uri_params, array('page' => $page))));
echo link_to($page, $url);
Felix's suggestion is good, however, it'd require you to hard core the "current route"..
You can get the name of the current route by using:
sfRouting::getInstance()->getCurrentRouteName()
and you can plug that directly in url_for, like so:
url_for(sfRouting::getInstance()->getCurrentRouteName(),
array_merge($sf_request->extractParameters(array('parameter1', 'parameter3')),
array('bar' => 'barz'))
)
Hope that helps.
With the same concept than Erq, and thanks to his code, I have made the same with some small changes, since my URL needs to convert some characters. Its generic though and should work with most forms, in order to save the parameters the user has chosen to search for.
public function executeSaveFormQuery(sfWebRequest $request)
{
$sURLServer = "http://";
$sURLInternalUri = "";
$page = "";
$sURLInternalUri = sfContext::getInstance()->getRouting()->getCurrentInternalUri();
$suri_params = $request->getParameterHolder()->getAll();
$sParams = http_build_query(array_merge($suri_params));
$dpos = strpos($sURLInternalUri, "?");
$sURLConsulta[$dpos] = '/';
$sURL = substr($sURLInternalUri, $dpos);
$dpos = strpos($sURL, "=");
$sURL[$dpos] = '/';
$sURLFinal = $sURLServer . $sURL . '?' . $sParams;
//$this->redirect($this->module_name . '/new');
self::executeNew($request, $sURLFinal);
//echo "var_dump(sURLFinal): ";
//var_dump($sURLFinal);
//echo "<br></br>";
//return sfView::NONE;
}
In executeNew, as easy as:
public function executeNew(sfWebRequest $request, $sURLQuery)
{
//$sURLQuery= "http://";
if ($sURLQuery!= "")
{
$this->form = new sfGuardQueryForm();
//echo "var_dump(sURLQuery)";
//var_dump($sURLQuery);
//echo "<br></br>";
$this->form->setDefault('surl', $sURLQuery);
}
else
{
$this->form = new sfGuardQueryForm();
}
}
echo $sf_context->getRequest()->getUri();

Categories