PHP catching excepion from another class in a loop - php

I'm total PHP newbie, learning while creating following app. I got stuck trying to catch exception which breaks the loop in class Basic. Exception comes from class ProductVariation. Function generateRandomItems should generate random items on base of class Product and product.json file and skip productVariation when color is null.
<?php
class Product implements Item
{
public $id;
public $name;
public $price;
public $quantity;
public function __construct($file)
{
if (!file_exists($file)) {
throw new Exception('ProductFileNotFound');
}
$data = file_get_contents($file);
$product = json_decode($data);
$id = $product->id;
$name = $product->name;
$price = $product->price;
$quantity = $product->quantity;
$this->id = $id;
$this->name = $name;
$this->price = $price;
$this->quantity = $quantity;
}
public function getAmount()
{
$this->amount = $this->price * $this->quantity;
return $this->amount;
}
public function __toString()
{
$output = '';
foreach ($this as $key => $val) {
$output .= $key . ': ' . $val . "<br>";
}
return $output;
}
public function getId()
{
return $this->id;
}
public function getNet($vat = 0.23)
{
return round($this->price / (1 + $vat), 2);
}
}
class ProductVariation extends Product
{
public $color;
public function __construct($file, $color)
{
parent::__construct($file);
$this->color = $color;
if (!is_string($color)) {
throw new Exception('UndefinedVariantColor');
}
return $this->color;
}
}
interface Item
{
public function getId();
public function getNet($vat);
}
class Products extends ArrayIterator
{
public function __construct($file, $color)
{
$this->product = new Product($file);
$this->productVariation = new ProductVariation($file, $color);
}
}
class Basic
{
public function generateRandomString($randomLength)
{
$characters = 'abcdefghijklmnopqrstuvwxyz';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $randomLength; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
public function generateRandomItems($length)
{
$colors = array(
"red", "green", "blue",
"white", "black", null,
);
$list = [];
for ($i = 2; $i < $length + 2; $i += 2) {
$color = $colors[array_rand($colors, 1)];
$products = new Products('product.json', $color);
$products->product->id = $i - 1;
$products->product->name = $this->generateRandomString(rand(3, 15));
$products->product->price = rand(99, 10000) / 100;
$products->product->quantity = rand(0, 99);
$products->productVariation->id = $i;
$products->productVariation->name = $this->generateRandomString(rand(3, 15));
$products->productVariation->price = rand(99, 10000) / 100;
$products->productVariation->quantity = rand(0, 99);
echo $products->product;
echo $products->productVariation;
array_push($list, $products->product, $products->productVariation);
}
$uid = uniqid();
$fp = fopen("products/" . $uid . '.json', 'w');
fwrite($fp, json_encode($list));
fclose($fp);
}
}
product.json file content is {"id":1,"name":"Produkt testowy","price":13.99,"quantity":19}

For one, the check should precede the assignment to check if it’s null (this is in your Basic class).
// put check first
if (!is_string($color)) {
throw new Exception('UndefinedVariantColor');
}
$this->color = $color;

Related

Add element to listnode in PHP

If i have a listnode with the following defination
class ListNode {
public $val = 0;
public $next = null;
function __construct($val = 0, $next = null) {
$this->val = $val;
$this->next = $next;
}
}
How can i add an element to the end of the listnode and thus add int[i] elements by interation?
class ListNode {
public int $val = 0;
public ?ListNode $next = null;
function __construct(?int $val = 0, ?ListNode $next = null) {
$this->val = $val;
$this->next = $next;
}
function appendToListEnd(int $val) {
if ($this->next == null) {
$this->next = new ListNode($val);
} else {
$temp = $this->next;
while ($temp->next != null) {
$temp = $temp->next;
}
$temp->next = new ListNode($val);
}
}
}
$arr = [ 1, 2, 3, 4 ];
$listHead = new ListNode($arr[0]);
for ($i = 1; $i < count($arr); $i++) {
$listHead->appendToListEnd($arr[$i]);
}
print_r($listHead);
$listHead->appendToListEnd(5);
print_r($listHead);

Using another class from a thread

My threaded script doesn't see another class from within a thread. Here is my code.
require_once __DIR__.'\vendor\autoload.php';
use Symfony\Component\DomCrawler\Crawler;
$threadCount = 5;
$list = range(0,100);
$list = array_chunk($list, $threadCount);
foreach ($list as $line) {
$workers = [];
foreach (range(0,count($line)-1) as $i) {
$threadName = "Thread #".$i.": ";
$workers[$i] = new WorkerThreads($threadName,$line[$i]);
$workers[$i]->start();
}
foreach (range(0,count($line)-1) as $i) {
$workers[$i]->join();
}
}
class WorkerThreads extends Thread {
private $threadName;
private $num;
public function __construct($threadName,$num) {
$this->threadName = $threadName;
$this->num = $num;
}
public function run() {
if ($this->threadName && $this->num) {
$result = doThis($this->num);
printf('%sResult for number %s' . "\n", $this->threadName, $this->num);
}
}
}
function doThis($num){
$response = '<html><body><p class="message">Hello World!</p></body></html>';
$crawler = new Crawler($response);
$data = $crawler->filter('p')->text();
return $data;
}
When I run it, I get the following error message
Fatal error: Class 'Symfony\Component\SomeComponent\SomeClass' not found
How would I make my thread see another class?
With the help of #Federkun answer, which he deleted, I found the following thread discussing the issue
Here is a working solution
$autoloader = require __DIR__.'\vendor\autoload.php';
use Symfony\Component\DomCrawler\Crawler;
$threadCount = 1;
$list = range(0,100);
$list = array_chunk($list, $threadCount);
foreach ($list as $line) {
$workers = [];
foreach (range(0,count($line)-1) as $i) {
$threadName = "Thread #".$i.": ";
$workers[$i] = new WorkerThreads($autoloader,$threadName,$line[$i]);
$workers[$i]->start();
}
foreach (range(0,count($line)-1) as $i) {
$workers[$i]->join();
}
}
class WorkerThreads extends Thread {
private $threadName;
private $num;
public function __construct(Composer\Autoload\ClassLoader $loader,$threadName,$num) {
$this->threadName = $threadName;
$this->num = $num;
$this->loader = $loader;
}
public function run() {
$this->loader->register();
if ($this->threadName && $this->num) {
$result = doThis($this->num);
printf('%sResult for number %s' . "\n", $this->threadName, $this->num);
}
}
}
function doThis($num){
$response = '<html><body><p class="message">Hello World!</p></body></html>';
$crawler = new Crawler($response);
$data = $crawler->filter('p')->text();
return $data;
}

Amazon Scraper Script works on XAMPP Windows but not PHP5 Cli on Linux

I'm trying to scrape Amazon ASIN codes using the below code:
<?php
class Scraper {
const BASE_URL = "http://www.amazon.com";
private $categoryFile = "";
private $outputFile = "";
private $catArray;
private $currentPage = NULL;
private $asin = array();
private $categoriesMatched = 0;
private $categoryProducts = array();
private $pagesMatched = 0;
private $totalPagesMatched = 0;
private $productsMatched = 0;
public function __construct($categoryFile, $outputFile) {
$this->categoryFile = $categoryFile;
$this->outputFile = $outputFile;
}
public function run() {
$this->readCategories($this->categoryFile);
$this->setupASINArray($this->asin);
$x = 1;
foreach ($this->catArray as $cat) {
$this->categoryProducts["$x"] = 0;
if ($this->currentPage == NULL) {
$this->currentPage = $cat;
$this->scrapeASIN($this->currentPage, $x);
$this->pagesMatched++;
}
if ($this->getNextPageLink($this->currentPage)) {
do {
// next page found
$this->pagesMatched++;
$this->scrapeASIN($this->currentPage, $x);
} while ($this->getNextPageLink($this->currentPage));
}
echo "Category complete: $this->pagesMatched Pages" . "\n";
$this->totalPagesMatched += $this->pagesMatched;
$this->pagesMatched = 0;
$this->writeASIN($this->outputFile, $x);
$x++;
$this->currentPage = NULL;
$this->categoriesMatched++;
}
$this->returnStats();
}
private function readCategories($categoryFile) {
$catArray = file($categoryFile, FILE_IGNORE_NEW_LINES);
$this->catArray = $catArray;
}
private function setupASINArray($asinArray) {
$x = 0;
foreach ($this->catArray as $cat) {
$asinArray["$x"][0] = "$cat";
$x++;
}
$this->asin = $asinArray;
}
private function getNextPageLink($currentPage) {
$document = new DOMDocument();
$html = file_get_contents($currentPage);
#$document->loadHTML($html);
$xpath = new DOMXPath($document);
$element = $xpath->query("//a[#id='pagnNextLink']/#href");
if ($element->length != 0) {
$this->currentPage = self::BASE_URL . $element->item(0)->value;
return true;
} else {
return false;
}
}
private function scrapeASIN($currentPage, $catNo) {
$html = file_get_contents($currentPage);
$regex = '~(?:www\.)?ama?zo?n\.(?:com|ca|co\.uk|co\.jp|de|fr)/(?:exec/obidos/ASIN/|o/|gp/product/|(?:(?:[^"\'/]*)/)?dp/|)(B[A-Z0-9]{9})(?:(?:/|\?|\#)(?:[^"\'\s]*))?~isx';
preg_match_all($regex, $html, $asin);
foreach ($asin[1] as $match) {
$this->asin[$catNo-1][] = $match;
}
}
private function writeASIN($outputFile, $catNo) {
$fh = fopen($outputFile, "a+");
$this->fixDupes($catNo);
$this->productsMatched += (count($this->asin[$catNo-1]) - 1);
$this->categoryProducts["$catNo"] = (count($this->asin[$catNo-1]) - 1);
flock($fh, LOCK_EX);
$x = 0;
foreach ($this->asin[$catNo-1] as $asin) {
fwrite($fh, "$asin" . "\n");
$x++;
}
flock($fh, LOCK_UN);
fclose($fh);
$x -= 1;
echo "$x ASIN codes written to file" . "\n";
}
private function fixDupes($catNo) {
$this->asin[$catNo-1] = array_unique($this->asin[$catNo-1], SORT_STRING);
}
public function returnStats() {
echo "Categories matched: " . $this->categoriesMatched . "\n";
echo "Pages parsed: " . $this->totalPagesMatched . "\n";
echo "Products parsed: " . $this->productsMatched . "\n";
echo "Category breakdown:" . "\n";
$x = 1;
foreach ($this->categoryProducts as $catProds) {
echo "Category $x had $catProds products" . "\n";
$x++;
}
}
}
$scraper = new Scraper($argv[1], $argv[2]);
$scraper->run();
?>
But it works fine on XAMPP on Windows but not on Linux. Any ideas as to why this may be? Sometimes it scrapes 0 ASIN's to file, sometimes it only scrapes 1 page in a category of 400+ pages. But the output/functionality is totally fine in Windows/XAMPP.
Any thoughts would be greatly appreciated!
Cheers
- Bryce
So try to change this way, just to avoid the error messages:
private function readCategories($categoryFile) {
if (file_exists($categoryFile)) {
$catArray = file($categoryFile, FILE_IGNORE_NEW_LINES);
$this->catArray = $catArray;
} else {
echo "File ".$categoryFile.' not exists!';
$this->catArray = array();
}
}

PHP Simple object oriented application

I am getting undefined variable for periods and subPeriods on the last line of this program. not sure what the problem is. Could it be my instances?
This is my first proper attempt at oop in PHP so i am sure i am doing something wrong.
$global_periods = 5;
$global_subperiods = 2;
$questionslist = array("q_1_1", "q_1_2", "q_2_1", "q_2_2", "q_3_1", "q_4_1", "q_5_1");
class User {
public $userId;
public $periods = array();
public function __construct($number)
{
$this->userId = $number;
}
public function addPeriod($pno)
{
$periods[] = new Period($pno);
}
}
class Period {
public $periodNo;
public $subPeriods = array();
public function __construct($number)
{
$this->periodNo = $number;
}
public function addSubPeriod($spno)
{
$subPeriods[] = new SubPeriod($spno);
}
}
class SubPeriod {
public $SubPeriodNo;
public $answers = array();
public function __construct($number)
{
$this->SubPeriodNo = $number;
}
public function addAnswer($answer)
{
$answers[] = new Answer($answer);
}
}
class Question {
public $answer;
public function __construct($ans)
{
$this->answer = $ans;
}
public function getAnswer()
{
echo $answer;
}
}
$userlist = array();
$sql = 'SELECT user_ref FROM _survey_1_as GROUP BY user_ref ORDER BY user_ref ASC';
$result = mysql_query($sql);
while ($row = mysql_fetch_array($result))
{
$userlist[] = new User($row['user_ref']);
}
for ($i = 0; $i >= count($userlist); $i++)
{
for ($x = 1; $x > $global_periods; $x++)
{
$userlist[i]->addPeriod($x);
for ($y = 1; $y > $global_subperiods; $y++)
{
$userlist[i]->$periods[x]->addSubPeriod($y);
foreach($questionslist as $aquestion)
{
$sql = 'SELECT ' . $questionNumber . ' FROM _survey_1_as WHERE user_ref = ' .
$i . ' AND answer_sub_period = ' . $y . ' AND answer_period = ' . $x .'';
$result = mysql_query($sql);
while ($row = mysql_fetch_array($result))
{
$userlist[i]->$periods[x]->$subPeriods[y]->addAnswer($row[$questionNumber]);
}
}
}
}
}
$userlist[3]->$periods[2]->$subPeriods[2]->getAnswer();
Remove all the $ signs behind the $userlist, you only need to define the first variable. You can't use dollar signs like this, this way, it will try get the value of the word after the $ sign and call that, but that variable doesn't exist.

OOP in PHP - object array iteration

I am trying to iterate through array of objects in PHP, but I can't figure it out. This is my code:
require_once("databaseConnect.php");
require_once("class/Ticket.php");
function showAll(){
$sql = "SELECT * FROM Ticket WHERE Status='1'";
$p = mysql_query($sql);
while ($row = mysql_fetch_object($p)){
$t = new Ticket($row->IDTicket, $row->IDUser, $row->TotalOdd, $row->PlacedBet, $row->PossibleWin, $row->Status, $row->Won, $row->Time);
$nizTiketa[] = $t;
}
return $nizTiketa;
}
$niz = showAll();
for ($i; $i<count($niz); $i++){
echo $niz[$i]->getIDTicket()."<br/>";
}
and this is class Ticket:
class Ticket {
private $IDTicket;
private $IDUser;
private $TotalOdd;
private $PlacedBet;
private $PossibleWin;
private $Status;
private $Won;
private $Time;
function Ticket($idTicket, $idUser, $totalOdd, $placedBet, $possibleWin, $status, $won, $time) {
$this->IDTicket = $idTicket;
$this->IDUser = $idUser;
$this->TotalOdd = $totalOdd;
$this->PlacedBet = $placedBet;
$this->PossibleWin = $possibleWin;
$this->Status = $status;
$this->Won = $won;
$this->Time = $time;
}
function getIDTicket(){
return $this->IDTicket;
}
function setIDTicket($idTicket){
$this->IDTicket = $idTicket;
}
.
.
.
I got error Call to a member function getIDTicket() on a non-object
How should it be done?
Couple of things I'd do here for sanity...
As mentioned by Joe, initialise your array before adding elements, eg
function showAll() {
$nizTiketa = array();
// ...
Either initialise your iteration counter $i to zero
for ($i = 0, $count = count($niz); $i < $count; $i++)
or more simply, use foreach
foreach ($niz as $ticket) {
echo $ticket->getIDTicket(), "<br/>";
}

Categories