I'm just taking my OOP lessons and I've found on a practice that I did not understand the theory as I thought... basically for practicing I tried to create a class which contains all the scripts I need to use on a single page, and I went as follows:
class pageScripts {
protected $scripts = array(); //an array to storage the links to the scripts
public function setScripts($link) {
$this->scripts[] = $link; //filling the array with the links
}
public function __toString() {
$output = '';
foreach($this->scripts as $values) {
$output .= "<script src=" . $values . "></script>";
}
return $output;
}
}
$scripts = new pageScripts;
$scripts->setScripts('link to the script');
$scripts->setScripts('link to the script2');
//var_dump ($scripts);
print($scripts);
Now, in my dreams, it supposed to concatenate the links and make a cute script list, however it doesn't, also I made a var_dump() and the array is filled, I cannot understand what I am doing wrong.
Any ideas?
The output & the code are fine (works for me), but by default PHP renders output with content type text/html, which "hides" the <script> tag.
To reveal the <script> tag, you can either set the content type to text/plain (which does not make sense), or review it in source code.
Related
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
I would like to create a multiple language website but I have a problem!
I will explain it to you with an example:
lang-en.php
<?php
$lang = [];
$lang['hello'] = "Wellcome $userName to our website!";
?>
index.php
<?php
$useName = "Amir";
require_once("lang-en.php");
echo $lang['hello'];
?>
Now, I would like to see this output in my page:
Welcome Amir to our website!
How can i do this?
It might be smart to make it a bit more complicated, to look to the future. If you remove the implementation part to a separate class, you can have your actual usage and the implementation of the translation separate. If you plan to use gettext (po/mo files) later, you can switch easier.
A simple, but untested, example would be
class translate{
private $translations = [
'hello' => "Wellcome %s to our website!",
]
public function trans($key, $value)
{
return sprintf($this->translations[$key], $value);
}
}
Mind you, this is a quick example, and probably needs some work -> for instance, it presumes always a single variable, etc etc. But the idea is that you create class with an internal implementation, and a function that you call. If you can keep the function call's footprint the same, you can change the working of your translation system!
You'll call this like so
$trans = new Translate();
echo $trans->trans('hello', 'Amir');
(again, I typed this in the answer box, no check for syntax, testing etc has been done, so this is probably not a copy-paste ready class, but it is about the idea)
edit: as requested, a bit more example. Again, not tested, probably some syntax errors etc, but to help you with the idea:
class translate{
private $translations = [
'hello' => array('test' =>"Welcome %s to our website!", 'vars' => 1),
'greet' => array('test' =>"I'd like to say $s to %s ", 'vars' => 2),
]
public function trans($key, array $values)
{
// no translation
if(!isset($this->translations[$key])){
return false; // or exception if you want
}
// translation needs more (or less) variables
if($this->translations[$key][vars] !== count($values)){
return false; // or exception if you want
}
// note: now using vsprintf
return vsprintf($this->translations[$key], $values);
}
}
Make a function one in lang-en.php
<?php
function lang($username)
{
$lang['hello'] = $username;
echo $lang['hello'];
}
?>
In index.php call that function
<?php
require_once("lang-en.php");
lang('arun');
?>
you nearly had it
langen.php
<?php
//declare array
$lang = array();
$templang['hello1'] = "Wellcome ";
$templang['hello2'] = " to our website!";
//add new item in array
array_push($lang,$templang);
?>
index.php
<?php
$useName = "Amir";
require_once("langen.php");
//it is first entry of array row so [0] is 0
echo $lang[0]['hello1'];
echo $userName;
echo $lang[0]['hello2'];
//out is welcome amir to our website
?>
this is a easy way too see how to pass variables a little long way but i didn't want to combine so that you can see how it works you can also do some reading about sessions for passing variables between pages that is not included
Amir Agha,
When you call another .php file by include or require php acts as if the contents of the included file is inserted in the same line and the same scope (except for classes and functions) so your code in the view of php interpreter looks like this:
<?php
$userName = "Amir";
$lang = [];
$lang['hello'] = "Wellcome $userName to our website!";
echo $lang['hello'];
?>
So this code must display:
Wellcome Amir to our website!
But why it doesn't work? Simply because you wrote $useName instead of $userName in your index.php file.
p.s.: Other answers made it very complicated. only change $useName to $userName
I was wandering if it were possible to store a html schema page with special strings to replace with variable and how to do it.
In an external file, I would like to put the html structure of a product, let's call it schema.php:
<span id="{% id %}">{%= name %}</span>
<span>{%= imageURL() %}</span>
The example above is just a simpler example. In the external file, the html would be more complex. I know that if there were just few lines I could just echo them with a simple function but this is not the case.
In another file I have a class that handle products, let's call it class.php:
class Product {
//logic that is useless to post here.
public function imageURL() {
return "/some/url".$this->id."jpg";
}
}
In this class I would like to add a function that take the content from schema.php and then echo it in the public file for users.
I tried with file_get_contents() and file_put_contents() but it just doesn't work:
$path_to_file = 'data/prodotti/scheda.inc';
$file_contents = file_get_contents($path_to_file);
$file_contents = str_replace(
"{%= ",
"<?php echo $this->",
$file_contents
);
$file_contents = str_replace(
" }",
"; ?>",
$file_contents
);
file_put_contents($path_to_file, $file_contents);
is it possible to call schema.php page and print it with custom variables?
By "schema page" I think you mean "template" and yes, but the best way to do it is to use an existing templating engine such as Smarty or a Mustache implementation like https://github.com/bobthecow/mustache.php instead of implementing it yourself because of the risks of XSS, HTML-injection, and how you'll eventually want features like looping and conditionals.
you can do it normaly with php require func. without any strings to replace, if you just want to use that file as "template" then:
in schema.php:
<?php
echo'<span id="'.$id.'">'.$name.'</span>
<span>'.$imageURL.'</span>';
?>
in class.php:
<?php
class Product {
//logic that is useless to post here.
public function imageURL() {
return "/some/url".$this->id."jpg";
}
}
$imageURL = imageURL(); ?>
Index.php or whatever the main page that handles class.php and temp.php(schema)
<?php
//avoid undefined variables on errors
//in case that you don't check for values submitted
$id = 0;
$name = 0;
$imageURL = '';
//set vars values
$id = /*something*/;
$name = /*something 2*/;
$imageURL = /*something3*/;
//all date will be replaced is ready, oky nothing to wait for
require('path/to/schema.php');
Note: If you gets these data from user, then you should validate with if(isset()).
hope that helps,
I have a project where people can book places on events. There are dozens of events. I have been requested to generate a report listing attendees so they can be checked in at the door. Because there are so many events, I would like to add an "Attendees Report" button to the editform for each event (inside the CMS). I have created the button, and it works.
BUT... instead of getting the data in a CSV, I get the (correct) data displaying in the CMS, as if it was being echoed.
Here is my function
public function getCustomersForEvent($data, $form){
$attendees = CustomerOrderLine::get()->filter(array("EventID" => $data["ID"]));
if(!$attendees){
return false;
}
$fileName = "report.csv";
$separator = ",";
$csvColumns = array("ID", "Description", "Customer");
$fileData = "";
foreach($attendees as $row){
$fileData .= $row->Event()->EventName . $separator;
$fileData .= $row->CustomerOrder()->Customer()->FirstName . " " . $row->CustomerOrder()->Customer()->Surname . "\n";
}
return SS_HTTPRequest::send_file($fileData, $fileName, 'text/csv');
}
I have had a look at this http://www.silverstripe.org/community/forums/general-questions/show/15325 but the data echoed to the CMS anyway.
Can someone please tell me what I am doing wrong? As I said, the data is fine, but I'm not getting the CSV Open or Save dialog.
The solution will be in how you are calling this. I would advise that you make a complete new controller or modify a module like...
https://github.com/axyr/silverstripe-phpexcel
...where you can copy the php code and modify it to return just the data you require from above.
To make a controller that is only focused on downloading a file...
class CustomersForEvent_Controller extends Page_Controller {
private static $allowed_actions = array (
'downloadcsv',
);
public function downloadcsv() {
return SS_HTTPRequest::send_file("my content",'myfile.csv','text/csv');
}
}
and add that controller to the routes in _config/config.yml...
Director:
rules:
'attendees': 'CustomersForEvent_Controller'
...and then you can just link to yousite.com/attendees/downloadcsv
This has been tested locally and confirmed to work
Is this report to be generated from within the CMS itself? If so, do you have a ModelAdmin for managing CustomerOrderLine objects? If so, can you not use the GridField's "Export to CSV" button?
In order to output anything more than just those fields displayed by the GridField itself, you'll need to create/alter your model class's $getExportFields() method to return an array of all the fields on your model you wish to be exported in this manner.
I'm scraping data on cryptographers for a research project I'm doing for school. I have a really simple class that goes to a webpage, enters each of that page's href links, and writes them to a file.
I'm not actually getting a specific error when I run the code, but right now it just writes a blank file. My issue seems to be that my getters and setters have no knowledge of my private instance variables, and furthermore, my object ($obj) seems to have no knowledge of my getters and setters so I'm a bit confused.
I'm using JetBrains PHPStorm. Thanks to everyone for the help and support
Edit: I've updated the code below and it will run just fine. For anyone interested in using it - this code will scrape all of the links off of a web page and store the contents of each link inside of a file. I'm probably going to end up modifying this to strip out all html so that I only get raw text and then JSON-encode the output so that it can be easily parsed.
<?php
class Scraper
{
/*
=============================================
SET UP THE BASE DIRECTORY FOR SCRAPING,
AND OPEN FILES TO WRITE INFORMATION TO
==============================================
*/
private $basedir; //BASE DIRECTORY PATH FOR SCRAPING
private $outfile; //NAME OF FILE TO WRITE TO
/*
=============================================
SETTER FOR BASE DIRECTORY
==============================================
*/
public function setBaseDirectory($base)
{
$this->basedir = $base;
}
/*
=============================================
SETTER FOR OUTFILE
==============================================
*/
public function setOutfile($file)
{
$this->outfile = $file;
}
/*
=============================================
GETTER FOR OUTFILE
==============================================
*/
public function getOutfile()
{
return $this->outfile;
}
/*
=============================================
GETTER FOR BASE DIRECTORY
==============================================
*/
public function getBaseDirectory()
{
return $this->basedir;
}
/*
=============================================
THIS FUNCTION TAKES THE HYPERLINKS OUT OF
A WEB PAGE AND RETURNS THEM IN AN ARRAY.
ITS SCOPE IS PRIVATE SINCE IT IS A HELPER
METHOD FOR GETDIRCONTENTS
=============================================
*/
private function grabLinks($contents)
{
$last_dir = array();
$URLs = array();
preg_match_all("|href=[\"'](.*?)[\"']|", $contents, $match);
foreach ($match as $key => $value)
foreach ($value as $key2 => $TheUrl)
$URLs[] = $TheUrl;
for ($i =0; $i < (count($URLs)/2);$i++)
{
$item = str_replace('href=','',(string)$URLs[$i]);
$item = str_replace('"','',$item);
array_push($last_dir, $item);
}
return $last_dir;
}
/*
=============================================
THE GOAL OF THIS FUNCTION IS TO GET THE
CONTENTS OF EACH FORUM POST AND WRITE THEM
INTO A FILE. MAY EXPLORE CREATING AN
ASSOCIATIVE ARRAY AND JSON_ENCODING THEM
BASED ON NAME = POST NAME VALUE = FILE CONTENTS
=============================================
*/
public function getDirContents($dir)
{
$contents = file_get_contents($dir);
$linksArray = $this->grabLinks($contents);
for ($i = 0; $i < count($linksArray);$i++)
{
$contents = strip_tags(file_get_contents($dir.$linksArray[$i])); //GET CONTENTS OF FILE FROM LINK
fwrite($this->getOutfile(), $contents);
$debug = fopen("debugLog.txt", "w");
fwrite($debug, "debug contents: \n\n".$this->getOutfile().$this->getBaseDirectory()." $contents \n\n");
}
}
}
/*
=============================================
CREATE NEW INSTANCE OF CLASS AND CALL FUNCTION
TO GET CONTENTS OF DIRECTORY ITEMS
==============================================
*/
$obj = new Scraper();
$obj->setBaseDirectory("http://satoshi.nakamotoinstitute.org/posts/");
$obj->setOutfile(fopen("Satoshi_Forum_Posts.txt", "w"));
$obj->getDirContents($obj->getBaseDirectory());
echo $obj->getBaseDirectory();
echo $obj->getOutfile();
Ok, I've been able to locate the source of the problem and I apologize for wasting the time of those individuals who were kind enough to comment above. It turns out that my PHP code was just fine and ran after I made 1 change.
I just started using JetBrains PHPStorm IDE, and loaded this class file into the editor from my desktop rather than the JetBrains' workspace. Once I incorporated the small syntactical changes mentioned by Bulk and Jonathan Kuhn I created a new project in JetBrains inside of the workspace I defined upon setting up the program and all of the warning messages went away (I still don't fully understand why they went away).
I ran my code and produced the desired result. I'll post the updated code in the question with the updates suggested in the comments so that anyone who needs a script like this can use it. Thanks again for everyone willing to help out!